/*
* post.c -- enter messages into the mail transport system
*
- * $Id$
+ * This code is Copyright (c) 2002, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
*/
#include <h/mh.h>
#include <h/aliasbr.h>
#include <h/dropsbr.h>
#include <h/mime.h>
+#include <h/utils.h>
-#include <zotnet/tws/tws.h>
-#include <zotnet/mts/mts.h>
+#include <h/tws.h>
+#include <h/mts.h>
#include <errno.h>
-#include <setjmp.h>
#include <signal.h>
-#ifdef TIME_WITH_SYS_TIME
+#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef TM_IN_SYS_TIME
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
+#include <time.h>
-#ifdef MMDFMTS
-# include <mts/mmdf/util.h>
-# include <mts/mmdf/mmdf.h>
-#endif
+#include <mts/smtp/smtp.h>
-/*
- * Currently smtp and sendmail use
- * the same interface for posting.
- */
-#ifdef SMTPMTS
-# define SENDMTS
-#endif
+#ifndef CYRUS_SASL
+# define SASLminc(a) (a)
+#else /* CYRUS_SASL */
+# define SASLminc(a) 0
+#endif /* CYRUS_SASL */
-#ifdef SENDMTS
-# include <mts/smtp/smtp.h>
-#endif
-
-#ifndef MMDFMTS
-# define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : (c))
-#endif
+#ifndef TLS_SUPPORT
+# define TLSminc(a) (a)
+#else /* TLS_SUPPORT */
+# define TLSminc(a) 0
+#endif /* TLS_SUPPORT */
#define FCCS 10 /* max number of fccs allowed */
+/* In the following array of structures, the numeric second field of the
+ structures (minchars) is apparently used like this:
+
+ -# : Switch can be abbreviated to # characters; switch hidden in -help.
+ 0 : Switch can't be abbreviated; switch shown in -help.
+ # : Switch can be abbreviated to # characters; switch shown in -help. */
+
static struct swit switches[] = {
#define ALIASW 0
{ "alias aliasfile", 0 },
#define VERSIONSW 20
{ "version", 0 },
#define HELPSW 21
- { "help", 4 },
+ { "help", 0 },
#define BITSTUFFSW 22
{ "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 30
+ { "sasl", SASLminc(-4) },
+#define NOSASLSW 31
+ { "nosasl", SASLminc(-6) },
+#define SASLMXSSFSW 32
+ { "saslmaxssf", SASLminc(-10) },
+#define SASLMECHSW 33
+ { "saslmech", SASLminc(-5) },
+#define USERSW 34
+ { "user", SASLminc(-4) },
+#define PORTSW 35
+ { "port server port name/number", 4 },
+#define TLSSW 36
+ { "tls", TLSminc(-3) },
+#define NTLSSW 37
+ { "notls", TLSminc(-5) },
+#define FILEPROCSW 38
+ { "fileproc", -4 },
+#define MHLPROCSW 39
+ { "mhlproc", -3 },
{ NULL, 0 }
};
/*
* 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_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 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 },
{ "Resent-Fcc", HFCC, 0 },
{ "Reply-To", HADR, 0 },
{ "From", HADR|HNGR, MFRM },
-#ifdef MMDFI
- { "Sender", HADR|HNGR|HMNG, 0 },
-#else
- { "Sender", HADR|HNGR, 0 },
-#endif
+ { "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 }
};
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 */
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 signature[BUFSIZ]; /* my signature */
static char *filter = NULL; /* the filter for BCC'ing */
static char *subject = NULL; /* the subject field for BCC'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 */
-
-#ifdef MMDFMTS
-static char *submitmode = "m"; /* deliver to mailbox only */
-static char submitopts[6] = "vl"; /* initial options for submit */
-#endif /* MMDFMTS */
+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 SENDMTS
static int snoop = 0;
-static int smtpmode = S_MAIL;
static char *clientsw = NULL;
static char *serversw = NULL;
extern struct smtp sm_reply;
-#endif /* SENDMTS */
static char prefix[] = "----- =_aaaaaaaaaa";
-static int fill_up = 0;
-static char *fill_in = NULL;
static char *partno = NULL;
static int queued = 0;
static void pl (void);
static void anno (void);
static int annoaux (struct mailname *);
-static void insert_fcc (struct headers *, char *);
+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);
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;
arguments = getarguments (invo_name, argc, argv, 0);
argp = arguments;
-#if defined(MMDFMTS) && defined(MMDFII)
- mmdf_init (invo_name);
-#endif /* MMDFMTS and MMDFII */
-
while ((cp = *argp++)) {
if (*cp == '-') {
switch (smatch (++cp, switches)) {
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 == '-')
adios (NULL, "bad argument %s %s", argp[-2], cp);
continue;
-#ifdef MMDFMTS
- case MAILSW:
- submitmode = "m";
- continue;
- case SOMLSW: /* for right now, sigh... */
- case SAMLSW:
- submitmode = "b";
- continue;
- case SENDSW:
- submitmode = "y";
- continue;
-#endif /* MMDFMTS */
-
- case DLVRSW:
- if (!(cp = *argp++) || *cp == '-')
+ case CLIESW:
+ if (!(clientsw = *argp++) || *clientsw == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
-
-#ifndef SENDMTS
- case CLIESW:
case SERVSW:
- if (!(cp = *argp++) || *cp == '-')
+ if (!(serversw = *argp++) || *serversw == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
-
case SNOOPSW:
+ snoop++;
continue;
-#else /* SENDMTS */
- case MAILSW:
- smtpmode = S_MAIL;
+
+ case PARTSW:
+ if (!(partno = *argp++) || *partno == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
continue;
- case SAMLSW:
- smtpmode = S_SAML;
+
+ case QUEUESW:
+ queued++;
continue;
- case SOMLSW:
- smtpmode = S_SOML;
+
+ case SASLSW:
+ sasl++;
continue;
- case SENDSW:
- smtpmode = S_SEND;
+
+ case NOSASLSW:
+ sasl = 0;
continue;
- case CLIESW:
- if (!(clientsw = *argp++) || *clientsw == '-')
+
+ case SASLMXSSFSW:
+ if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument to %s", argp[-2]);
+ saslssf = atoi(cp);
continue;
- case SERVSW:
- if (!(serversw = *argp++) || *serversw == '-')
+
+ case SASLMECHSW:
+ if (!(saslmech = *argp++) || *saslmech == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
- case SNOOPSW:
- snoop++;
+
+ case USERSW:
+ if (!(user = *argp++) || *user == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
continue;
-#endif /* SENDMTS */
- case FILLSW:
- if (!(fill_in = *argp++) || *fill_in == '-')
+ case PORTSW:
+ if (!(port = *argp++) || *port == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
- case FILLUSW:
- fill_up++;
+
+ case TLSSW:
+ tls++;
continue;
- case PARTSW:
- if (!(partno = *argp++) || *partno == '-')
+
+ case NTLSSW:
+ tls = 0;
+ continue;
+
+ case FILEPROCSW:
+ if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument to %s", argp[-2]);
+ fileproc = cp;
continue;
- case QUEUESW:
- queued++;
+ case MHLPROCSW:
+ if (!(cp = *argp++) || *cp == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ mhlproc = cp;
continue;
}
}
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 {
- strncpy (tmpfil, m_scratch ("", m_maildir (invo_name)),
- sizeof(tmpfil));
- if ((out = fopen (tmpfil, "w")) == NULL) {
- strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
- if ((out = fopen (tmpfil, "w")) == NULL)
- adios (tmpfil, "unable to create");
- }
+ char *cp = m_mktemp(m_maildir(invo_name), NULL, &out);
+ if (cp == NULL) {
+ cp = m_mktemp2(NULL, invo_name, NULL, &out);
+ if (cp == NULL) {
+ adios ("post", "unable to create temporary file");
+ }
+ }
+ strncpy(tmpfil, cp, sizeof(tmpfil));
chmod (tmpfil, 0600);
}
}
case BODY:
case BODYEOF:
finish_headers (out);
- if (whomsw && !fill_in)
+ if (whomsw)
break;
fprintf (out, "\n%s", buf);
while (state == BODY) {
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_PIPE. */
+ verify_all_addresses (1, envelope);
done (0);
}
-#ifdef MMDFMTS
- strcat (submitopts, submitmode);
- if (watch)
- strcat (submitopts, "nw");
-#endif /* MMDFMTS */
-
if (msgflags & MINV) {
make_bcc_file (dashstuff);
if (msgflags & MVIS) {
- verify_all_addresses (verbose);
- post (tmpfil, 0, verbose);
+ if (sm_mts != MTS_PIPE) {
+ /* It would be nice to have support to call
+ verify_all_addresses with MTS_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);
if (verbose)
printf (partno ? "Partial Message #%s Processed\n" : "Message Processed\n",
partno);
- return done (0);
+ done (0);
+ return 1;
}
int count, grp, i, keep;
char *cp, *pp, *qp;
char namep[BUFSIZ];
- struct mailname *mp, *np;
+ struct mailname *mp = NULL, *np = NULL;
struct headers *hdr;
while (*str == ' ' || *str == '\t')
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));
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) {
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++;
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) */
- pp = akvalue (mp->m_mbox);
+ /* The address doesn't include a host, so it might be an alias. */
+ pp = akvalue (mp->m_mbox); /* do mh alias substitution */
qp = akvisible () ? mp->m_mbox : "";
np = mp;
if (np->m_gname)
badadr++;
continue;
}
+
+ /*
+ * 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++;
if (np->m_ingrp)
mnfree (mp);
}
else {
+ /* Address includes a host, so no alias substitution is needed. */
+
+ /*
+ * 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++;
if (mp->m_gname)
badmsg++;
}
if (linepos) {
- if (fill_in && grp > 0)
- putc (';', out);
putc ('\n', out);
}
}
static void
start_headers (void)
{
- char *cp;
- char myhost[BUFSIZ], sigbuf[BUFSIZ];
+ unsigned char *cp;
+ 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';
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)
while (getname (""))
continue;
} else {
- strncpy (signature, adrsprintf (NULL, NULL), sizeof(signature));
+ strncpy (signature, getlocaladdr(), sizeof(signature));
}
}
{
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;
+ }
+
+ if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) {
+ advise (NULL, "A Sender: or Envelope-From: header is required "
+ "with multiple\nFrom: addresses");
+ badmsg++;
+ break;
+ }
+
+ if (whomsw)
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)
- fprintf (out, "Sender: %s\n", from);
- else
- fprintf (out, "From: %s\n", signature);
- if (whomsw)
- break;
+ (int) getpid (), (long) tclock, LocalName (1));
+ /*
+ * 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");
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;
+ }
-#ifdef MMDFI /* sigh */
- fprintf (out, "Sender: %s\n", from);
-#endif /* MMDFI */
+ 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)
- fprintf (out, "Resent-Sender: %s\n", from);
- else
- fprintf (out, "Resent-From: %s\n", signature);
- if (whomsw)
- break;
+ (int) getpid (), (long) tclock, LocalName (1));
+ /*
+ * 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);
+ }
+ }
+
if (!(msgflags & MVIS))
fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
break;
struct headers *h;
for (h = table; h->value; h++)
- if (!strcasecmp (header, h->value))
+ if (!mh_strcasecmp (header, h->value))
return (h - table);
return NOTOK;
if (mp->m_mbox == NULL || ((flags & HTRY) && !insert (mp)))
return 0;
- if ((!fill_in && (flags & (HBCC | HDCC))) || mp->m_ingrp)
+ if (sm_mts != MTS_PIPE && ((flags & (HBCC | HDCC | HEFM)) || mp->m_ingrp))
return 1;
if (!nameoutput) {
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 {
int len;
char *cp;
- if (!fill_in && (flags & HBCC))
+ if (sm_mts != MTS_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) {
: &netaddrs;
mp->m_next;
mp = mp->m_next)
- if (!strcasecmp (np->m_host, mp->m_next->m_host)
- && !strcasecmp (np->m_mbox, mp->m_next->m_mbox)
+ if (!mh_strcasecmp (np->m_host, mp->m_next->m_host)
+ && !mh_strcasecmp (np->m_mbox, mp->m_next->m_mbox)
&& np->m_bcc == mp->m_next->m_bcc)
return 0;
static void
-insert_fcc (struct headers *hdr, char *pp)
+insert_fcc (struct headers *hdr, unsigned char *pp)
{
- char *cp;
+ unsigned char *cp;
for (cp = pp; isspace (*cp); cp++)
continue;
pid_t child_id;
char *vec[6];
FILE *out;
+ char *tfile = NULL;
- strncpy (bccfil, m_tmpfil ("bccs"), sizeof(bccfil));
- if ((out = fopen (bccfil, "w")) == NULL)
- adios (bccfil, "unable to create");
+ 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, "Date: %s\n", dtime (&tclock, 0));
if (msgid)
fprintf (out, "Message-ID: <%d.%ld@%s>\n",
- (int) getpid (), (long) tclock, LocalName ());
- fprintf (out, "From: %s\n", signature);
+ (int) getpid (), (long) tclock, LocalName (1));
if (subject)
fprintf (out, "Subject: %s", subject);
fprintf (out, "BCC:\n");
static int
find_prefix (void)
{
- int len, result;
- char buffer[BUFSIZ];
+ int result = OK;
+ unsigned char buffer[BUFSIZ];
FILE *in;
if ((in = fopen (tmpfil, "r")) == NULL)
adios (tmpfil, "unable to re-open");
- len = strlen (prefix);
-
- result = OK;
while (fgets (buffer, sizeof(buffer) - 1, in))
if (buffer[0] == '-' && buffer[1] == '-') {
- char *cp;
+ unsigned char *cp;
for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
if (!isspace (*cp))
chkadr ();
-#ifdef MMDFMTS
- if (rp_isbad (retval = mm_waend ()))
- die (NULL, "problem ending addresses [%s]\n", rp_valstr (retval));
-#endif /* MMDFMTS */
-
-#ifdef SENDMTS
if (rp_isbad (retval = sm_waend ()))
die (NULL, "problem ending addresses; %s", rp_string (retval));
-#endif /* SENDMTS */
}
* SENDMAIL/SMTP routines
*/
-#ifdef SENDMTS
-
static void
-post (char *file, int bccque, int talk)
+post (char *file, int bccque, int talk, char *envelope)
{
int fd, onex;
- int retval;
+ int retval, i;
+ pid_t child_id;
onex = !(msgflags & MINV) || bccque;
if (verbose) {
sigon ();
- if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose,
- snoop, onex, queued))
- || rp_isbad (retval = sm_winit (smtpmode, from)))
- die (NULL, "problem initializing server; %s", rp_string (retval));
+ if (sm_mts == MTS_PIPE) {
+ char *sargv[16], **argp;
- 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);
+ for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
+ sleep (5);
+ switch (child_id) {
+ case NOTOK:
+ adios ("fork", "unable to");
- sm_end (onex ? OK : DONE);
- sigoff ();
+ case OK:
+ if (freopen( file, "r", stdin) == NULL) {
+ adios (file, "can't reopen for sendmail");
+ }
- if (verbose) {
- if (msgflags & MINV)
- printf (" -- %s Recipient Copies Posted --\n",
- bccque ? "Blind" : "Sighted");
- else
- printf (" -- Recipient Copies Posted --\n");
- }
+ argp = sargv;
+ *argp++ = "sendmail";
+ *argp++ = "-m"; /* send to me too */
+ *argp++ = "-t"; /* read msg for recipients */
+ *argp++ = "-i"; /* don't stop on "." */
+ if (whomsw)
+ *argp++ = "-bv";
+ if (snoop)
+ *argp++ = "-v";
+ *argp = NULL;
- fflush (stdout);
+ 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, onex, 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 (onex ? 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;
sigon ();
if (!whomsw || checksw)
- if (rp_isbad (retval = sm_init (clientsw, serversw, 0, 0, snoop, 0, 0))
- || rp_isbad (retval = sm_winit (smtpmode, from)))
+ if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
+ verbose, snoop, 0, queued, sasl,
+ saslssf, saslmech, user, tls))
+ || rp_isbad (retval = sm_winit (envelope)))
die (NULL, "problem initializing server; %s", rp_string (retval));
if (talk && !whomsw)
}
}
-#endif /* SENDMTS */
-
-/*
- * MMDF routines
- */
-
-#ifdef MMDFMTS
-
-static void
-post (char *file, int bccque, int talk)
-{
- int fd, onex;
- int retval;
-#ifdef RP_NS
- int len;
- struct rp_bufstruct reply;
-#endif /* RP_NS */
-
- onex = !(msgflags & MINV) || bccque;
- if (verbose) {
- if (msgflags & MINV)
- printf (" -- Posting for %s Recipients --\n",
- bccque ? "Blind" : "Sighted");
- else
- printf (" -- Posting for All Recipients --\n");
- }
-
- sigon ();
-
- if (rp_isbad (retval = mm_init ())
- || rp_isbad (retval = mm_sbinit ())
- || rp_isbad (retval = mm_winit (NULL, submitopts, from)))
- die (NULL, "problem initializing MMDF system [%s]",
- rp_valstr (retval));
-#ifdef RP_NS
- if (rp_isbad (retval = mm_rrply (&reply, &len)))
- die (NULL, "problem with sender address [%s]",
- rp_valstr (retval));
-#endif /* RP_NS */
-
- 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);
-
- mm_sbend ();
- mm_end (OK);
- 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)
-{
- int retval;
- struct mailname *lp;
-
-#ifdef RP_NS
- int len;
- struct rp_bufstruct reply;
-#endif /* RP_NS */
-
- sigon ();
-
- if (!whomsw || checksw) {
- if (rp_isbad (retval = mm_init ())
- || rp_isbad (retval = mm_sbinit ())
- || rp_isbad (retval = mm_winit (NULL, submitopts, from)))
- die (NULL, "problem initializing MMDF system [%s]",
- rp_valstr (retval));
-#ifdef RP_NS
- if (rp_isbad (retval = mm_rrply (&reply, &len)))
- die (NULL, "problem with sender address [%s]", rp_valstr (retval));
-#endif /* RP_NS */
- }
-
- if (talk && !whomsw)
- printf (" -- Address Verification --\n");
- if (talk && localaddrs.m_next)
- printf (" -- Local Recipients --\n");
- for (lp = localaddrs.m_next; lp; lp = lp->m_next)
- do_an_address (lp, talk);
-
- if (talk && uuaddrs.m_next)
- printf (" -- UUCP Recipients --\n");
- for (lp = uuaddrs.m_next; lp; lp = lp->m_next)
- do_an_address (lp, talk);
-
- if (talk && netaddrs.m_next)
- printf (" -- Network Recipients --\n");
- for (lp = netaddrs.m_next; lp; lp = lp->m_next)
- do_an_address (lp, talk);
-
- chkadr ();
- if (talk && !whomsw)
- printf (" -- Address Verification Successful --\n");
-
- if (!whomsw || checksw)
- mm_end (NOTOK);
-
- fflush (stdout);
- sigoff ();
-}
-
-
-static void
-do_an_address (struct mailname *lp, int talk)
-{
- int len, retval;
- char *mbox, *host, *text, *path;
- char addr[BUFSIZ];
- struct rp_bufstruct reply;
-
- switch (lp->m_type) {
- case LOCALHOST:
- mbox = lp->m_mbox;
- host = LocalName ();
- strncpy (addr, mbox, sizeof(addr));
- break;
-
- case UUCPHOST:
- fprintf (talk ? stdout : stderr, " %s!%s: %s\n",
- lp->m_host, lp->m_mbox, "not supported; UUCP address");
- unkadr++;
- fflush (stdout);
- return;
-
- default: /* let MMDF decide if the host is bad */
- mbox = lp->m_mbox;
- host = lp->m_host;
- snprintf (addr, sizeof(addr), "%s at %s", mbox, host);
- break;
- }
-
- if (talk)
- printf (" %s%s", addr, whomsw && lp->m_bcc ? "[BCC]" : "");
-
- if (whomsw && !checksw) {
- putchar ('\n');
- return;
- }
- if (talk)
- printf (": ");
- fflush (stdout);
-
-#ifdef MMDFII
- if (lp->m_path)
- path = concat (lp->m_path, mbox, "@", host, NULL);
- else
-#endif /* MMDFII */
- path = NULL;
- if (rp_isbad (retval = mm_wadr (path ? NULL : host, path ? path : mbox))
- || rp_isbad (retval = mm_rrply (&reply, &len)))
- die (NULL, "problem submitting address [%s]", rp_valstr (retval));
-
- switch (rp_gval (reply.rp_val)) {
- case RP_AOK:
- if (talk)
- printf ("address ok\n");
- fflush (stdout);
- return;
-
-#ifdef RP_DOK
- case RP_DOK:
- if (talk)
- printf ("nameserver timeout - queued for checking\n");
- fflush (stdout);
- return;
-#endif /* RP_DOK */
-
- case RP_NO:
- text = "you lose";
- break;
-
-#ifdef RP_NS
- case RP_NS:
- text = "temporary nameserver failure";
- break;
-
-#endif /* RP_NS */
-
- case RP_USER:
- case RP_NDEL:
- text = "not deliverable";
- break;
-
- case RP_AGN:
- text = "try again later";
- break;
-
- case RP_NOOP:
- text = "nothing done";
- break;
-
- default:
- if (!talk)
- fprintf (stderr, " %s: ", addr);
- text = "unexpected response";
- die (NULL, "%s;\n [%s] -- %s", text,
- rp_valstr (reply.rp_val), reply.rp_line);
- }
-
- if (!talk)
- fprintf (stderr, " %s: ", addr);
- fprintf (talk ? stdout : stderr, "%s;\n %s\n", text, reply.rp_line);
- unkadr++;
-
- fflush (stdout);
-}
-
-
-static void
-do_text (char *file, int fd)
-{
- int retval, state;
- char buf[BUFSIZ];
- struct rp_bufstruct reply;
-
- lseek (fd, (off_t) 0, SEEK_SET);
-
- while ((state = read (fd, buf, sizeof(buf))) > 0) {
- if (rp_isbad (mm_wtxt (buf, state)))
- die (NULL, "problem writing text [%s]\n", rp_valstr (retval));
- }
-
- if (state == NOTOK)
- die (file, "problem reading from");
-
- if (rp_isbad (retval = mm_wtend ()))
- die (NULL, "problem ending text [%s]\n", rp_valstr (retval));
-
- if (rp_isbad (retval = mm_rrply (&reply, &state)))
- die (NULL, "problem getting submission status [%s]\n",
- rp_valstr (retval));
-
- switch (rp_gval (reply.rp_val)) {
- case RP_OK:
- case RP_MOK:
- break;
-
- case RP_NO:
- die (NULL, "you lose; %s", reply.rp_line);
-
- case RP_NDEL:
- die (NULL, "no delivery occurred; %s", reply.rp_line);
-
- case RP_AGN:
- die (NULL, "try again later; %s", reply.rp_line);
-
- case RP_NOOP:
- die (NULL, "nothing done; %s", reply.rp_line);
-
- default:
- die (NULL, "unexpected response;\n\t[%s] -- %s",
- rp_valstr (reply.rp_val), reply.rp_line);
- }
-}
-
-#endif /* MMDFMTS */
-
/*
* SIGNAL HANDLING
*/
-static RETSIGTYPE
+static void
sigser (int i)
{
-#ifndef RELIABLE_SIGNALS
- SIGNAL (i, SIG_IGN);
-#endif
+ NMH_UNUSED (i);
unlink (tmpfil);
if (msgflags & MINV)
unlink (bccfil);
-#ifdef MMDFMTS
- if (!whomsw || checksw)
- mm_end (NOTOK);
-#endif /* MMDFMTS */
-
-#ifdef SENDMTS
if (!whomsw || checksw)
sm_end (NOTOK);
-#endif /* SENDMTS */
done (1);
}
if (msgflags & MINV)
unlink (bccfil);
-#ifdef MMDFMTS
- if (!whomsw || checksw)
- mm_end (NOTOK);
-#endif /* MMDFMTS */
-
-#ifdef SENDMTS
if (!whomsw || checksw)
sm_end (NOTOK);
-#endif /* SENDMTS */
va_start(ap, fmt);
advertise (what, NULL, fmt, ap);
va_end(ap);
done (1);
}
-
-
-#ifdef MMDFMTS
-/*
- * err_abrt() is used by the mm_ routines
- * do not, under *ANY* circumstances, remove it from post,
- * or you will lose *BIG*
- */
-
-void
-err_abrt (int code, char *fmt, ...)
-{
- char buffer[BUFSIZ];
- va_list ap;
-
- snprintf (buffer, sizeof(buffer), "[%s]", rp_valstr (code));
-
- va_start(ap, fmt);
- advertise (buffer, NULL, fmt, ap);
- va_end(ap);
-
- done (1);
-}
-#endif /* MMDFMTS */