]> diplodocus.org Git - nmh/blobdiff - uip/post.c
Alter HasSuffixC()'s char * to be const.
[nmh] / uip / post.c
index 239ecdfcba6373e30336c7e8e3a4e028c45ec672..553a22587932930c34750a1efdaf166ebd2246f6 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * post.c -- enter messages into the mail transport system
  *
 #include <h/dropsbr.h>
 #include <h/mime.h>
 #include <h/utils.h>
-
 #include <h/tws.h>
 #include <h/mts.h>
 
-#include <errno.h>
-#include <signal.h>
-
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
 # define TLSminc(a)   0
 #endif /* TLS_SUPPORT */
 
+#ifndef OAUTH_SUPPORT
+# define OAUTHminc(a)  (a)
+#else /* OAUTH_SUPPORT */
+# define OAUTHminc(a)  0
+#endif /* OAUTH_SUPPORT */
+
 #define FCCS           10      /* max number of fccs allowed */
 
 /* In the following array of structures, the numeric second field of the
     X("server host", 6, SERVSW) /* specify alternate SMTP server */ \
     X("snoop", -5, SNOOPSW) /* snoop the SMTP transaction */ \
     X("partno", -6, PARTSW) \
-    X("queued", -6, QUEUESW) \
-    X("sasl", SASLminc(-4), SASLSW) \
-    X("nosasl", SASLminc(-6), NOSASLSW) \
-    X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
-    X("saslmech", SASLminc(-5), SASLMECHSW) \
+    X("sasl", SASLminc(4), SASLSW) \
+    X("nosasl", SASLminc(6), NOSASLSW) \
+    X("saslmech", SASLminc(5), SASLMECHSW) \
     X("user", SASLminc(-4), USERSW) \
-    X("port server port name/number", 4, PORTSW) \
+    X("port server submission port name/number", 4, PORTSW) \
     X("tls", TLSminc(-3), TLSSW) \
+    X("initialtls", TLSminc(-10), INITTLSSW) \
     X("notls", TLSminc(-5), NTLSSW) \
     X("fileproc", -4, FILEPROCSW) \
     X("mhlproc", -3, MHLPROCSW) \
+    X("sendmail program", 0, MTSSM) \
     X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \
+    X("credentials legacy|file:filename", 0, CREDENTIALSSW) \
     X("messageid localname|random", 2, MESSAGEIDSW) \
+    X("authservice auth-service-name", OAUTHminc(-11), AUTHSERVICESW) \
+    X("oauthcredfile credential-file", OAUTHminc(-7), OAUTHCREDFILESW) \
+    X("oauthclientid client-id", OAUTHminc(-12), OAUTHCLIDSW) \
+    X("oauthclientsecret client-secret", OAUTHminc(-12), OAUTHCLSECSW) \
+    X("oauthauthendpoint authentication-endpoint", OAUTHminc(-6), OAUTHAUTHENDSW) \
+    X("oauthredirect redirect-uri", OAUTHminc(-6), OAUTHREDIRSW) \
+    X("oauthtokenendpoint token-endpoint", OAUTHminc(-6), OAUTHTOKENDSW) \
+    X("oauthscope scope", OAUTHminc(-6), OAUTHSCOPESW) \
 
 #define X(sw, minchars, id) id,
 DEFINE_SWITCH_ENUM(POST);
@@ -103,6 +113,26 @@ DEFINE_SWITCH_ARRAY(POST, switches);
 #undef X
 
 
+/*
+ * Mapping between command-line switches and profile entries, communicated
+ * from 'send'.  We use a service name of 'post' internally.
+ */
+
+static struct oauth_profile {
+    const char *profname;
+    int switchnum;
+    const char *value;
+} oauthswitches[] = {
+    { "oauth-%s-credential-file", OAUTHCREDFILESW, NULL },
+    { "oauth-%s-client_id", OAUTHCLIDSW, NULL },
+    { "oauth-%s-client_secret", OAUTHCLSECSW, NULL },
+    { "oauth-%s-auth_endpoint", OAUTHAUTHENDSW, NULL },
+    { "oauth-%s-redirect_uri", OAUTHREDIRSW, NULL },
+    { "oauth-%s-token_endpoint", OAUTHTOKENDSW, NULL },
+    { "oauth-%s-scope", OAUTHSCOPESW, NULL },
+    { NULL, 0, NULL }
+};
+
 struct headers {
     char *value;
     unsigned int flags;
@@ -126,6 +156,8 @@ struct headers {
 #define        HDCC  0x0400    /* another undocumented feature                       */
 #define HONE  0x0800   /* Only (zero or) one address allowed                 */
 #define HEFM  0x1000   /* Envelope-From: header                              */
+#define HMIM  0x2000    /* MIME-Version: header                               */
+#define HCTE  0x4000    /* Content-Transfer-Encoding: header                  */
 
 /*
  * flags for headers->set
@@ -138,7 +170,7 @@ struct headers {
 #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: */
-
+#define MMIM  0x0100    /* We've seen Mime-Version:  */
 
 static struct headers NHeaders[] = {
     { "Return-Path",   HBAD,                0 },
@@ -155,6 +187,8 @@ static struct headers NHeaders[] = {
     { "Message-ID",    HBAD,                0 },
     { "Fcc",           HFCC,                0 },
     { "Envelope-From", HADR|HONE|HEFM,      MEFM },
+    { "MIME-Version",  HMIM,                MMIM },
+    { "Content-Transfer-Encoding",  HCTE,   0 },
     { NULL,            0,                   0 }
 };
 
@@ -178,6 +212,8 @@ static struct headers RHeaders[] = {
     { "Bcc",               HADR|HTRY|HBCC|HNIL, 0 },
     { "Fcc",               HIGN,                0 },
     { "Envelope-From",     HADR|HONE|HEFM,      MEFM },
+    { "MIME-Version",      HMIM,                MMIM },
+    { "Content-Transfer-Encoding",  HCTE,       0 },
     { NULL,                0,                   0 }
 };
 
@@ -200,11 +236,10 @@ 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 char *port="submission";        /* Name of server port for SMTP submission */
+static int tls=-1;             /* Use TLS for encryption                */
 static int fromcount=0;                /* Count of addresses on From: header    */
 static int seensender=0;       /* Have we seen a Sender: header?        */
 
@@ -225,10 +260,11 @@ 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 */
 static char *fccfold[FCCS];    /* foldernames for FCC'ing       */
+enum encoding { UNKNOWN = 0, BINARY = 1, SEVENBIT = 7, EIGHTBIT = 8 };
+static enum encoding cte = UNKNOWN;
 
 static struct headers  *hdrtab;        /* table for the message we're doing */
 
@@ -241,17 +277,14 @@ static int snoop      = 0;
 static char *clientsw = NULL;
 static char *serversw = NULL;
 
-extern struct smtp sm_reply;
-
 static char prefix[] = "----- =_aaaaaaaaaa";
 
 static char *partno = NULL;
-static int queued = 0;
 
 /*
  * static prototypes
  */
-static void putfmt (char *, char *, FILE *);
+static void putfmt (char *, char *, int *, FILE *);
 static void start_headers (void);
 static void finish_headers (FILE *);
 static int get_header (char *, struct headers *);
@@ -263,14 +296,14 @@ static void anno (void);
 static int annoaux (struct mailname *);
 static void insert_fcc (struct headers *, char *);
 static void make_bcc_file (int);
-static void verify_all_addresses (int, char *);
+static void verify_all_addresses (int, int, char *, 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, char *);
+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);
 static void do_addresses (int, int);
@@ -280,28 +313,22 @@ static int find_prefix (void);
 int
 main (int argc, char **argv)
 {
-    int state, compnum, dashstuff = 0;
+    int state, compnum, dashstuff = 0, swnum, oauth_flag = 0;
+    int eai = 0; /* use Email Address Internationalization (EAI) (SMTPUTF8) */
     char *cp, *msg = NULL, **argp, **arguments, *envelope;
-    char buf[BUFSIZ], name[NAMESZ];
+    char buf[BUFSIZ], name[NAMESZ], *auth_svc = NULL;
     FILE *in, *out;
     m_getfld_state_t gstate = 0;
 
-#ifdef LOCALE
-    setlocale(LC_ALL, "");
-#endif
-    invo_name = r1bindex (argv[0], '/');
-
-    /* foil search of user profile/context */
-    if (context_foil (NULL) == -1)
-       done (1);
+    if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; }
 
-    mts_init (invo_name);
+    mts_init ();
     arguments = getarguments (invo_name, argc, argv, 0);
     argp = arguments;
 
     while ((cp = *argp++)) {
        if (*cp == '-') {
-           switch (smatch (++cp, switches)) {
+           switch ((swnum = smatch (++cp, switches))) {
                case AMBIGSW: 
                    ambigsw (cp, switches);
                    done (1);
@@ -434,10 +461,6 @@ main (int argc, char **argv)
                        adios (NULL, "missing argument to %s", argp[-2]);
                    continue;
 
-               case QUEUESW:
-                   queued++;
-                   continue;
-               
                case SASLSW:
                    sasl++;
                    continue;
@@ -446,17 +469,45 @@ main (int argc, char **argv)
                    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 == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);
                    continue;
-               
+
+               case AUTHSERVICESW:
+                   if (!(auth_svc = *argp++) || *auth_svc == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   oauth_flag++;
+                   continue;
+
+               case OAUTHCREDFILESW:
+               case OAUTHCLIDSW:
+               case OAUTHCLSECSW:
+               case OAUTHAUTHENDSW:
+               case OAUTHREDIRSW:
+               case OAUTHTOKENDSW:
+               case OAUTHSCOPESW:
+               {
+                   int i;
+
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+
+                   for (i = 0; oauthswitches[i].profname != NULL; i++) {
+                       if (oauthswitches[i].switchnum == swnum) {
+                           oauthswitches[i].value = cp;
+                           break;
+                       }
+                   }
+
+                   if (oauthswitches[i].profname == NULL)
+                       adios (NULL, "internal error: cannot map switch %s "
+                              "to profile entry", argp[-2]);
+
+                   oauth_flag++;
+                   continue;
+               }
+
                case USERSW:
                    if (!(user = *argp++) || *user == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);
@@ -468,7 +519,11 @@ main (int argc, char **argv)
                    continue;
 
                case TLSSW:
-                   tls++;
+                   tls = 1;
+                   continue;
+
+               case INITTLSSW:
+                   tls = 2;
                    continue;
 
                case NTLSSW:
@@ -487,12 +542,25 @@ main (int argc, char **argv)
                    mhlproc = cp;
                    continue;
 
+               case MTSSM:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                    sendmail = cp;
+                   continue;
+
                case MTSSW:
                    if (!(cp = *argp++) || *cp == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);
                     save_mts_method (cp);
                    continue;
 
+               case CREDENTIALSSW: {
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   add_profile_entry ("credentials", cp);
+                   continue;
+               }
+
                case MESSAGEIDSW:
                    if (!(cp = *argp++) || *cp == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);
@@ -527,15 +595,12 @@ main (int argc, char **argv)
            if ((out = fopen ("/dev/null", "w")) == NULL)
                adios ("/dev/null", "unable to open");
        } else {
-            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");
-                }
-            }
+           char *cp = m_mktemp2(NULL, invo_name, NULL, &out);
+           if (cp == NULL) {
+               adios(NULL, "unable to create temporary file in %s",
+                     get_temp_dir());
+           }
             strncpy(tmpfil, cp, sizeof(tmpfil));
-           chmod (tmpfil, 0600);
        }
     }
 
@@ -546,14 +611,14 @@ main (int argc, char **argv)
        switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
            case FLD: 
            case FLDPLUS: 
-               compnum++;
+                compnum++;
                cp = add (buf, NULL);
                while (state == FLDPLUS) {
                    bufsz = sizeof buf;
                    state = m_getfld (&gstate, name, buf, &bufsz, in);
                    cp = add (buf, cp);
                }
-               putfmt (name, cp, out);
+               putfmt (name, cp, &eai, out);
                free (cp);
                continue;
 
@@ -612,10 +677,50 @@ main (int argc, char **argv)
        envelope = from;
     }
 
+    if (tls == -1) {
+#ifdef TLS_SUPPORT
+       /*
+        * The user didn't specify any of the tls switches.  Try to
+        * help them by implying -initialtls if they're using port 465
+        * (smtps, until IANA revoked that registration in 1998).
+        */
+       tls = ! strcmp (port, "465")  ||  ! strcasecmp (port, "smtps")
+           ?  2
+           :  0;
+#else  /* ! TLS_SUPPORT */
+       tls = 0;
+#endif /* ! TLS_SUPPORT */
+    }
+
+    /*
+     * If we were given any oauth flags, store the appropriate profile
+     * entries and make sure an authservice was given (we have to do this
+     * here because we aren't guaranteed the authservice will be given on
+     * the command line before the other OAuth flags are given).
+     */
+
+    if (oauth_flag) {
+       int i;
+       char sbuf[128];
+
+       if (auth_svc == NULL) {
+           adios(NULL, "No authentication service given with -authservice");
+       }
+
+       for (i = 0; oauthswitches[i].profname != NULL; i++) {
+               if (oauthswitches[i].value != NULL) {
+                   snprintf(sbuf, sizeof(sbuf),
+                   oauthswitches[i].profname, auth_svc);
+                   sbuf[sizeof(sbuf) - 1] = '\0';
+                   add_profile_entry(sbuf, oauthswitches[i].value);
+               }
+       }
+    }
+
     /* If we are doing a "whom" check */
     if (whomsw) {
        /* This won't work with MTS_SENDMAIL_PIPE. */
-       verify_all_addresses (1, envelope);
+        verify_all_addresses (1, eai, envelope, oauth_flag, auth_svc);
        done (0);
     }
 
@@ -627,22 +732,27 @@ main (int argc, char **argv)
                   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);
+               verify_all_addresses (verbose, eai, envelope, oauth_flag,
+                                      auth_svc);
            }
-           post (tmpfil, 0, verbose, envelope);
+           post (tmpfil, 0, verbose, eai, envelope, oauth_flag, auth_svc);
        }
-       post (bccfil, 1, verbose, envelope);
-       unlink (bccfil);
+       post (bccfil, 1, verbose, eai, envelope, oauth_flag, auth_svc);
+       (void) m_unlink (bccfil);
     } else {
-       post (tmpfil, 0, isatty (1), envelope);
+       post (tmpfil, 0, isatty (1), eai, envelope, oauth_flag, auth_svc);
     }
 
     p_refile (tmpfil);
-    unlink (tmpfil);
+    (void) m_unlink (tmpfil);
+
+    if (verbose) {
+       if (partno)
+           printf ("Partial Message #%s Processed\n", partno);
+       else
+           printf ("Message Processed\n");
+    }
 
-    if (verbose)
-       printf (partno ? "Partial Message #%s Processed\n" : "Message Processed\n",
-               partno);
     done (0);
     return 1;
 }
@@ -653,11 +763,11 @@ main (int argc, char **argv)
  */
 
 static void
-putfmt (char *name, char *str, FILE *out)
+putfmt (char *name, char *str, int *eai, FILE *out)
 {
     int count, grp, i, keep;
     char *cp, *pp, *qp;
-    char namep[BUFSIZ];
+    char namep[BUFSIZ], error[BUFSIZ];
     struct mailname *mp = NULL, *np = NULL;
     struct headers *hdr;
 
@@ -670,16 +780,31 @@ putfmt (char *name, char *str, FILE *out)
        return;
     }
 
+    if (! *eai) {
+        /* Check each header field value to see if it has any 8-bit characters.
+           If it does, enable EAI support. */
+        if (contains8bit(str, NULL)) {
+            if (verbose) {
+                printf ("EAI/SMTPUTF8 enabled\n");
+            }
+
+            /* Enable SMTPUTF8. */
+            *eai = 1;
+
+            /* Enable passing of utf-8 setting to getname()/getadrx(). */
+            enable_eai();
+        }
+    }
+
     if ((i = get_header (name, hdrtab)) == NOTOK) {
-       if (strncasecmp (name, "nmh-", 4)) {
+        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';
+                TrimSuffixC(str, '\n');
                if (! whomsw) {
                    advise (NULL, "ignoring header line -- %s: %s", name, str);
                }
@@ -701,37 +826,49 @@ putfmt (char *name, char *str, FILE *out)
     msgflags |= (hdr->set & ~(MVIS | MINV));
 
     if (hdr->flags & HSUB)
-       subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
+       subject = subject ? add (str, add ("\t", subject)) : mh_xstrdup(str);
     if (hdr->flags & HFCC) {
        if ((cp = strrchr(str, '\n')))
            *cp = 0;
-       for (cp = pp = str; (cp = strchr(pp, ',')); pp = cp) {
+       for (pp = str; (cp = strchr(pp, ',')); pp = cp) {
            *cp++ = 0;
            insert_fcc (hdr, pp);
        }
        insert_fcc (hdr, pp);
        return;
     }
-
+    if (hdr->flags & HCTE) {
+        if (strncasecmp (str, "7bit", 4) == 0) {
+            cte = SEVENBIT;
+        } else if (strncasecmp (str, "8bit", 4) == 0) {
+            cte = EIGHTBIT;
+        } else if (strncasecmp (str, "binary", 6) == 0) {
+            cte = BINARY;
+        }
+    }
     if (!(hdr->flags & HADR)) {
        fprintf (out, "%s: %s", name, str);
        return;
     }
 
     tmpaddrs.m_next = NULL;
-    for (count = 0; (cp = getname (str)); count++)
-       if ((mp = getm (cp, NULL, 0, AD_HOST, NULL))) {
+
+    for (count = 0; (cp = getname (str)); count++) {
+       if ((mp = getm (cp, NULL, 0, error, sizeof(error)))) {
            if (tmpaddrs.m_next)
                np->m_next = mp;
            else
                tmpaddrs.m_next = mp;
            np = mp;
        }
-       else
+       else {
+           admonish(cp, "%s", error);
            if (hdr->flags & HTRY)
                badadr++;
            else
                badmsg++;
+       }
+    }
 
     if (count < 1) {
        if (hdr->flags & HNIL)
@@ -772,7 +909,8 @@ putfmt (char *name, char *str, FILE *out)
            if (np->m_gname)
                putgrp (namep, np->m_gname, out, hdr->flags);
            while ((cp = getname (pp))) {
-               if (!(mp = getm (cp, NULL, 0, AD_HOST, NULL))) {
+               if (!(mp = getm (cp, NULL, 0, error, sizeof(error)))) {
+                   admonish(cp, "%s", error);
                    badadr++;
                    continue;
                }
@@ -921,9 +1059,6 @@ putfmt (char *name, char *str, FILE *out)
 static void
 start_headers (void)
 {
-    char  *cp, sigbuf[BUFSIZ];
-    struct mailname *mp;
-
     time (&tclock);
 
     /*
@@ -934,21 +1069,6 @@ start_headers (void)
     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, getlocaladdr());
-       if ((cp = getname (signature)) == NULL)
-           adios (NULL, "getname () failed -- you lose extraordinarily big");
-       if ((mp = getm (cp, NULL, 0, AD_HOST, NULL)) == NULL)
-           adios (NULL, "bad signature '%s'", sigbuf);
-       mnfree (mp);
-       while (getname (""))
-           continue;
-    } else {
-       strncpy (signature, getlocaladdr(), sizeof(signature));
-    }
 }
 
 
@@ -1097,7 +1217,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);
+       mp->m_pers = mh_xstrdup(aka);
     if (format) {
        if (mp->m_gname) {
            snprintf (buffer, sizeof(buffer), "%s;", mp->m_gname);
@@ -1213,7 +1333,7 @@ pl (void)
     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');
 }
 
 
@@ -1269,7 +1389,7 @@ insert_fcc (struct headers *hdr, char *pp)
 
     if (fccind >= FCCS)
        adios (NULL, "too many %ss", hdr->value);
-    fccfold[fccind++] = getcpy (cp);
+    fccfold[fccind++] = mh_xstrdup(cp);
 }
 
 /*
@@ -1285,8 +1405,9 @@ make_bcc_file (int dashstuff)
     FILE *out;
     char *tfile = NULL, *program;
 
-    tfile = m_mktemp2(NULL, "bccs", NULL, &out);
-    if (tfile == NULL) adios("bcc", "unable to create temporary file");
+    if ((tfile = m_mktemp2(NULL, "bccs", NULL, &out)) == NULL) {
+       adios(NULL, "unable to create temporary file in %s", get_temp_dir());
+    }
     strncpy (bccfil, tfile, sizeof(bccfil));
 
     fprintf (out, "From: %s\n", fullfrom);
@@ -1491,9 +1612,9 @@ do_addresses (int bccque, int talk)
  */
 
 static void
-post (char *file, int bccque, int talk, char *envelope)
+post (char *file, int bccque, int talk, int eai, char *envelope,
+      int oauth_flag, char *auth_svc)
 {
-    int fd;
     int        retval, i;
     pid_t child_id;
 
@@ -1539,15 +1660,33 @@ post (char *file, int bccque, int talk, char *envelope)
                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)))
+        const int fd = open (file, O_RDONLY);
+        int eightbit = 0;
+
+        if (fd == NOTOK) {
+          die (file, "unable to re-open");
+        }
+
+        if (msgflags & MMIM  &&  cte != UNKNOWN) {
+            /* MIME message with C-T-E header.  (BINARYMIME isn't
+               supported, use 8BITMIME instead for binary.) */
+            eightbit = cte != SEVENBIT;
+        } else {
+            if (scan_input (fd, &eightbit) == NOTOK) {
+                close (fd);
+                die (file, "problem reading from");
+            }
+        }
+
+       if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
+                                       verbose, snoop, sasl, saslmech, user,
+                                       oauth_flag ? auth_svc : NULL, tls))
+               || rp_isbad (retval = sm_winit (envelope, eai, eightbit))) {
+           close (fd);
            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);
@@ -1571,19 +1710,25 @@ post (char *file, int bccque, int talk, char *envelope)
 /* Address Verification */
 
 static void
-verify_all_addresses (int talk, char *envelope)
+verify_all_addresses (int talk, int eai, char *envelope, int oauth_flag,
+                      char *auth_svc)
 {
     int retval;
     struct mailname *lp;
 
     sigon ();
 
-    if (!whomsw || checksw)
+    if (!whomsw || checksw) {
+        /* Not sending message body, so don't need to use 8BITMIME. */
+        const int eightbit = 0;
+
        if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
-                                       verbose, snoop, queued, sasl,
-                                       saslssf, saslmech, user, tls))
-               || rp_isbad (retval = sm_winit (envelope)))
+                                       verbose, snoop, sasl, saslmech, user,
+                                       oauth_flag ? auth_svc : NULL, tls))
+               || rp_isbad (retval = sm_winit (envelope, eai, eightbit))) {
            die (NULL, "problem initializing server; %s", rp_string (retval));
+       }
+    }
 
     if (talk && !whomsw)
        printf (" -- Address Verification --\n");
@@ -1717,9 +1862,9 @@ sigser (int i)
 {
     NMH_UNUSED (i);
 
-    unlink (tmpfil);
+    (void) m_unlink (tmpfil);
     if (msgflags & MINV)
-       unlink (bccfil);
+       (void) m_unlink (bccfil);
 
     if (!whomsw || checksw)
        sm_end (NOTOK);
@@ -1841,9 +1986,9 @@ die (char *what, char *fmt, ...)
 {
     va_list ap;
 
-    unlink (tmpfil);
+    (void) m_unlink (tmpfil);
     if (msgflags & MINV)
-       unlink (bccfil);
+       (void) m_unlink (bccfil);
 
     if (!whomsw || checksw)
        sm_end (NOTOK);