X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=uip%2Fpost.c;h=09ca15e54e6bb1e580654cf8c8e738464023577d;hb=59ae7b80f479fd5d406cd549f7740849bdc76dc0;hp=20482282fa0c0e6f86074244368b0e78d8877fc3;hpb=3a84d814004fd4557bf4f44952648e9e69bd22a8;p=mmh diff --git a/uip/post.c b/uip/post.c index 2048228..09ca15e 100644 --- a/uip/post.c +++ b/uip/post.c @@ -20,7 +20,6 @@ #include #include -#include #include #ifdef HAVE_SYS_TIME_H @@ -28,9 +27,7 @@ #endif #include -#ifdef SMTPMTS -# include -#endif +#include #ifndef CYRUS_SASL # define SASLminc(a) (a) @@ -46,8 +43,6 @@ #define FCCS 10 /* max number of fccs allowed */ -#define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : c) - /* In the following array of structures, the numeric second field of the structures (minchars) is apparently used like this: @@ -104,46 +99,42 @@ static struct swit switches[] = { { "dashstuffing", -12 }, /* should we dashstuff BCC messages? */ #define NBITSTUFFSW 23 { "nodashstuffing", -14 }, -#define MAILSW 24 - { "mail", -4 }, /* specify MAIL smtp mode */ -#define SAMLSW 25 - { "saml", -4 }, /* specify SAML smtp mode */ -#define SENDSW 26 - { "send", -4 }, /* specify SEND smtp mode */ -#define SOMLSW 27 - { "soml", -4 }, /* specify SOML smtp mode */ -#define ANNOSW 28 +#define ANNOSW 24 { "idanno number", -6 }, /* interface from send */ -#define DLVRSW 29 - { "deliver address-list", -7 }, -#define CLIESW 30 +#define CLIESW 25 { "client host", -6 }, -#define SERVSW 31 - { "server host", -6 }, /* specify alternate SMTP server */ -#define SNOOPSW 32 +#define SERVSW 26 + { "server host", 6 }, /* specify alternate SMTP server */ +#define SNOOPSW 27 { "snoop", -5 }, /* snoop the SMTP transaction */ -#define FILLSW 33 - { "fill-in file", -7 }, -#define FILLUSW 34 - { "fill-up", -7 }, -#define PARTSW 35 +#define PARTSW 28 { "partno", -6 }, -#define QUEUESW 36 +#define QUEUESW 29 { "queued", -6 }, -#define SASLSW 37 +#define SASLSW 30 { "sasl", SASLminc(-4) }, -#define SASLMECHSW 38 +#define NOSASLSW 31 + { "nosasl", SASLminc(-6) }, +#define SASLMXSSFSW 32 + { "saslmaxssf", SASLminc(-10) }, +#define SASLMECHSW 33 { "saslmech", SASLminc(-5) }, -#define USERSW 39 +#define USERSW 34 { "user", SASLminc(-4) }, -#define PORTSW 40 +#define PORTSW 35 { "port server port name/number", 4 }, -#define TLSSW 41 +#define TLSSW 36 { "tls", TLSminc(-3) }, -#define FILEPROCSW 42 +#define NTLSSW 37 + { "notls", TLSminc(-5) }, +#define FILEPROCSW 38 { "fileproc", -4 }, -#define MHLPROCSW 43 +#define MHLPROCSW 39 { "mhlproc", -3 }, +#define MTSSW 40 + { "mts smtp|sendmail/smtp|sendmail/pipe", 2 }, +#define MESSAGEIDSW 41 + { "messageid localname|random", 2 }, { NULL, 0 } }; @@ -157,50 +148,56 @@ struct headers { /* * flags for headers->flags */ -#define HNOP 0x0000 /* just used to keep .set around */ -#define HBAD 0x0001 /* bad header - don't let it through */ -#define HADR 0x0002 /* header has an address field */ -#define HSUB 0x0004 /* Subject: header */ -#define HTRY 0x0008 /* try to send to addrs on header */ -#define HBCC 0x0010 /* don't output this header */ -#define HMNG 0x0020 /* munge this header */ -#define HNGR 0x0040 /* no groups allowed in this header */ -#define HFCC 0x0080 /* FCC: type header */ -#define HNIL 0x0100 /* okay for this header not to have addrs */ -#define HIGN 0x0200 /* ignore this header */ -#define HDCC 0x0400 /* another undocumented feature */ +#define HNOP 0x0000 /* just used to keep .set around */ +#define HBAD 0x0001 /* bad header - don't let it through */ +#define HADR 0x0002 /* header has an address field */ +#define HSUB 0x0004 /* Subject: header */ +#define HTRY 0x0008 /* try to send to addrs on header */ +#define HBCC 0x0010 /* don't output this header, unless MTS_SENDMAIL_PIPE */ +#define HMNG 0x0020 /* munge this header */ +#define HNGR 0x0040 /* no groups allowed in this header */ +#define HFCC 0x0080 /* FCC: type header */ +#define HNIL 0x0100 /* okay for this header not to have addrs */ +#define HIGN 0x0200 /* ignore this header */ +#define HDCC 0x0400 /* another undocumented feature */ +#define HONE 0x0800 /* Only (zero or) one address allowed */ +#define HEFM 0x1000 /* Envelope-From: header */ /* * flags for headers->set */ -#define MFRM 0x0001 /* we've seen a From: */ -#define MDAT 0x0002 /* we've seen a Date: */ -#define MRFM 0x0004 /* we've seen a Resent-From: */ -#define MVIS 0x0008 /* we've seen sighted addrs */ -#define MINV 0x0010 /* we've seen blind addrs */ +#define MFRM 0x0001 /* we've seen a From: */ +#define MDAT 0x0002 /* we've seen a Date: */ +#define MRFM 0x0004 /* we've seen a Resent-From: */ +#define MVIS 0x0008 /* we've seen sighted addrs */ +#define MINV 0x0010 /* we've seen blind addrs */ +#define MSND 0x0020 /* we've seen a Sender: */ +#define MRSN 0x0040 /* We've seen a Resent-Sendr:*/ +#define MEFM 0x0080 /* We've seen Envelope-From: */ static struct headers NHeaders[] = { - { "Return-Path", HBAD, 0 }, - { "Received", HBAD, 0 }, - { "Reply-To", HADR|HNGR, 0 }, - { "From", HADR|HNGR, MFRM }, - { "Sender", HADR|HBAD, 0 }, - { "Date", HBAD, 0 }, - { "Subject", HSUB, 0 }, - { "To", HADR|HTRY, MVIS }, - { "cc", HADR|HTRY, MVIS }, - { "Bcc", HADR|HTRY|HBCC|HNIL, MINV }, - { "Dcc", HADR|HTRY|HDCC|HNIL, MVIS }, /* sorta cc & bcc combined */ - { "Message-ID", HBAD, 0 }, - { "Fcc", HFCC, 0 }, - { NULL, 0, 0 } + { "Return-Path", HBAD, 0 }, + { "Received", HBAD, 0 }, + { "Reply-To", HADR|HNGR, 0 }, + { "From", HADR|HNGR, MFRM }, + { "Sender", HADR|HNGR|HONE, MSND }, + { "Date", HBAD, 0 }, + { "Subject", HSUB, 0 }, + { "To", HADR|HTRY, MVIS }, + { "cc", HADR|HTRY, MVIS }, + { "Bcc", HADR|HTRY|HBCC|HNIL, MINV }, + { "Dcc", HADR|HTRY|HDCC|HNIL, MVIS }, /* sorta cc & bcc combined */ + { "Message-ID", HBAD, 0 }, + { "Fcc", HFCC, 0 }, + { "Envelope-From", HADR|HONE|HEFM, MEFM }, + { NULL, 0, 0 } }; static struct headers RHeaders[] = { { "Resent-Reply-To", HADR|HNGR, 0 }, { "Resent-From", HADR|HNGR, MRFM }, - { "Resent-Sender", HADR|HBAD, 0 }, + { "Resent-Sender", HADR|HNGR, MRSN }, { "Resent-Date", HBAD, 0 }, { "Resent-Subject", HSUB, 0 }, { "Resent-To", HADR|HTRY, MVIS }, @@ -210,12 +207,13 @@ static struct headers RHeaders[] = { { "Resent-Fcc", HFCC, 0 }, { "Reply-To", HADR, 0 }, { "From", HADR|HNGR, MFRM }, - { "Sender", HADR|HNGR, 0 }, + { "Sender", HADR|HNGR, MSND }, { "Date", HNOP, MDAT }, { "To", HADR|HNIL, 0 }, { "cc", HADR|HNIL, 0 }, { "Bcc", HADR|HTRY|HBCC|HNIL, 0 }, { "Fcc", HIGN, 0 }, + { "Envelope-From", HADR|HONE|HEFM, MEFM }, { NULL, 0, 0 } }; @@ -240,10 +238,13 @@ static int checksw = 0; /* whom -check */ static int linepos=0; /* putadr()'s position on the line */ static int nameoutput=0; /* putadr() has output header name */ static int sasl=0; /* Use SASL auth for SMTP */ +static int saslssf=-1; /* Our maximum SSF for SASL */ static char *saslmech=NULL; /* Force use of particular SASL mech */ static char *user=NULL; /* Authenticate as this user */ static char *port="smtp"; /* Name of server port for SMTP */ static int tls=0; /* Use TLS for encryption */ +static int fromcount=0; /* Count of addresses on From: header */ +static int seensender=0; /* Have we seen a Sender: header? */ static unsigned msgflags = 0; /* what we've seen */ @@ -259,6 +260,9 @@ static char tmpfil[BUFSIZ]; static char bccfil[BUFSIZ]; static char from[BUFSIZ]; /* my network address */ +static char sender[BUFSIZ]; /* my Sender: header */ +static char efrom[BUFSIZ]; /* my Envelope-From: header */ +static char fullfrom[BUFSIZ]; /* full contents of From header */ static char signature[BUFSIZ]; /* my signature */ static char *filter = NULL; /* the filter for BCC'ing */ static char *subject = NULL; /* the subject field for BCC'ing */ @@ -266,29 +270,22 @@ static char *fccfold[FCCS]; /* foldernames for FCC'ing */ static struct headers *hdrtab; /* table for the message we're doing */ -static struct mailname localaddrs={NULL}; /* local addrs */ -static struct mailname netaddrs={NULL}; /* network addrs */ -static struct mailname uuaddrs={NULL}; /* uucp addrs */ -static struct mailname tmpaddrs={NULL}; /* temporary queue */ +static struct mailname localaddrs; /* local addrs */ +static struct mailname netaddrs; /* network addrs */ +static struct mailname uuaddrs; /* uucp addrs */ +static struct mailname tmpaddrs; /* temporary queue */ -#ifdef SMTPMTS static int snoop = 0; -static int smtpmode = S_MAIL; static char *clientsw = NULL; static char *serversw = NULL; extern struct smtp sm_reply; -#endif /* SMTPMTS */ static char prefix[] = "----- =_aaaaaaaaaa"; -static int fill_up = 0; -static char *fill_in = NULL; static char *partno = NULL; static int queued = 0; -extern boolean draft_from_masquerading; /* defined in mts.c */ - /* * static prototypes */ @@ -304,14 +301,14 @@ static void anno (void); static int annoaux (struct mailname *); static void insert_fcc (struct headers *, unsigned char *); static void make_bcc_file (int); -static void verify_all_addresses (int); +static void verify_all_addresses (int, char *); static void chkadr (void); static void sigon (void); static void sigoff (void); static void p_refile (char *); static void fcc (char *, char *); static void die (char *, char *, ...); -static void post (char *, int, int); +static void post (char *, int, int, char *); static void do_text (char *file, int fd); static void do_an_address (struct mailname *, int); static void do_addresses (int, int); @@ -322,7 +319,7 @@ int main (int argc, char **argv) { int state, compnum, dashstuff = 0; - char *cp, *msg = NULL, **argp, **arguments; + char *cp, *msg = NULL, **argp, **arguments, *envelope; char buf[BUFSIZ], name[NAMESZ]; FILE *in, *out; @@ -351,10 +348,10 @@ main (int argc, char **argv) case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] file", invo_name); print_help (buf, switches, 0); - done (1); + done (0); case VERSIONSW: print_version(invo_name); - done (1); + done (0); case LIBSW: if (!(cp = *argp++) || *cp == '-') @@ -457,33 +454,6 @@ main (int argc, char **argv) adios (NULL, "bad argument %s %s", argp[-2], cp); continue; - case DLVRSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - -#ifndef SMTPMTS - case CLIESW: - case SERVSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - - case SNOOPSW: - continue; -#else /* SMTPMTS */ - case MAILSW: - smtpmode = S_MAIL; - continue; - case SAMLSW: - smtpmode = S_SAML; - continue; - case SOMLSW: - smtpmode = S_SOML; - continue; - case SENDSW: - smtpmode = S_SEND; - continue; case CLIESW: if (!(clientsw = *argp++) || *clientsw == '-') adios (NULL, "missing argument to %s", argp[-2]); @@ -495,15 +465,7 @@ main (int argc, char **argv) case SNOOPSW: snoop++; continue; -#endif /* SMTPMTS */ - case FILLSW: - if (!(fill_in = *argp++) || *fill_in == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - case FILLUSW: - fill_up++; - continue; case PARTSW: if (!(partno = *argp++) || *partno == '-') adios (NULL, "missing argument to %s", argp[-2]); @@ -516,6 +478,16 @@ main (int argc, char **argv) case SASLSW: sasl++; continue; + + case NOSASLSW: + sasl = 0; + continue; + + case SASLMXSSFSW: + if (!(cp = *argp++) || *cp == '-') + adios (NULL, "missing argument to %s", argp[-2]); + saslssf = atoi(cp); + continue; case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') @@ -536,6 +508,10 @@ main (int argc, char **argv) tls++; continue; + case NTLSSW: + tls = 0; + continue; + case FILEPROCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); @@ -547,6 +523,19 @@ main (int argc, char **argv) adios (NULL, "missing argument to %s", argp[-2]); mhlproc = cp; continue; + + case MTSSW: + if (!(cp = *argp++) || *cp == '-') + adios (NULL, "missing argument to %s", argp[-2]); + save_mts_method (cp); + continue; + + case MESSAGEIDSW: + if (!(cp = *argp++) || *cp == '-') + adios (NULL, "missing argument to %s", argp[-2]); + if (save_message_id_style (cp) != 0) + adios (NULL, "unsupported messageid \"%s\"", cp); + continue; } } if (msg) @@ -572,7 +561,7 @@ main (int argc, char **argv) discard (out = stdout); /* XXX: reference discard() to help loader */ } else { if (whomsw) { - if ((out = fopen (fill_in ? fill_in : "/dev/null", "w")) == NULL) + if ((out = fopen ("/dev/null", "w")) == NULL) adios ("/dev/null", "unable to open"); } else { char *cp = m_mktemp(m_maildir(invo_name), NULL, &out); @@ -610,7 +599,7 @@ main (int argc, char **argv) case BODY: case BODYEOF: finish_headers (out); - if (whomsw && !fill_in) + if (whomsw) break; fprintf (out, "\n%s", buf); while (state == BODY) { @@ -644,23 +633,46 @@ main (int argc, char **argv) fclose (out); } + /* + * Here's how we decide which address to use as the envelope-from + * address for SMTP. + * + * - If we were given an Envelope-From header, use that. + * - If we were given a Sender: address, use that. + * - Otherwise, use the address on the From: line + */ + + if (msgflags & MEFM) { + envelope = efrom; + } else if (seensender) { + envelope = sender; + } else { + envelope = from; + } + /* If we are doing a "whom" check */ if (whomsw) { - if (!fill_up) - verify_all_addresses (1); + /* This won't work with MTS_SENDMAIL_PIPE. */ + verify_all_addresses (1, envelope); done (0); } if (msgflags & MINV) { make_bcc_file (dashstuff); if (msgflags & MVIS) { - verify_all_addresses (verbose); - post (tmpfil, 0, verbose); + if (sm_mts != MTS_SENDMAIL_PIPE) { + /* It would be nice to have support to call + verify_all_addresses with MTS_SENDMAIL_PIPE, but + that might require running sendmail as root. Note + that spost didn't verify addresses. */ + verify_all_addresses (verbose, envelope); + } + post (tmpfil, 0, verbose, envelope); } - post (bccfil, 1, verbose); + post (bccfil, 1, verbose, envelope); unlink (bccfil); } else { - post (tmpfil, 0, isatty (1)); + post (tmpfil, 0, isatty (1), envelope); } p_refile (tmpfil); @@ -697,23 +709,31 @@ putfmt (char *name, char *str, FILE *out) } if ((i = get_header (name, hdrtab)) == NOTOK) { - fprintf (out, "%s: %s", name, str); + if (strncasecmp (name, "nmh-", 4)) { + fprintf (out, "%s: %s", name, str); + } else { + /* Filter out all Nmh-* headers, because Norm asked. They + should never have reached this point. Warn about any + that are non-empty. */ + if (strcmp (str, "\n")) { + char *newline = strchr (str, '\n'); + if (newline) *newline = '\0'; + if (! whomsw) { + advise (NULL, "ignoring header line -- %s: %s", name, str); + } + } + } + return; } hdr = &hdrtab[i]; if (hdr->flags & HIGN) { - if (fill_in) - fprintf (out, "%s: %s", name, str); return; } if (hdr->flags & HBAD) { - if (fill_in) - fprintf (out, "%s: %s", name, str); - else { - advise (NULL, "illegal header line -- %s:", name); - badmsg++; - } + advise (NULL, "illegal header line -- %s:", name); + badmsg++; return; } msgflags |= (hdr->set & ~(MVIS | MINV)); @@ -721,11 +741,6 @@ putfmt (char *name, char *str, FILE *out) if (hdr->flags & HSUB) subject = subject ? add (str, add ("\t", subject)) : getcpy (str); if (hdr->flags & HFCC) { - if (fill_in) { - fprintf (out, "%s: %s", name, str); - return; - } - if ((cp = strrchr(str, '\n'))) *cp = 0; for (cp = pp = str; (cp = strchr(pp, ',')); pp = cp) { @@ -760,6 +775,14 @@ putfmt (char *name, char *str, FILE *out) if (hdr->flags & HNIL) fprintf (out, "%s: %s", name, str); else { + /* + * Sender (or Resent-Sender) can have only one address + */ + if ((msgstate == RESENT) ? (hdr->set & MRSN) + : (hdr->set & MSND)) { + advise (NULL, "%s: field requires one address", name); + badmsg++; + } #ifdef notdef advise (NULL, "%s: field requires at least one address", name); badmsg++; @@ -768,9 +791,15 @@ putfmt (char *name, char *str, FILE *out) return; } + if (count > 1 && (hdr->flags & HONE)) { + advise (NULL, "%s: field only permits one address", name); + badmsg++; + return; + } + nameoutput = linepos = 0; snprintf (namep, sizeof(namep), "%s%s", - !fill_in && (hdr->flags & HMNG) ? "Original-" : "", name); + (hdr->flags & HMNG) ? "Original-" : "", name); for (grp = 0, mp = tmpaddrs.m_next; mp; mp = np) if (mp->m_nohost) { /* also used to test (hdr->flags & HTRY) */ @@ -786,17 +815,37 @@ putfmt (char *name, char *str, FILE *out) continue; } - if (draft_from_masquerading && ((msgstate == RESENT) - ? (hdr->set & MRFM) - : (hdr->set & MFRM))) - /* The user manually specified a [Resent-]From: address in - their draft and the "masquerade:" line in mts.conf - doesn't contain "draft_from", so we'll set things up to - use the actual email address embedded in the draft - [Resent-]From: (after alias substitution, and without the - GECOS full name or angle brackets) as the envelope - From:. */ + /* + * If it's a From: or Resent-From: header, save the address + * for later possible use (as the envelope address for SMTP) + */ + + if ((msgstate == RESENT) ? (hdr->set & MRFM) + : (hdr->set & MFRM)) { strncpy(from, auxformat(mp, 0), sizeof(from) - 1); + from[sizeof(from) - 1] = '\0'; + fromcount = count; + } + + /* + * Also save the Sender: or Resent-Sender: header as well + */ + + if ((msgstate == RESENT) ? (hdr->set & MRSN) + : (hdr->set & MSND)) { + strncpy(sender, auxformat(mp, 0), sizeof(sender) - 1); + sender[sizeof(sender) - 1] = '\0'; + seensender++; + } + + /* + * ALSO ... save Envelope-From + */ + + if (hdr->set & MEFM) { + strncpy(efrom, auxformat(mp, 0), sizeof(efrom) - 1); + efrom[sizeof(efrom) - 1] = '\0'; + } if (hdr->flags & HBCC) mp->m_bcc++; @@ -805,8 +854,22 @@ putfmt (char *name, char *str, FILE *out) else if (mp->m_gname) putgrp (namep, mp->m_gname, out, hdr->flags); - if (mp->m_ingrp) + if (mp->m_ingrp) { + if (sm_mts == MTS_SENDMAIL_PIPE) { + /* Catch this before sendmail chokes with: + "553 List:; syntax illegal for recipient + addresses". + If we wanted to, we could expand out blind + aliases and put them in Bcc:, but then + they'd have the Blind-Carbon-Copy + indication. */ + adios (NULL, + "blind aliases not compatible with" + " sendmail/pipe"); + } + grp++; + } if (putadr (namep, qp, mp, out, hdr->flags)) msgflags |= (hdr->set & (MVIS | MINV)); else @@ -818,17 +881,37 @@ putfmt (char *name, char *str, FILE *out) } else { /* Address includes a host, so no alias substitution is needed. */ - if (draft_from_masquerading && ((msgstate == RESENT) - ? (hdr->set & MRFM) - : (hdr->set & MFRM))) - /* The user manually specified a [Resent-]From: address in - their draft and the "masquerade:" line in mts.conf - doesn't contain "draft_from", so we'll set things up to - use the actual email address embedded in the draft - [Resent-]From: (after alias substitution, and without the - GECOS full name or angle brackets) as the envelope - From:. */ + + /* + * If it's a From: or Resent-From header, save the address + * for later possible use (as the envelope address for SMTP) + */ + + if ((msgstate == RESENT) ? (hdr->set & MRFM) + : (hdr->set & MFRM)) { strncpy(from, auxformat(mp, 0), sizeof(from) - 1); + fromcount = count; + } + + /* + * Also save the Sender: header as well + */ + + if ((msgstate == RESENT) ? (hdr->set & MRSN) + : (hdr->set & MSND)) { + strncpy(sender, auxformat(mp, 0), sizeof(sender) - 1); + sender[sizeof(sender) - 1] = '\0'; + seensender++; + } + + /* + * ALSO ... save Envelope-From + */ + + if (hdr->set & MEFM) { + strncpy(efrom, auxformat(mp, 0), sizeof(efrom) - 1); + efrom[sizeof(efrom) - 1] = '\0'; + } if (hdr->flags & HBCC) mp->m_bcc++; @@ -846,13 +929,28 @@ putfmt (char *name, char *str, FILE *out) mnfree (mp); } + /* + * If this is a From:/Resent-From: header, save the full thing for + * later in case we need it for use when constructing a Bcc draft message + */ + + if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { + strncpy(fullfrom, str, sizeof(fullfrom)); + fullfrom[sizeof(fullfrom) - 1] = 0; + /* + * Strip off any trailing newlines + */ + + while (strlen(fullfrom) > 0 && fullfrom[strlen(fullfrom) - 1] == '\n') { + fullfrom[strlen(fullfrom) - 1] = '\0'; + } + } + if (grp > 0 && (hdr->flags & HNGR)) { advise (NULL, "%s: field does not allow groups", name); badmsg++; } if (linepos) { - if (fill_in && grp > 0) - putc (';', out); putc ('\n', out); } } @@ -862,23 +960,26 @@ static void start_headers (void) { unsigned char *cp; - char myhost[BUFSIZ], sigbuf[BUFSIZ]; + char sigbuf[BUFSIZ]; struct mailname *mp; myuid = getuid (); mygid = getgid (); time (&tclock); - strncpy (from, adrsprintf (NULL, NULL), sizeof(from)); - strncpy (myhost, LocalName (), sizeof(myhost)); + /* + * Probably not necessary, but just in case ... + */ - for (cp = myhost; *cp; cp++) - *cp = uptolow (*cp); + from[0] = '\0'; + efrom[0] = '\0'; + sender[0] = '\0'; + fullfrom[0] = '\0'; if ((cp = getfullname ()) && *cp) { strncpy (sigbuf, cp, sizeof(sigbuf)); snprintf (signature, sizeof(signature), "%s <%s>", - sigbuf, adrsprintf (NULL, NULL)); + sigbuf, getlocaladdr()); if ((cp = getname (signature)) == NULL) adios (NULL, "getname () failed -- you lose extraordinarily big"); if ((mp = getm (cp, NULL, 0, AD_HOST, NULL)) == NULL) @@ -887,7 +988,7 @@ start_headers (void) while (getname ("")) continue; } else { - strncpy (signature, adrsprintf (NULL, NULL), sizeof(signature)); + strncpy (signature, getlocaladdr(), sizeof(signature)); } } @@ -903,28 +1004,46 @@ finish_headers (FILE *out) { switch (msgstate) { case NORMAL: - if (whomsw && !fill_up) + if (!(msgflags & MFRM)) { + /* + * A From: header is now required in the draft. + */ + advise (NULL, "message has no From: header"); + advise (NULL, "See default components files for examples"); + badmsg++; break; + } - fprintf (out, "Date: %s\n", dtime (&tclock, 0)); - if (msgid) - fprintf (out, "Message-ID: <%d.%ld@%s>\n", - (int) getpid (), (long) tclock, LocalName ()); - if (msgflags & MFRM) { - /* There was already a From: in the draft. Don't add one. */ - if (!draft_from_masquerading) - /* mts.conf didn't contain "masquerade:[...]draft_from[...]" - so we'll reveal the user's actual account@thismachine - address in a Sender: header (and use it as the envelope - From: later). */ - fprintf (out, "Sender: %s\n", from); + if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) { + advise (NULL, "A Sender: or Envelope-From: header is required " + "with multiple\nFrom: addresses"); + badmsg++; + break; } - else - /* Construct a From: header. */ - fprintf (out, "From: %s\n", signature); + if (whomsw) break; + fprintf (out, "Date: %s\n", dtime (&tclock, 0)); + if (msgid) + fprintf (out, "Message-ID: %s\n", message_id (tclock, 0)); + /* + * If we have multiple From: addresses, make sure we have an + * Sender: header. If we don't have one, then generate one + * from Envelope-From: (which in this case, cannot be blank) + */ + + if (fromcount > 1 && seensender == 0) { + if (efrom[0] == '\0') { + advise (NULL, "Envelope-From cannot be blank when there " + "is multiple From: addresses\nand no Sender: " + "header"); + badmsg++; + } else { + fprintf (out, "Sender: %s\n", efrom); + } + } + if (!(msgflags & MVIS)) fprintf (out, "Bcc: Blind Distribution List: ;\n"); break; @@ -938,27 +1057,43 @@ finish_headers (FILE *out) advise (NULL, "message has no From: header"); badmsg++; } - if (whomsw && !fill_up) + if (!(msgflags & MRFM)) { + advise (NULL, "message has no Resent-From: header"); + advise (NULL, "See default components files for examples"); + badmsg++; + break; + } + if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) { + advise (NULL, "A Resent-Sender: or Envelope-From: header is " + "required with multiple\nResent-From: addresses"); + badmsg++; + break; + } + + if (whomsw) break; fprintf (out, "Resent-Date: %s\n", dtime (&tclock, 0)); if (msgid) - fprintf (out, "Resent-Message-ID: <%d.%ld@%s>\n", - (int) getpid (), (long) tclock, LocalName ()); - if (msgflags & MRFM) { - /* There was already a Resent-From: in draft. Don't add one. */ - if (!draft_from_masquerading) - /* mts.conf didn't contain "masquerade:[...]draft_from[...]" - so we'll reveal the user's actual account@thismachine - address in a Sender: header (and use it as the envelope - From: later). */ - fprintf (out, "Resent-Sender: %s\n", from); + fprintf (out, "Resent-Message-ID: %s\n", + message_id (tclock, 0)); + /* + * If we have multiple Resent-From: addresses, make sure we have an + * Resent-Sender: header. If we don't have one, then generate one + * from Envelope-From (which in this case, cannot be blank) + */ + + if (fromcount > 1 && seensender == 0) { + if (efrom[0] == '\0') { + advise (NULL, "Envelope-From cannot be blank when there " + "is multiple Resent-From: addresses and no " + "Resent-Sender: header"); + badmsg++; + } else { + fprintf (out, "Resent-Sender: %s\n", efrom); + } } - else - /* Construct a Resent-From: header. */ - fprintf (out, "Resent-From: %s\n", signature); - if (whomsw) - break; + if (!(msgflags & MVIS)) fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n"); break; @@ -993,7 +1128,8 @@ putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flag if (mp->m_mbox == NULL || ((flags & HTRY) && !insert (mp))) return 0; - if ((!fill_in && (flags & (HBCC | HDCC))) || mp->m_ingrp) + if (sm_mts != MTS_SENDMAIL_PIPE && + ((flags & (HBCC | HDCC | HEFM)) || mp->m_ingrp)) return 1; if (!nameoutput) { @@ -1004,7 +1140,7 @@ putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flag if (*aka && mp->m_type != UUCPHOST && !mp->m_pers) mp->m_pers = getcpy (aka); if (format) { - if (mp->m_gname && !fill_in) { + if (mp->m_gname) { snprintf (buffer, sizeof(buffer), "%s;", mp->m_gname); cp = buffer; } else { @@ -1037,17 +1173,15 @@ putgrp (char *name, char *group, FILE *out, unsigned int flags) int len; char *cp; - if (!fill_in && (flags & HBCC)) + if (sm_mts != MTS_SENDMAIL_PIPE && (flags & HBCC)) return; if (!nameoutput) { fprintf (out, "%s: ", name); linepos += (nameoutput = strlen (name) + 2); - if (fill_in) - linepos -= strlen (group); } - cp = fill_in ? group : concat (group, ";", NULL); + cp = concat (group, ";", NULL); len = strlen (cp); if (linepos > nameoutput) { @@ -1192,25 +1326,12 @@ make_bcc_file (int dashstuff) tfile = m_mktemp2(NULL, "bccs", NULL, &out); if (tfile == NULL) adios("bcc", "unable to create temporary file"); - chmod (bccfil, 0600); strncpy (bccfil, tfile, sizeof(bccfil)); + fprintf (out, "From: %s\n", fullfrom); fprintf (out, "Date: %s\n", dtime (&tclock, 0)); if (msgid) - fprintf (out, "Message-ID: <%d.%ld@%s>\n", - (int) getpid (), (long) tclock, LocalName ()); - if (msgflags & MFRM) { - /* There was already a From: in the draft. Don't add one. */ - if (!draft_from_masquerading) - /* mts.conf didn't contain "masquerade:[...]draft_from[...]" - so we'll reveal the user's actual account@thismachine - address in a Sender: header (and use it as the envelope - From: later). */ - fprintf (out, "Sender: %s\n", from); - } - else - /* Construct a From: header. */ - fprintf (out, "From: %s\n", signature); + fprintf (out, "Message-ID: %s\n", message_id (tclock, 0)); if (subject) fprintf (out, "Subject: %s", subject); fprintf (out, "BCC:\n"); @@ -1396,10 +1517,8 @@ do_addresses (int bccque, int talk) chkadr (); -#ifdef SMTPMTS if (rp_isbad (retval = sm_waend ())) die (NULL, "problem ending addresses; %s", rp_string (retval)); -#endif /* SMTPMTS */ } @@ -1412,15 +1531,13 @@ do_addresses (int bccque, int talk) * SENDMAIL/SMTP routines */ -#ifdef SMTPMTS - static void -post (char *file, int bccque, int talk) +post (char *file, int bccque, int talk, char *envelope) { - int fd, onex; - int retval; + int fd; + int retval, i; + pid_t child_id; - onex = !(msgflags & MINV) || bccque; if (verbose) { if (msgflags & MINV) printf (" -- Posting for %s Recipients --\n", @@ -1431,38 +1548,71 @@ post (char *file, int bccque, int talk) sigon (); - if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, verbose, - snoop, onex, queued, sasl, saslmech, - user, tls)) - || rp_isbad (retval = sm_winit (smtpmode, from))) - die (NULL, "problem initializing server; %s", rp_string (retval)); - - do_addresses (bccque, talk && verbose); - if ((fd = open (file, O_RDONLY)) == NOTOK) - die (file, "unable to re-open"); - do_text (file, fd); - close (fd); - fflush (stdout); + if (sm_mts == MTS_SENDMAIL_PIPE) { + char *sargv[16], **argp; - sm_end (onex ? OK : DONE); - sigoff (); + for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) + sleep (5); + switch (child_id) { + case NOTOK: + adios ("fork", "unable to"); - if (verbose) { - if (msgflags & MINV) - printf (" -- %s Recipient Copies Posted --\n", - bccque ? "Blind" : "Sighted"); - else - printf (" -- Recipient Copies Posted --\n"); - } + case OK: + if (freopen( file, "r", stdin) == NULL) { + adios (file, "can't reopen for sendmail"); + } - fflush (stdout); + argp = sargv; + *argp++ = "sendmail"; + *argp++ = "-t"; /* read msg for recipients */ + *argp++ = "-i"; /* don't stop on "." */ + if (whomsw) + *argp++ = "-bv"; + if (snoop) + *argp++ = "-v"; + *argp = NULL; + + execv (sendmail, sargv); + adios (sendmail, "can't exec"); + + default: + pidXwait (child_id, NULL); + break; + } + } else { + if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, + verbose, snoop, queued, sasl, + saslssf, saslmech, user, tls)) || + rp_isbad (retval = sm_winit (envelope))) + die (NULL, "problem initializing server; %s", rp_string (retval)); + + do_addresses (bccque, talk && verbose); + if ((fd = open (file, O_RDONLY)) == NOTOK) + die (file, "unable to re-open"); + do_text (file, fd); + close (fd); + fflush (stdout); + + sm_end (!(msgflags & MINV) || bccque ? OK : DONE); + sigoff (); + + if (verbose) { + if (msgflags & MINV) + printf (" -- %s Recipient Copies Posted --\n", + bccque ? "Blind" : "Sighted"); + else + printf (" -- Recipient Copies Posted --\n"); + } + + fflush (stdout); + } } /* Address Verification */ static void -verify_all_addresses (int talk) +verify_all_addresses (int talk, char *envelope) { int retval; struct mailname *lp; @@ -1471,9 +1621,9 @@ verify_all_addresses (int talk) if (!whomsw || checksw) if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, - verbose, snoop, 0, queued, sasl, - saslmech, user, tls)) - || rp_isbad (retval = sm_winit (smtpmode, from))) + verbose, snoop, queued, sasl, + saslssf, saslmech, user, tls)) + || rp_isbad (retval = sm_winit (envelope))) die (NULL, "problem initializing server; %s", rp_string (retval)); if (talk && !whomsw) @@ -1598,8 +1748,6 @@ do_text (char *file, int fd) } } -#endif /* SMTPMTS */ - /* * SIGNAL HANDLING @@ -1614,10 +1762,8 @@ sigser (int i) if (msgflags & MINV) unlink (bccfil); -#ifdef SMTPMTS if (!whomsw || checksw) sm_end (NOTOK); -#endif /* SMTPMTS */ done (1); } @@ -1733,10 +1879,8 @@ die (char *what, char *fmt, ...) if (msgflags & MINV) unlink (bccfil); -#ifdef SMTPMTS if (!whomsw || checksw) sm_end (NOTOK); -#endif /* SMTPMTS */ va_start(ap, fmt); advertise (what, NULL, fmt, ap);