-/*
- * 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>
#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 void putfmt (char *, char *, int *, FILE *);
static void start_headers (void);
static void finish_headers (FILE *);
-static int get_header (char *, struct headers *);
-static int putadr (char *, char *, struct mailname *, FILE *, unsigned int);
+static int get_header (char *, struct headers *) PURE;
+static int putadr (char *, char *, struct mailname *, FILE *, unsigned int,
+ char *, unsigned int);
static void putgrp (char *, char *, FILE *, unsigned int);
static int insert (struct mailname *);
static void pl (void);
static void insert_fcc (struct headers *, char *);
static void make_bcc_file (int);
static void verify_all_addresses (int, int, char *, int, char *);
-static void chkadr (void);
+static void chkadr (void) PURE;
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 fatal (char *, char *, ...) CHECK_PRINTF(2, 3);
static void post (char *, int, int, int, char *, int, char *);
static void do_text (char *file, int fd);
static void do_an_address (struct mailname *, int);
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;
+ m_getfld_state_t gstate;
if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; }
}
if (msg)
adios (NULL, "only one message at a time!");
- else
- msg = cp;
+ msg = cp;
}
alias (AliasFile);
hdrtab = msgstate == NORMAL ? NHeaders : RHeaders;
+ gstate = m_getfld_state_init(in);
for (compnum = 1;;) {
int bufsz = sizeof buf;
- switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
+ switch (state = m_getfld2(&gstate, name, buf, &bufsz)) {
case FLD:
case FLDPLUS:
compnum++;
cp = mh_xstrdup(buf);
while (state == FLDPLUS) {
bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, in);
+ state = m_getfld2(&gstate, name, buf, &bufsz);
cp = add (buf, cp);
}
putfmt (name, cp, &eai, out);
fprintf (out, "\n%s", buf);
while (state == BODY) {
bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, in);
+ state = m_getfld2(&gstate, name, buf, &bufsz);
fputs (buf, out);
}
break;
if (debug) {
pl ();
done (0);
- } else {
- fclose (out);
}
+ fclose (out);
/*
* Here's how we decide which address to use as the envelope-from
int count, grp, i, keep;
char *cp, *pp, *qp;
char namep[BUFSIZ], error[BUFSIZ];
+ char *savehdr = NULL;
+ unsigned int savehdrlen = 0;
struct mailname *mp = NULL, *np = NULL;
struct headers *hdr;
return;
}
+ /*
+ * 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.
+ * Because we want to capture the results of alias expansion, save
+ * the output from putadr().
+ */
+
+ if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) {
+ savehdr = fullfrom;
+ savehdr[0] = '\0';
+ savehdrlen = sizeof(fullfrom);
+ }
+
tmpaddrs.m_next = NULL;
for (count = 0; (cp = getname (str)); count++) {
mp->m_bcc++;
if (np->m_ingrp)
mp->m_ingrp = np->m_ingrp;
- else
- if (mp->m_gname)
- putgrp (namep, mp->m_gname, out, hdr->flags);
+ else if (mp->m_gname)
+ putgrp (namep, mp->m_gname, out, hdr->flags);
if (mp->m_ingrp) {
if (sm_mts == MTS_SENDMAIL_PIPE) {
/* Catch this before sendmail chokes with:
grp++;
}
- if (putadr (namep, qp, mp, out, hdr->flags))
+ if (putadr (namep, qp, mp, out, hdr->flags, savehdr,
+ savehdrlen))
msgflags |= (hdr->set & (MVIS | MINV));
else
mnfree (mp);
putgrp (namep, mp->m_gname, out, hdr->flags);
if (mp->m_ingrp)
grp++;
- keep = putadr (namep, "", mp, out, hdr->flags);
+ keep = putadr (namep, "", mp, out, hdr->flags, savehdr, savehdrlen);
np = mp->m_next;
if (keep) {
mp->m_next = NULL;
}
/*
- * 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 it was a From header, strip off any trailing newlines from
+ * the alias-expanded From line.
*/
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 (*fullfrom && fullfrom[strlen(fullfrom) - 1] == '\n') {
fullfrom[strlen(fullfrom) - 1] = '\0';
}
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;
static int
-putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flags)
+putadr (char *name, char *aka, struct mailname *mp, FILE *out,
+ unsigned int flags, char *savehdr, unsigned int savehdrsize)
{
- int len;
+ int len, saveappend = 0;
+ unsigned int shlen;
char *cp;
char buffer[BUFSIZ];
linepos += (nameoutput = strlen (name) + 2);
}
+ if (savehdr) {
+ shlen = strlen(savehdr);
+ saveappend = 1;
+ }
+
if (*aka && mp->m_type != UUCPHOST && !mp->m_pers)
mp->m_pers = mh_xstrdup(aka);
if (format) {
len = strlen (cp);
if (linepos != nameoutput) {
- if (len + linepos + 2 > outputlinelen)
+ if (len + linepos + 2 > outputlinelen) {
fprintf (out, ",\n%*s", linepos = nameoutput, "");
- else {
+ if (saveappend) {
+ if (shlen + 2 + nameoutput + len >= savehdrsize) {
+ saveappend = 0;
+ } else {
+ snprintf(savehdr + shlen, savehdrsize - shlen, ",\n%*s",
+ linepos, "");
+ }
+ }
+ } else {
fputs (", ", out);
linepos += 2;
+ if (saveappend) {
+ if (shlen + 2 + len >= savehdrsize) {
+ saveappend = 0;
+ } else {
+ strncat(savehdr, ", ", savehdrsize - shlen);
+ }
+ }
}
}
fputs (cp, out);
+
+ if (saveappend && shlen + len < savehdrsize)
+ strncat(savehdr, cp, savehdrsize - shlen + len);
+
linepos += len;
return (flags & HTRY);
: &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" : "");
while (find_prefix () == NOTOK) {
if (*cp < 'z')
(*cp)++;
- else
- if (*++cp == 0)
- adios (NULL, "can't find a unique delimiter string");
- else
- (*cp)++;
+ else if (*++cp == 0)
+ adios (NULL, "can't find a unique delimiter string");
+ else
+ (*cp)++;
}
fprintf (out, "%s: %s\n%s: multipart/digest; boundary=\"",
* of MIME encapsulation.
*/
if (filter != NULL) {
- for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
- sleep (5);
+ child_id = fork();
switch (child_id) {
case NOTOK:
adios ("fork", "unable to");
}
-#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));
+ fatal (NULL, "%d address%s unparsable, %d addressee%s undeliverable",
+ badadr, PLURALS(badadr), unkadr, PLURALS(badadr));
if (badadr)
- die (NULL, "%d address%s unparsable", badadr, plural (badadr));
+ fatal (NULL, "%d address%s unparsable", badadr, PLURALS(badadr));
if (unkadr)
- die (NULL, "%d addressee%s undeliverable", unkadr, plural (unkadr));
+ fatal (NULL, "%d addressee%s undeliverable", unkadr, PLURALS(unkadr));
}
chkadr ();
if (rp_isbad (retval = sm_waend ()))
- die (NULL, "problem ending addresses; %s", rp_string (retval));
+ fatal (NULL, "problem ending addresses; %s", rp_string (retval));
}
post (char *file, int bccque, int talk, int eai, char *envelope,
int oauth_flag, char *auth_svc)
{
- int retval, i;
+ int retval;
pid_t child_id;
if (verbose) {
char **argp, *program;
int argc;
- for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
- sleep (5);
+ child_id = fork();
switch (child_id) {
case NOTOK:
adios ("fork", "unable to");
int eightbit = 0;
if (fd == NOTOK) {
- die (file, "unable to re-open");
+ fatal (file, "unable to re-open");
}
if (msgflags & MMIM && cte != UNKNOWN) {
} else {
if (scan_input (fd, &eightbit) == NOTOK) {
close (fd);
- die (file, "problem reading from");
+ fatal (file, "problem reading from");
}
}
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));
+ fatal (NULL, "problem initializing server; %s", rp_string (retval));
}
do_addresses (bccque, talk && verbose);
verbose, snoop, sasl, saslmech, user,
oauth_flag ? auth_svc : NULL, tlsflag))
|| rp_isbad (retval = sm_winit (envelope, eai, eightbit))) {
- die (NULL, "problem initializing server; %s", rp_string (retval));
+ fatal (NULL, "problem initializing server; %s", rp_string (retval));
}
}
puts(" -- Address Verification Successful --");
if (!whomsw || checksw)
- sm_end (DONE);
+ sm_end (whomsw ? OK : DONE);
fflush (stdout);
sigoff ();
default:
if (!talk)
fprintf (stderr, " %s: ", addr);
- die (NULL, "unexpected response; %s", rp_string (retval));
+ fatal (NULL, "unexpected response; %s", rp_string (retval));
}
fflush (stdout);
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)))
- die (NULL, "problem writing text; %s\n", rp_string (retval));
+ fatal (NULL, "problem writing text; %s\n", rp_string (retval));
}
if (state == NOTOK)
- die (file, "problem reading from");
+ fatal (file, "problem reading from");
switch (retval = sm_wtend ()) {
case RP_OK:
case RP_NO:
case RP_NDEL:
- die (NULL, "posting failed; %s", rp_string (retval));
- /* FALLTHRU */
+ fatal (NULL, "posting failed; %s", rp_string (retval));
+ break;
default:
- die (NULL, "unexpected response; %s", rp_string (retval));
+ fatal (NULL, "unexpected response; %s", rp_string (retval));
}
}
fcc (char *file, char *folder)
{
pid_t child_id;
- int i, status, argp;
+ int status, argp;
char fold[BUFSIZ];
char **arglist, *program;
printf (" %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder);
fflush (stdout);
- for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
- sleep (5);
-
+ child_id = fork();
switch (child_id) {
case NOTOK:
if (!verbose)
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)
puts("folder ok");
*/
static void
-die (char *what, char *fmt, ...)
+fatal (char *what, char *fmt, ...)
{
int err;
va_list ap;