more cleanup for DSN drafts
[unix-history] / usr / src / usr.sbin / sendmail / src / envelope.c
index c4aca1a..8523480 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)envelope.c 8.33 (Berkeley) %G%";
+static char sccsid[] = "@(#)envelope.c 8.56 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -74,16 +74,20 @@ dropenvelope(e)
        register ENVELOPE *e;
 {
        bool queueit = FALSE;
        register ENVELOPE *e;
 {
        bool queueit = FALSE;
-       bool saveit = bitset(EF_FATALERRS, e->e_flags);
+       bool failure_return = FALSE;
+       bool success_return = FALSE;
        register ADDRESS *q;
        char *id = e->e_id;
        char buf[MAXLINE];
 
        if (tTd(50, 1))
        {
        register ADDRESS *q;
        char *id = e->e_id;
        char buf[MAXLINE];
 
        if (tTd(50, 1))
        {
+               extern void printenvflags();
+
                printf("dropenvelope %x: id=", e);
                xputs(e->e_id);
                printf("dropenvelope %x: id=", e);
                xputs(e->e_id);
-               printf(", flags=0x%x\n", e->e_flags);
+               printf(", flags=");
+               printenvflags(e);
                if (tTd(50, 10))
                {
                        printf("sendq=");
                if (tTd(50, 10))
                {
                        printf("sendq=");
@@ -116,34 +120,46 @@ dropenvelope(e)
        {
                if (bitset(QQUEUEUP, q->q_flags))
                        queueit = TRUE;
        {
                if (bitset(QQUEUEUP, q->q_flags))
                        queueit = TRUE;
-               if (!bitset(QDONTSEND, q->q_flags) &&
-                   bitset(QBADADDR, q->q_flags))
+
+               /* see if a notification is needed */
+               if (bitset(QBADADDR, q->q_flags) &&
+                   bitset(QPINGONFAILURE, q->q_flags))
                {
                {
-                       if (q->q_owner == NULL &&
-                           strcmp(e->e_from.q_paddr, "<>") != 0)
+                       failure_return = TRUE;
+                       if (q->q_owner == NULL && !emptyaddr(&e->e_from))
                                (void) sendtolist(e->e_from.q_paddr, NULL,
                                (void) sendtolist(e->e_from.q_paddr, NULL,
-                                                 &e->e_errorqueue, e);
+                                                 &e->e_errorqueue, 0, e);
+               }
+               else if (bitset(QPINGONSUCCESS, q->q_flags) &&
+                        ((bitset(QSENT, q->q_flags) &&
+                          bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
+                         bitset(QRELAYED|QEXPLODED, q->q_flags)))
+               {
+                       success_return = TRUE;
                }
        }
 
                }
        }
 
+       if (e->e_class < 0)
+               e->e_flags |= EF_NO_BODY_RETN;
+
        /*
        **  See if the message timed out.
        */
 
        if (!queueit)
                /* nothing to do */ ;
        /*
        **  See if the message timed out.
        */
 
        if (!queueit)
                /* nothing to do */ ;
-       else if (curtime() > e->e_ctime + TimeOuts.to_q_return)
+       else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
        {
                (void) sprintf(buf, "Cannot send message for %s",
        {
                (void) sprintf(buf, "Cannot send message for %s",
-                       pintvl(TimeOuts.to_q_return, FALSE));
+                       pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
                if (e->e_message != NULL)
                        free(e->e_message);
                e->e_message = newstr(buf);
                message(buf);
                e->e_flags |= EF_CLRQUEUE;
                if (e->e_message != NULL)
                        free(e->e_message);
                e->e_message = newstr(buf);
                message(buf);
                e->e_flags |= EF_CLRQUEUE;
-               saveit = TRUE;
+               failure_return = TRUE;
                fprintf(e->e_xfp, "Message could not be delivered for %s\n",
                fprintf(e->e_xfp, "Message could not be delivered for %s\n",
-                       pintvl(TimeOuts.to_q_return, FALSE));
+                       pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
                fprintf(e->e_xfp, "Message will be deleted from queue\n");
                for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                {
                fprintf(e->e_xfp, "Message will be deleted from queue\n");
                for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                {
@@ -151,32 +167,61 @@ dropenvelope(e)
                                q->q_flags |= QBADADDR;
                }
        }
                                q->q_flags |= QBADADDR;
                }
        }
-       else if (TimeOuts.to_q_warning > 0 &&
-           curtime() > e->e_ctime + TimeOuts.to_q_warning)
+       else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
+           curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
        {
        {
-               if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
+               bool delay_return = FALSE;
+
+               for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+               {
+                       if (bitset(QQUEUEUP, q->q_flags) &&
+                           bitset(QPINGONDELAY, q->q_flags))
+                       {
+                               q->q_flags |= QREPORT;
+                               delay_return = TRUE;
+                       }
+               }
+               if (delay_return &&
+                   !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
                    e->e_class >= 0 &&
                    e->e_class >= 0 &&
-                   strcmp(e->e_from.q_paddr, "<>") != 0)
+                   strcmp(e->e_from.q_paddr, "<>") != 0 &&
+                   strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
+                   (strlen(e->e_from.q_paddr) <= 8 ||
+                    strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
                {
                        (void) sprintf(buf,
                {
                        (void) sprintf(buf,
-                               "warning: cannot send message for %s",
-                               pintvl(TimeOuts.to_q_warning, FALSE));
+                               "Warning: cannot send message for %s",
+                               pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
                        if (e->e_message != NULL)
                                free(e->e_message);
                        e->e_message = newstr(buf);
                        message(buf);
                        e->e_flags |= EF_WARNING;
                        if (e->e_message != NULL)
                                free(e->e_message);
                        e->e_message = newstr(buf);
                        message(buf);
                        e->e_flags |= EF_WARNING;
-                       saveit = TRUE;
+                       failure_return = TRUE;
                }
                fprintf(e->e_xfp,
                        "Warning: message still undelivered after %s\n",
                }
                fprintf(e->e_xfp,
                        "Warning: message still undelivered after %s\n",
-                       pintvl(TimeOuts.to_q_warning, FALSE));
+                       pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
                fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
                fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
-                       pintvl(TimeOuts.to_q_return, FALSE));
+                       pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+       }
+
+       if (tTd(50, 2))
+               printf("failure_return=%d success_return=%d queueit=%d\n",
+                       failure_return, success_return, queueit);
+
+       /*
+       **  If we had some fatal error, but no addresses are marked as
+       **  bad, mark them _all_ as bad.
+       */
+
+       if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
+       {
+               failure_return = TRUE;
                for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                {
                for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                {
-                       if (bitset(QQUEUEUP, q->q_flags))
-                               q->q_flags |= QREPORT;
+                       if (!bitset(QDONTSEND, q->q_flags))
+                               q->q_flags |= QBADADDR;
                }
        }
 
                }
        }
 
@@ -184,21 +229,30 @@ dropenvelope(e)
        **  Send back return receipts as requested.
        */
 
        **  Send back return receipts as requested.
        */
 
-       if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
+/*
+       if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)
+           && !bitset(PRIV_NORECEIPTS, PrivacyFlags))
+*/
+       if (e->e_receiptto == NULL)
+               e->e_receiptto = e->e_from.q_paddr;
+       if (success_return && !failure_return &&
+           !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
+           strcmp(e->e_receiptto, "<>") != 0)
        {
                auto ADDRESS *rlist = NULL;
 
        {
                auto ADDRESS *rlist = NULL;
 
-               (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, e);
+               e->e_flags |= EF_SENDRECEIPT;
+               (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e);
                (void) returntosender("Return receipt", rlist, FALSE, e);
                (void) returntosender("Return receipt", rlist, FALSE, e);
-               e->e_flags &= ~EF_SENDRECEIPT;
        }
        }
+       e->e_flags &= ~EF_SENDRECEIPT;
 
        /*
        **  Arrange to send error messages if there are fatal errors.
        */
 
 
        /*
        **  Arrange to send error messages if there are fatal errors.
        */
 
-       if (saveit && e->e_errormode != EM_QUIET)
-               savemail(e);
+       if (failure_return && e->e_errormode != EM_QUIET)
+               savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
 
        /*
        **  Arrange to send warning messages to postmaster as requested.
 
        /*
        **  Arrange to send warning messages to postmaster as requested.
@@ -209,7 +263,7 @@ dropenvelope(e)
        {
                auto ADDRESS *rlist = NULL;
 
        {
                auto ADDRESS *rlist = NULL;
 
-               (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, e);
+               (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
                (void) returntosender(e->e_message, rlist, FALSE, e);
        }
 
                (void) returntosender(e->e_message, rlist, FALSE, e);
        }
 
@@ -221,9 +275,14 @@ dropenvelope(e)
            bitset(EF_CLRQUEUE, e->e_flags))
        {
                if (tTd(50, 1))
            bitset(EF_CLRQUEUE, e->e_flags))
        {
                if (tTd(50, 1))
-                       printf("\n===== Dropping [dq]f%s =====\n\n", e->e_id);
-               if (e->e_df != NULL)
-                       xunlink(e->e_df);
+               {
+                       extern void printenvflags();
+
+                       printf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=",
+                               e->e_id, queueit);
+                       printenvflags(e);
+               }
+               xunlink(queuename(e, 'd'));
                xunlink(queuename(e, 'q'));
 
 #ifdef LOG
                xunlink(queuename(e, 'q'));
 
 #ifdef LOG
@@ -246,9 +305,10 @@ dropenvelope(e)
 
        /* make sure that this envelope is marked unused */
        if (e->e_dfp != NULL)
 
        /* make sure that this envelope is marked unused */
        if (e->e_dfp != NULL)
-               (void) xfclose(e->e_dfp, "dropenvelope", e->e_df);
+               (void) xfclose(e->e_dfp, "dropenvelope df", e->e_id);
        e->e_dfp = NULL;
        e->e_dfp = NULL;
-       e->e_id = e->e_df = NULL;
+       e->e_id = NULL;
+       e->e_flags &= ~EF_HAS_DF;
 }
 \f/*
 **  CLEARENVELOPE -- clear an envelope without unlocking
 }
 \f/*
 **  CLEARENVELOPE -- clear an envelope without unlocking
@@ -285,7 +345,7 @@ clearenvelope(e, fullclear)
                if (e->e_xfp != NULL)
                        (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
                if (e->e_dfp != NULL)
                if (e->e_xfp != NULL)
                        (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
                if (e->e_dfp != NULL)
-                       (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df);
+                       (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_id);
                e->e_xfp = e->e_dfp = NULL;
        }
 
                e->e_xfp = e->e_dfp = NULL;
        }
 
@@ -462,11 +522,14 @@ openxscript(e)
                if (fd < 0)
                        syserr("!Can't open /dev/null");
        }
                if (fd < 0)
                        syserr("!Can't open /dev/null");
        }
-       e->e_xfp = fdopen(fd, "w");
+       e->e_xfp = fdopen(fd, "a");
        if (e->e_xfp == NULL)
        if (e->e_xfp == NULL)
-       {
                syserr("!Can't create transcript stream %s", p);
                syserr("!Can't create transcript stream %s", p);
-       }
+#ifdef HASSETVBUF
+       setvbuf(e->e_xfp, NULL, _IOLBF, 0);
+#else
+       setlinebuf(e->e_xfp);
+#endif
        if (tTd(46, 9))
        {
                printf("openxscript(%s):\n  ", p);
        if (tTd(46, 9))
        {
                printf("openxscript(%s):\n  ", p);
@@ -613,7 +676,7 @@ setsender(from, e, delimptr, internal)
                        char nbuf[100];
 
                        SuprErrs = TRUE;
                        char nbuf[100];
 
                        SuprErrs = TRUE;
-                       expand("\201n", nbuf, &nbuf[sizeof nbuf], e);
+                       expand("\201n", nbuf, sizeof nbuf, e);
                        if (parseaddr(from = newstr(nbuf), &e->e_from,
                                      RF_COPYALL, ' ', NULL, e) == NULL &&
                            parseaddr(from = "postmaster", &e->e_from,
                        if (parseaddr(from = newstr(nbuf), &e->e_from,
                                      RF_COPYALL, ' ', NULL, e) == NULL &&
                            parseaddr(from = "postmaster", &e->e_from,
@@ -631,34 +694,27 @@ setsender(from, e, delimptr, internal)
        }
        SuprErrs = FALSE;
 
        }
        SuprErrs = FALSE;
 
-       pvp = NULL;
-       if (e->e_from.q_mailer == LocalMailer)
-       {
 # ifdef USERDB
 # ifdef USERDB
+       if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
+       {
                register char *p;
                extern char *udbsender();
                register char *p;
                extern char *udbsender();
-# endif
 
 
+               p = udbsender(e->e_from.q_user);
+               if (p != NULL)
+                       from = p;
+       }
+# endif /* USERDB */
+
+       if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
+       {
                if (!internal)
                {
                if (!internal)
                {
-                       /* if the user has given fullname already, don't redefine */
+                       /* if the user already given fullname don't redefine */
                        if (FullName == NULL)
                                FullName = macvalue('x', e);
                        if (FullName != NULL && FullName[0] == '\0')
                                FullName = NULL;
                        if (FullName == NULL)
                                FullName = macvalue('x', e);
                        if (FullName != NULL && FullName[0] == '\0')
                                FullName = NULL;
-
-# ifdef USERDB
-                       p = udbsender(e->e_from.q_user);
-
-                       if (p != NULL)
-                       {
-                               /*
-                               **  We have an alternate address for the sender
-                               */
-
-                               pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL);
-                       }
-# endif /* USERDB */
                }
 
                if ((pw = getpwnam(e->e_from.q_user)) != NULL)
                }
 
                if ((pw = getpwnam(e->e_from.q_user)) != NULL)
@@ -713,8 +769,7 @@ setsender(from, e, delimptr, internal)
        **      links in the net.
        */
 
        **      links in the net.
        */
 
-       if (pvp == NULL)
-               pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL);
+       pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL);
        if (pvp == NULL)
        {
                /* don't need to give error -- prescan did that already */
        if (pvp == NULL)
        {
                /* don't need to give error -- prescan did that already */
@@ -724,12 +779,14 @@ setsender(from, e, delimptr, internal)
 # endif
                finis();
        }
 # endif
                finis();
        }
+/*
        (void) rewrite(pvp, 3, 0, e);
        (void) rewrite(pvp, 1, 0, e);
        (void) rewrite(pvp, 4, 0, e);
        (void) rewrite(pvp, 3, 0, e);
        (void) rewrite(pvp, 1, 0, e);
        (void) rewrite(pvp, 4, 0, e);
+*/
        bp = buf + 1;
        cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
        bp = buf + 1;
        cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
-       if (*bp == '@')
+       if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
        {
                /* heuristic: route-addr: add angle brackets */
                strcat(bp, ">");
        {
                /* heuristic: route-addr: add angle brackets */
                strcat(bp, ">");
@@ -750,3 +807,67 @@ setsender(from, e, delimptr, internal)
                        e->e_fromdomain = copyplist(pvp, TRUE);
        }
 }
                        e->e_fromdomain = copyplist(pvp, TRUE);
        }
 }
+\f/*
+**  PRINTENVFLAGS -- print envelope flags for debugging
+**
+**     Parameters:
+**             e -- the envelope with the flags to be printed.
+**
+**     Returns:
+**             none.
+*/
+
+struct eflags
+{
+       char    *ef_name;
+       u_long  ef_bit;
+};
+
+struct eflags  EnvelopeFlags[] =
+{
+       "OLDSTYLE",     EF_OLDSTYLE,
+       "INQUEUE",      EF_INQUEUE,
+       "NO_BODY_RETN", EF_NO_BODY_RETN,
+       "CLRQUEUE",     EF_CLRQUEUE,
+       "SENDRECEIPT",  EF_SENDRECEIPT,
+       "FATALERRS",    EF_FATALERRS,
+       "KEEPQUEUE",    EF_KEEPQUEUE,
+       "RESPONSE",     EF_RESPONSE,
+       "RESENT",       EF_RESENT,
+       "VRFYONLY",     EF_VRFYONLY,
+       "WARNING",      EF_WARNING,
+       "QUEUERUN",     EF_QUEUERUN,
+       "GLOBALERRS",   EF_GLOBALERRS,
+       "PM_NOTIFY",    EF_PM_NOTIFY,
+       "METOO",        EF_METOO,
+       "LOGSENDER",    EF_LOGSENDER,
+       "NORECEIPT",    EF_NORECEIPT,
+       "HAS8BIT",      EF_HAS8BIT,
+       "NL_NOT_EOL",   EF_NL_NOT_EOL,
+       "CRLF_NOT_EOL", EF_CRLF_NOT_EOL,
+       "RET_PARAM",    EF_RET_PARAM,
+       "HAS_DF",       EF_HAS_DF,
+       NULL
+};
+
+void
+printenvflags(e)
+       register ENVELOPE *e;
+{
+       register struct eflags *ef;
+       bool first = TRUE;
+
+       printf("%lx", e->e_flags);
+       for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
+       {
+               if (!bitset(ef->ef_bit, e->e_flags))
+                       continue;
+               if (first)
+                       printf("<%s", ef->ef_name);
+               else
+                       printf(",%s", ef->ef_name);
+               first = FALSE;
+       }
+       if (!first)
+               printf(">\n");
+}