-/*
- * post.c -- enter messages into the mail transport system
+/* post.c -- enter messages into the mail transport system
*
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
#include <h/utils.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "../sbr/m_mktemp.h"
+#include "../sbr/message_id.h"
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
X("tls", TLSminc(-3), TLSSW) \
X("initialtls", TLSminc(-10), INITTLSSW) \
X("notls", TLSminc(-5), NTLSSW) \
+ X("certverify", TLSminc(-10), CERTVERSW) \
+ X("nocertverify", TLSminc(-12), NOCERTVERSW) \
X("fileproc", -4, FILEPROCSW) \
X("mhlproc", -3, MHLPROCSW) \
X("sendmail program", 0, MTSSM) \
* from 'send'. We use a service name of 'post' internally.
*/
-static struct oauth_profile {
+static struct {
const char *profname;
int switchnum;
const char *value;
#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 MRSN 0x0040 /* We've seen a Resent-Sender: */
#define MEFM 0x0080 /* We've seen Envelope-From: */
#define MMIM 0x0100 /* We've seen Mime-Version: */
static char *saslmech=NULL; /* Force use of particular SASL mech */
static char *user=NULL; /* Authenticate as this user */
static char *port="submission"; /* Name of server port for SMTP submission */
-static int tls=-1; /* Use TLS for encryption */
+static int tlsflag=0; /* Flags to control TLS settings */
static int fromcount=0; /* Count of addresses on From: header */
static int seensender=0; /* Have we seen a Sender: header? */
int
main (int argc, char **argv)
{
- int state, compnum, dashstuff = 0, swnum, oauth_flag = 0;
+ int state, compnum, dashstuff = 0, swnum, oauth_flag = 0, tls = -1;
+ int noverify = 0;
int eai = 0; /* use Email Address Internationalization (EAI) (SMTPUTF8) */
char *cp, *msg = NULL, **argp, **arguments, *envelope;
- char buf[BUFSIZ], name[NAMESZ], *auth_svc = NULL;
+ char buf[NMH_BUFSIZ], name[NAMESZ], *auth_svc = NULL;
FILE *in, *out;
m_getfld_state_t gstate = 0;
tls = 0;
continue;
+ case CERTVERSW:
+ noverify = 0;
+ continue;
+
+ case NOCERTVERSW:
+ noverify++;
+ continue;
+
case FILEPROCSW:
if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument to %s", argp[-2]);
case FLD:
case FLDPLUS:
compnum++;
- cp = add (buf, NULL);
+ cp = mh_xstrdup(buf);
while (state == FLDPLUS) {
bufsz = sizeof buf;
state = m_getfld (&gstate, name, buf, &bufsz, in);
#endif /* ! TLS_SUPPORT */
}
+ if (tls == 1)
+ tlsflag = S_STARTTLS;
+ else if (tls == 2)
+ tlsflag = S_INITTLS;
+ else
+ tlsflag = 0;
+
+ if (noverify)
+ tlsflag |= S_NOVERIFY;
+
/*
* If we were given any oauth flags, store the appropriate profile
* entries and make sure an authservice was given (we have to do this
if (partno)
printf ("Partial Message #%s Processed\n", partno);
else
- printf ("Message Processed\n");
+ puts("Message Processed");
}
done (0);
str++;
if (msgstate == NORMAL && uprf (name, "resent")) {
- advise (NULL, "illegal header line -- %s:", name);
+ inform("illegal header line -- %s:", name);
badmsg++;
return;
}
If it does, enable EAI support. */
if (contains8bit(str, NULL)) {
if (verbose) {
- printf ("EAI/SMTPUTF8 enabled\n");
+ puts("EAI/SMTPUTF8 enabled");
}
/* Enable SMTPUTF8. */
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';
+ trim_suffix_c(str, '\n');
if (! whomsw) {
- advise (NULL, "ignoring header line -- %s: %s", name, str);
+ inform("ignoring header line -- %s: %s", name, str);
}
}
}
return;
}
if (hdr->flags & HBAD) {
- advise (NULL, "illegal header line -- %s:", name);
+ inform("illegal header line -- %s:", name);
badmsg++;
return;
}
*/
if ((msgstate == RESENT) ? (hdr->set & MRSN)
: (hdr->set & MSND)) {
- advise (NULL, "%s: field requires one address", name);
+ inform("%s: field requires one address", name);
badmsg++;
}
#ifdef notdef
- advise (NULL, "%s: field requires at least one address", name);
+ inform("%s: field requires at least one address", name);
badmsg++;
#endif /* notdef */
}
}
if (count > 1 && (hdr->flags & HONE)) {
- advise (NULL, "%s: field only permits one address", name);
+ inform("%s: field only permits one address", name);
badmsg++;
return;
}
* Strip off any trailing newlines
*/
- while (strlen(fullfrom) > 0 && fullfrom[strlen(fullfrom) - 1] == '\n') {
+ while (*fullfrom && 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);
+ inform("%s: field does not allow groups", name);
badmsg++;
}
if (linepos) {
/*
* A From: header is now required in the draft.
*/
- advise (NULL, "message has no From: header");
- advise (NULL, "See default components files for examples");
+ inform("message has no From: header");
+ inform("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 "
+ inform("A Sender: or Envelope-From: header is required "
"with multiple\nFrom: addresses");
badmsg++;
break;
if (fromcount > 1 && seensender == 0) {
if (efrom[0] == '\0') {
- advise (NULL, "Envelope-From cannot be blank when there "
+ inform("Envelope-From cannot be blank when there "
"is multiple From: addresses\nand no Sender: "
"header");
badmsg++;
case RESENT:
if (!(msgflags & MDAT)) {
- advise (NULL, "message has no Date: header");
+ inform("message has no Date: header");
badmsg++;
}
if (!(msgflags & MFRM)) {
- advise (NULL, "message has no From: header");
+ inform("message has no From: header");
badmsg++;
}
if (!(msgflags & MRFM)) {
- advise (NULL, "message has no Resent-From: header");
- advise (NULL, "See default components files for examples");
+ inform("message has no Resent-From: header");
+ inform("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 "
+ inform("A Resent-Sender: or Envelope-From: header is "
"required with multiple\nResent-From: addresses");
badmsg++;
break;
if (fromcount > 1 && seensender == 0) {
if (efrom[0] == '\0') {
- advise (NULL, "Envelope-From cannot be blank when there "
+ inform("Envelope-From cannot be blank when there "
"is multiple Resent-From: addresses and no "
"Resent-Sender: header");
badmsg++;
struct headers *h;
for (h = table; h->value; h++)
- if (!strcasecmp (header ? header : "", h->value ? h->value : ""))
+ if (!strcasecmp (FENDNULL(header), FENDNULL(h->value)))
return (h - table);
return NOTOK;
: &netaddrs;
mp->m_next;
mp = mp->m_next)
- if (!strcasecmp (np->m_host ? np->m_host : "",
- mp->m_next->m_host ? mp->m_next->m_host : "") &&
- !strcasecmp (np->m_mbox ? np->m_mbox : "",
- mp->m_next->m_mbox ? mp->m_next->m_mbox : "") &&
+ if (!strcasecmp (FENDNULL(np->m_host),
+ FENDNULL(mp->m_next->m_host)) &&
+ !strcasecmp (FENDNULL(np->m_mbox),
+ FENDNULL(mp->m_next->m_mbox)) &&
np->m_bcc == mp->m_next->m_bcc)
return 0;
printf ("\nnet:\t");
for (mp = netaddrs.m_next; mp; mp = mp->m_next)
- printf ("%s%s@%s%s%s", mp->m_path ? mp->m_path : "",
+ printf ("%s%s@%s%s%s", FENDNULL(mp->m_path),
mp->m_mbox, mp->m_host,
mp->m_bcc ? "[BCC]" : "",
mp->m_next ? ",\n\t" : "");
printf ("\n\t-- Folder Copies --\nfcc:\t");
for (i = 0; i < fccind; i++)
printf ("%s%s", fccfold[i], i + 1 < fccind ? ",\n\t" : "");
- printf ("\n");
+ putchar('\n');
}
if ((in = fopen (tmpfil, "r")) == NULL)
adios (tmpfil, "unable to re-open");
- while (fgets (buffer, sizeof(buffer) - 1, in))
+ while (fgets (buffer, sizeof buffer, in))
if (buffer[0] == '-' && buffer[1] == '-') {
char *cp;
}
-#define plural(x) (x == 1 ? "" : "s")
-
static void
chkadr (void)
{
if (badadr && unkadr)
die (NULL, "%d address%s unparsable, %d addressee%s undeliverable",
- badadr, plural (badadr), unkadr, plural (badadr));
+ badadr, PLURALS(badadr), unkadr, PLURALS(badadr));
if (badadr)
- die (NULL, "%d address%s unparsable", badadr, plural (badadr));
+ die (NULL, "%d address%s unparsable", badadr, PLURALS(badadr));
if (unkadr)
- die (NULL, "%d addressee%s undeliverable", unkadr, plural (unkadr));
+ die (NULL, "%d addressee%s undeliverable", unkadr, PLURALS(unkadr));
}
for (lp = localaddrs.m_next; lp; lp = lp->m_next)
if (lp->m_bcc ? bccque : !bccque) {
if (talk && !state)
- printf (" -- Local Recipients --\n");
+ puts(" -- Local Recipients --");
do_an_address (lp, talk);
state++;
}
for (lp = uuaddrs.m_next; lp; lp = lp->m_next)
if (lp->m_bcc ? bccque : !bccque) {
if (talk && !state)
- printf (" -- UUCP Recipients --\n");
+ puts(" -- UUCP Recipients --");
do_an_address (lp, talk);
state++;
}
for (lp = netaddrs.m_next; lp; lp = lp->m_next)
if (lp->m_bcc ? bccque : !bccque) {
if (talk && !state)
- printf (" -- Network Recipients --\n");
+ puts(" -- Network Recipients --");
do_an_address (lp, talk);
state++;
}
printf (" -- Posting for %s Recipients --\n",
bccque ? "Blind" : "Sighted");
else
- printf (" -- Posting for All Recipients --\n");
+ puts(" -- Posting for All Recipients --");
}
sigon ();
if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
verbose, snoop, sasl, saslmech, user,
- oauth_flag ? auth_svc : NULL, tls))
+ oauth_flag ? auth_svc : NULL, tlsflag))
|| rp_isbad (retval = sm_winit (envelope, eai, eightbit))) {
close (fd);
die (NULL, "problem initializing server; %s", rp_string (retval));
printf (" -- %s Recipient Copies Posted --\n",
bccque ? "Blind" : "Sighted");
else
- printf (" -- Recipient Copies Posted --\n");
+ puts(" -- Recipient Copies Posted --");
}
fflush (stdout);
if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
verbose, snoop, sasl, saslmech, user,
- oauth_flag ? auth_svc : NULL, tls))
+ oauth_flag ? auth_svc : NULL, tlsflag))
|| rp_isbad (retval = sm_winit (envelope, eai, eightbit))) {
die (NULL, "problem initializing server; %s", rp_string (retval));
}
}
if (talk && !whomsw)
- printf (" -- Address Verification --\n");
+ puts(" -- Address Verification --");
if (talk && localaddrs.m_next)
- printf (" -- Local Recipients --\n");
+ puts(" -- Local Recipients --");
for (lp = localaddrs.m_next; lp; lp = lp->m_next)
do_an_address (lp, talk);
if (talk && uuaddrs.m_next)
- printf (" -- UUCP Recipients --\n");
+ puts(" -- UUCP Recipients --");
for (lp = uuaddrs.m_next; lp; lp = lp->m_next)
do_an_address (lp, talk);
if (talk && netaddrs.m_next)
- printf (" -- Network Recipients --\n");
+ puts(" -- Network Recipients --");
for (lp = netaddrs.m_next; lp; lp = lp->m_next)
do_an_address (lp, talk);
chkadr ();
if (talk && !whomsw)
- printf (" -- Address Verification Successful --\n");
+ puts(" -- Address Verification Successful --");
if (!whomsw || checksw)
sm_end (DONE);
lp->m_type != UUCPHOST ? lp->m_path : NULL)) {
case RP_OK:
if (talk)
- printf ("address ok\n");
+ puts("address ok");
break;
case RP_NO:
int retval, state;
char buf[BUFSIZ];
- lseek (fd, (off_t) 0, SEEK_SET);
+ lseek(fd, 0, SEEK_SET);
while ((state = read (fd, buf, sizeof(buf))) > 0) {
if (rp_isbad (retval = sm_wtxt (buf, state)))
case RP_NO:
case RP_NDEL:
die (NULL, "posting failed; %s", rp_string (retval));
+ break;
default:
die (NULL, "unexpected response; %s", rp_string (retval));
return;
if (verbose)
- printf (" -- Filing Folder Copies --\n");
+ puts(" -- Filing Folder Copies --");
for (i = 0; i < fccind; i++)
fcc (file, fccfold[i]);
if (verbose)
- printf (" -- Folder Copies Filed --\n");
+ puts(" -- Folder Copies Filed --");
}
if (!verbose)
fprintf (stderr, " %sFcc %s: ",
msgstate == RESENT ? "Resent-" : "", folder);
- pidstatus (status, verbose ? stdout : stderr, NULL);
+ pidstatus (status, verbose ? stdout : stderr, fileproc);
} else {
if (verbose)
- printf ("folder ok\n");
+ puts("folder ok");
}
}
static void
die (char *what, char *fmt, ...)
{
+ int err;
va_list ap;
+ err = errno;
+
(void) m_unlink (tmpfil);
if (msgflags & MINV)
(void) m_unlink (bccfil);
sm_end (NOTOK);
va_start(ap, fmt);
+ errno = err;
advertise (what, NULL, fmt, ap);
va_end(ap);
done (1);