don't pass through NOTIFY= unless it was given in the SMTP RCPT
[unix-history] / usr / src / usr.sbin / sendmail / src / usersmtp.c
index e0c4b31..4086589 100644 (file)
@@ -10,9 +10,9 @@
 
 #ifndef lint
 #ifdef SMTP
 
 #ifndef lint
 #ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.20 (Berkeley) %G% (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.40 (Berkeley) %G% (with SMTP)";
 #else
 #else
-static char sccsid[] = "@(#)usersmtp.c 8.20 (Berkeley) %G% (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.40 (Berkeley) %G% (without SMTP)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -79,6 +79,8 @@ smtpinit(m, mci, e)
 
        SmtpError[0] = '\0';
        CurHostName = mci->mci_host;            /* XXX UGLY XXX */
 
        SmtpError[0] = '\0';
        CurHostName = mci->mci_host;            /* XXX UGLY XXX */
+       if (CurHostName == NULL)
+               CurHostName = MyHostName;
        SmtpNeedIntro = TRUE;
        switch (mci->mci_state)
        {
        SmtpNeedIntro = TRUE;
        switch (mci->mci_state)
        {
@@ -216,9 +218,9 @@ tryhelo:
 \f/*
 **  ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
 **
 \f/*
 **  ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
 **
-**
 **     Parameters:
 **             line -- the response line.
 **     Parameters:
 **             line -- the response line.
+**             firstline -- set if this is the first line of the reply.
 **             m -- the mailer.
 **             mci -- the mailer connection info.
 **             e -- the envelope.
 **             m -- the mailer.
 **             mci -- the mailer connection info.
 **             e -- the envelope.
@@ -228,23 +230,38 @@ tryhelo:
 */
 
 void
 */
 
 void
-esmtp_check(line, m, mci, e)
+esmtp_check(line, firstline, m, mci, e)
        char *line;
        char *line;
+       bool firstline;
        MAILER *m;
        register MCI *mci;
        ENVELOPE *e;
 {
        MAILER *m;
        register MCI *mci;
        ENVELOPE *e;
 {
-       if (strlen(line) < 5)
-               return;
-       line += 4;
-       if (strncmp(line, "ESMTP ", 6) == 0)
-               mci->mci_flags |= MCIF_ESMTP;
+       register char *l;
+
+       for (l = line; (l = strchr(++l, 'E')) != NULL; )
+       {
+               if (strncmp(l, "ESMTP ", 6) == 0)
+               {
+                       mci->mci_flags |= MCIF_ESMTP;
+                       break;
+               }
+       }
+       for (l = line; (l = strchr(++l, '8')) != NULL; )
+       {
+               if (strncmp(l, "8BIT OK", 7) == 0)
+               {
+                       mci->mci_flags |= MCIF_8BITOK;
+                       break;
+               }
+       }
 }
 \f/*
 **  HELO_OPTIONS -- process the options on a HELO line.
 **
 **     Parameters:
 **             line -- the response line.
 }
 \f/*
 **  HELO_OPTIONS -- process the options on a HELO line.
 **
 **     Parameters:
 **             line -- the response line.
+**             firstline -- set if this is the first line of the reply.
 **             m -- the mailer.
 **             mci -- the mailer connection info.
 **             e -- the envelope.
 **             m -- the mailer.
 **             mci -- the mailer connection info.
 **             e -- the envelope.
@@ -254,14 +271,18 @@ esmtp_check(line, m, mci, e)
 */
 
 void
 */
 
 void
-helo_options(line, m, mci, e)
+helo_options(line, firstline, m, mci, e)
        char *line;
        char *line;
+       bool firstline;
        MAILER *m;
        register MCI *mci;
        ENVELOPE *e;
 {
        register char *p;
 
        MAILER *m;
        register MCI *mci;
        ENVELOPE *e;
 {
        register char *p;
 
+       if (firstline)
+               return;
+
        if (strlen(line) < 5)
                return;
        line += 4;
        if (strlen(line) < 5)
                return;
        line += 4;
@@ -281,6 +302,8 @@ helo_options(line, m, mci, e)
        }
        else if (strcasecmp(line, "expn") == 0)
                mci->mci_flags |= MCIF_EXPN;
        }
        else if (strcasecmp(line, "expn") == 0)
                mci->mci_flags |= MCIF_EXPN;
+       else if (strcasecmp(line, "x-dsn-3") == 0)
+               mci->mci_flags |= MCIF_DSN;
 }
 \f/*
 **  SMTPMAILFROM -- send MAIL command
 }
 \f/*
 **  SMTPMAILFROM -- send MAIL command
@@ -298,7 +321,8 @@ smtpmailfrom(m, mci, e)
 {
        int r;
        char *bufp;
 {
        int r;
        char *bufp;
-       char buf[MAXNAME];
+       char *bodytype;
+       char buf[MAXNAME + 1];
        char optbuf[MAXLINE];
 
        if (tTd(18, 2))
        char optbuf[MAXLINE];
 
        if (tTd(18, 2))
@@ -310,18 +334,56 @@ smtpmailfrom(m, mci, e)
        else
                strcpy(optbuf, "");
 
        else
                strcpy(optbuf, "");
 
-       if (e->e_bodytype != NULL)
+       bodytype = e->e_bodytype;
+       if (bitset(MCIF_8BITMIME, mci->mci_flags))
        {
        {
-               if (bitset(MCIF_8BITMIME, mci->mci_flags))
+               if (bodytype == NULL &&
+                   bitset(MM_MIME8BIT, MimeMode) &&
+                   bitset(EF_HAS8BIT, e->e_flags) &&
+                   !bitnset(M_8BITS, m->m_flags))
+                       bodytype = "8BITMIME";
+               if (bodytype != NULL)
                {
                        strcat(optbuf, " BODY=");
                {
                        strcat(optbuf, " BODY=");
-                       strcat(optbuf, e->e_bodytype);
+                       strcat(optbuf, bodytype);
                }
                }
-               else if (strcasecmp(e->e_bodytype, "7bit") != 0)
+       }
+       else if (bitnset(M_8BITS, m->m_flags) ||
+                !bitset(EF_HAS8BIT, e->e_flags) ||
+                (e->e_bodytype != NULL &&
+                 strcasecmp(e->e_bodytype, "7bit") == 0))
+       {
+               /* just pass it through */
+       }
+       else if (bitset(MM_CVTMIME, MimeMode) &&
+                (e->e_bodytype != NULL || !bitset(MM_PASS8BIT, MimeMode)))
+       {
+               /* must convert from 8bit MIME format to 7bit encoded */
+               mci->mci_flags |= MCIF_CVT8TO7;
+       }
+       else if (!bitset(MM_PASS8BIT, MimeMode))
+       {
+               /* cannot just send a 8-bit version */
+               usrerr("%s does not support 8BITMIME", mci->mci_host);
+               return EX_DATAERR;
+       }
+
+       if (bitset(MCIF_DSN, mci->mci_flags))
+       {
+               if (e->e_envid != NULL)
                {
                {
-                       /* cannot just send a 7-bit version */
-                       usrerr("%s does not support 8BITMIME", mci->mci_host);
-                       return EX_DATAERR;
+                       strcat(optbuf, " ENVID=");
+                       strcat(optbuf, e->e_envid);
+               }
+
+               /* RET= parameter */
+               if (bitset(EF_RET_PARAM, e->e_flags))
+               {
+                       strcat(optbuf, " RET=");
+                       if (bitset(EF_NO_BODY_RETN, e->e_flags))
+                               strcat(optbuf, "HDRS");
+                       else
+                               strcat(optbuf, "FULL");
                }
        }
 
                }
        }
 
@@ -344,7 +406,7 @@ smtpmailfrom(m, mci, e)
            !bitnset(M_NO_NULL_FROM, m->m_flags))
                (void) strcpy(buf, "");
        else
            !bitnset(M_NO_NULL_FROM, m->m_flags))
                (void) strcpy(buf, "");
        else
-               expand("\201g", buf, &buf[sizeof buf - 1], e);
+               expand("\201g", buf, sizeof buf, e);
        if (buf[0] == '<')
        {
                /* strip off <angle brackets> (put back on below) */
        if (buf[0] == '<')
        {
                /* strip off <angle brackets> (put back on below) */
@@ -377,13 +439,17 @@ smtpmailfrom(m, mci, e)
        }
        else if (r == 250)
        {
        }
        else if (r == 250)
        {
-               mci->mci_exitstat = EX_OK;
                return EX_OK;
        }
                return EX_OK;
        }
+       else if (r == 501 || r == 553)
+       {
+               /* syntax error in arguments */
+               smtpquit(m, mci, e);
+               return EX_DATAERR;
+       }
        else if (r == 552)
        {
                /* signal service unavailable */
        else if (r == 552)
        {
                /* signal service unavailable */
-               mci->mci_exitstat = EX_UNAVAILABLE;
                smtpquit(m, mci, e);
                return EX_UNAVAILABLE;
        }
                smtpquit(m, mci, e);
                return EX_UNAVAILABLE;
        }
@@ -391,14 +457,13 @@ smtpmailfrom(m, mci, e)
 #ifdef LOG
        if (LogLevel > 1)
        {
 #ifdef LOG
        if (LogLevel > 1)
        {
-               syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s",
-                       e->e_id, SmtpReplyBuffer);
+               syslog(LOG_CRIT, "%s: %s: SMTP MAIL protocol error: %s",
+                       e->e_id, mci->mci_host, SmtpReplyBuffer);
        }
 #endif
 
        /* protocol error -- close up */
        smtpquit(m, mci, e);
        }
 #endif
 
        /* protocol error -- close up */
        smtpquit(m, mci, e);
-       mci->mci_exitstat = EX_PROTOCOL;
        return EX_PROTOCOL;
 }
 \f/*
        return EX_PROTOCOL;
 }
 \f/*
@@ -424,12 +489,54 @@ smtprcpt(to, m, mci, e)
        ENVELOPE *e;
 {
        register int r;
        ENVELOPE *e;
 {
        register int r;
+       char optbuf[MAXLINE];
 
 
-       smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
+       strcpy(optbuf, "");
+       if (bitset(MCIF_DSN, mci->mci_flags))
+       {
+               /* NOTIFY= parameter */
+               if (bitset(QHASNOTIFY, to->q_flags))
+               {
+                       bool firstone = TRUE;
+
+                       strcat(optbuf, " NOTIFY=");
+                       if (bitset(QPINGONSUCCESS, to->q_flags))
+                       {
+                               strcat(optbuf, "SUCCESS");
+                               firstone = FALSE;
+                       }
+                       if (bitset(QPINGONFAILURE, to->q_flags))
+                       {
+                               if (!firstone)
+                                       strcat(optbuf, ",");
+                               strcat(optbuf, "FAILURE");
+                               firstone = FALSE;
+                       }
+                       if (bitset(QPINGONDELAY, to->q_flags))
+                       {
+                               if (!firstone)
+                                       strcat(optbuf, ",");
+                               strcat(optbuf, "DELAY");
+                               firstone = FALSE;
+                       }
+                       if (firstone)
+                               strcat(optbuf, "NEVER");
+               }
+
+               /* ORCPT= parameter */
+               if (to->q_orcpt != NULL)
+               {
+                       strcat(optbuf, " ORCPT=");
+                       strcat(optbuf, to->q_orcpt);
+               }
+       }
+
+       smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf);
 
        SmtpPhase = mci->mci_phase = "client RCPT";
        setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
        r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
 
        SmtpPhase = mci->mci_phase = "client RCPT";
        setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
        r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
+       setstatus(to, SmtpReplyBuffer);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        else if (REPLYTYPE(r) == 2)
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        else if (REPLYTYPE(r) == 2)
@@ -442,8 +549,8 @@ smtprcpt(to, m, mci, e)
 #ifdef LOG
        if (LogLevel > 1)
        {
 #ifdef LOG
        if (LogLevel > 1)
        {
-               syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s",
-                       e->e_id, SmtpReplyBuffer);
+               syslog(LOG_CRIT, "%s: %s: SMTP RCPT protocol error: %s",
+                       e->e_id, mci->mci_host, SmtpReplyBuffer);
        }
 #endif
 
        }
 #endif
 
@@ -464,7 +571,7 @@ smtprcpt(to, m, mci, e)
 */
 
 static jmp_buf CtxDataTimeout;
 */
 
 static jmp_buf CtxDataTimeout;
-static int     datatimeout();
+static void    datatimeout();
 
 smtpdata(m, mci, e)
        struct mailer *m;
 
 smtpdata(m, mci, e)
        struct mailer *m;
@@ -503,8 +610,8 @@ smtpdata(m, mci, e)
 #ifdef LOG
                if (LogLevel > 1)
                {
 #ifdef LOG
                if (LogLevel > 1)
                {
-                       syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s",
-                               e->e_id, SmtpReplyBuffer);
+                       syslog(LOG_CRIT, "%s: %s: SMTP DATA-1 protocol error: %s",
+                               e->e_id, mci->mci_host, SmtpReplyBuffer);
                }
 #endif
                smtprset(m, mci, e);
                }
 #endif
                smtprset(m, mci, e);
@@ -533,11 +640,17 @@ smtpdata(m, mci, e)
        timeout += e->e_nrcpts * 90;
        ev = setevent(timeout, datatimeout, 0);
 
        timeout += e->e_nrcpts * 90;
        ev = setevent(timeout, datatimeout, 0);
 
-       /* now output the actual message */
-       (*e->e_puthdr)(mci, e);
-       putline("\n", mci);
+       /*
+       **  Output the actual message.
+       */
+
+       (*e->e_puthdr)(mci, e->e_header, e);
        (*e->e_putbody)(mci, e, NULL);
 
        (*e->e_putbody)(mci, e, NULL);
 
+       /*
+       **  Cleanup after sending message.
+       */
+
        clrevent(ev);
 
        if (ferror(mci->mci_out))
        clrevent(ev);
 
        if (ferror(mci->mci_out))
@@ -577,15 +690,15 @@ smtpdata(m, mci, e)
 #ifdef LOG
        if (LogLevel > 1)
        {
 #ifdef LOG
        if (LogLevel > 1)
        {
-               syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s",
-                       e->e_id, SmtpReplyBuffer);
+               syslog(LOG_CRIT, "%s: %s: SMTP DATA-2 protocol error: %s",
+                       e->e_id, mci->mci_host, SmtpReplyBuffer);
        }
 #endif
        return (EX_PROTOCOL);
 }
 
 
        }
 #endif
        return (EX_PROTOCOL);
 }
 
 
-static int
+static void
 datatimeout()
 {
        longjmp(CtxDataTimeout, 1);
 datatimeout()
 {
        longjmp(CtxDataTimeout, 1);
@@ -810,8 +923,8 @@ reply(m, mci, e, timeout, pfunc)
                        nmessage("050 %s", bufp);
 
                /* process the line */
                        nmessage("050 %s", bufp);
 
                /* process the line */
-               if (pfunc != NULL && !firstline)
-                       (*pfunc)(bufp, m, mci, e);
+               if (pfunc != NULL)
+                       (*pfunc)(bufp, firstline, m, mci, e);
 
                firstline = FALSE;
 
 
                firstline = FALSE;