* 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/dropsbr.h>
#include <h/mime.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 <mts/mmdf/mmdf.h>
#endif
-/*
- * Currently smtp and sendmail use
- * the same interface for posting.
- */
#ifdef SMTPMTS
-# define SENDMTS
-#endif
-
-#ifdef SENDMTS
# include <mts/smtp/smtp.h>
#endif
# define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : (c))
#endif
+#ifndef CYRUS_SASL
+# define SASLminc(a) (a)
+#else /* CYRUS_SASL */
+# define SASLminc(a) 0
+#endif /* CYRUS_SASL */
+
#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
{ "partno", -6 },
#define QUEUESW 36
{ "queued", -6 },
+#define SASLSW 37
+ { "sasl", SASLminc(-4) },
+#define SASLMECHSW 38
+ { "saslmech", SASLminc(-5) },
+#define USERSW 39
+ { "user", SASLminc(-4) },
{ NULL, 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 char *saslmech=NULL; /* Force use of particular SASL mech */
+static char *user=NULL; /* Authenticate as this user */
static unsigned msgflags = 0; /* what we've seen */
static char submitopts[6] = "vl"; /* initial options for submit */
#endif /* MMDFMTS */
-#ifdef SENDMTS
+#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 /* SENDMTS */
+#endif /* SMTPMTS */
static char prefix[] = "----- =_aaaaaaaaaa";
static char *partno = NULL;
static int queued = 0;
+extern boolean draft_from_masquerading; /* defined in mts.c */
+
/*
* static prototypes
*/
adios (NULL, "missing argument to %s", argp[-2]);
continue;
-#ifndef SENDMTS
+#ifndef SMTPMTS
case CLIESW:
case SERVSW:
if (!(cp = *argp++) || *cp == '-')
case SNOOPSW:
continue;
-#else /* SENDMTS */
+#else /* SMTPMTS */
case MAILSW:
smtpmode = S_MAIL;
continue;
case SNOOPSW:
snoop++;
continue;
-#endif /* SENDMTS */
+#endif /* SMTPMTS */
case FILLSW:
if (!(fill_in = *argp++) || *fill_in == '-')
case QUEUESW:
queued++;
continue;
+
+ case SASLSW:
+ sasl++;
+ continue;
+
+ case SASLMECHSW:
+ if (!(saslmech = *argp++) || *saslmech == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ continue;
+
+ case USERSW:
+ if (!(user = *argp++) || *user == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ continue;
}
}
if (msg)
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 (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:. */
+ strncpy(from, auxformat(mp, 0), sizeof(from) - 1);
+
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 (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:. */
+ strncpy(from, auxformat(mp, 0), sizeof(from) - 1);
+
if (hdr->flags & HBCC)
mp->m_bcc++;
if (mp->m_gname)
if (msgid)
fprintf (out, "Message-ID: <%d.%ld@%s>\n",
(int) getpid (), (long) tclock, LocalName ());
- if (msgflags & MFRM)
- fprintf (out, "Sender: %s\n", from);
+ 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);
if (whomsw)
break;
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);
+ 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);
+ }
else
+ /* Construct a Resent-From: header. */
fprintf (out, "Resent-From: %s\n", signature);
if (whomsw)
break;
die (NULL, "problem ending addresses [%s]\n", rp_valstr (retval));
#endif /* MMDFMTS */
-#ifdef SENDMTS
+#ifdef SMTPMTS
if (rp_isbad (retval = sm_waend ()))
die (NULL, "problem ending addresses; %s", rp_string (retval));
-#endif /* SENDMTS */
+#endif /* SMTPMTS */
}
* SENDMAIL/SMTP routines
*/
-#ifdef SENDMTS
+#ifdef SMTPMTS
static void
post (char *file, int bccque, int talk)
sigon ();
if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose,
- snoop, onex, queued))
+ snoop, onex, queued, sasl, saslmech,
+ user))
|| rp_isbad (retval = sm_winit (smtpmode, from)))
die (NULL, "problem initializing server; %s", rp_string (retval));
sigon ();
if (!whomsw || checksw)
- if (rp_isbad (retval = sm_init (clientsw, serversw, 0, 0, snoop, 0, 0))
+ if (rp_isbad (retval = sm_init (clientsw, serversw, 0, 0, snoop, 0,
+ 0, 0, 0, 0))
|| rp_isbad (retval = sm_winit (smtpmode, from)))
die (NULL, "problem initializing server; %s", rp_string (retval));
}
}
-#endif /* SENDMTS */
+#endif /* SMTPMTS */
/*
* MMDF routines
mm_end (NOTOK);
#endif /* MMDFMTS */
-#ifdef SENDMTS
+#ifdef SMTPMTS
if (!whomsw || checksw)
sm_end (NOTOK);
-#endif /* SENDMTS */
+#endif /* SMTPMTS */
done (1);
}
mm_end (NOTOK);
#endif /* MMDFMTS */
-#ifdef SENDMTS
+#ifdef SMTPMTS
if (!whomsw || checksw)
sm_end (NOTOK);
-#endif /* SENDMTS */
+#endif /* SMTPMTS */
va_start(ap, fmt);
advertise (what, NULL, fmt, ap);