diff options
Diffstat (limited to 'usr.sbin/sendmail/src/savemail.c')
-rw-r--r-- | usr.sbin/sendmail/src/savemail.c | 164 |
1 files changed, 124 insertions, 40 deletions
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c index 80639b12cf34e..baa1a04d446a6 100644 --- a/usr.sbin/sendmail/src/savemail.c +++ b/usr.sbin/sendmail/src/savemail.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995 Eric P. Allman + * Copyright (c) 1983, 1995, 1996 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)savemail.c 8.87.1.2 (Berkeley) 9/16/96"; +static char sccsid[] = "@(#)savemail.c 8.100 (Berkeley) 9/27/96"; #endif /* not lint */ # include "sendmail.h" @@ -86,7 +86,7 @@ savemail(e, sendbody) auto ADDRESS *q = NULL; register char *p; MCI mcibuf; - int sfflags; + int flags; char buf[MAXLINE+1]; extern char *ttypath(); typedef int (*fnptr)(); @@ -283,7 +283,9 @@ savemail(e, sendbody) break; } if (returntosender(e->e_message, e->e_errorqueue, - sendbody, e) == 0) + sendbody ? RTSF_SEND_BODY + : RTSF_NO_BODY, + e) == 0) { state = ESM_DONE; break; @@ -299,14 +301,17 @@ savemail(e, sendbody) */ q = NULL; - if (sendtolist("postmaster", NULL, &q, 0, e) <= 0) + if (sendtolist(DoubleBounceAddr, NULL, &q, 0, e) <= 0) { - syserr("553 cannot parse postmaster!"); + syserr("553 cannot parse %s!", DoubleBounceAddr); ExitStat = EX_SOFTWARE; state = ESM_USRTMP; break; } - if (returntosender(e->e_message, q, sendbody, e) == 0) + flags = RTSF_PM_BOUNCE; + if (sendbody) + flags |= RTSF_SEND_BODY; + if (returntosender(e->e_message, q, flags, e) == 0) { state = ESM_DONE; break; @@ -344,9 +349,9 @@ savemail(e, sendbody) /* we have a home directory; write dead.letter */ define('z', p, e); expand("\201z/dead.letter", buf, sizeof buf, e); - sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; + flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; e->e_to = buf; - if (mailfile(buf, NULL, sfflags, e) == EX_OK) + if (mailfile(buf, NULL, flags, e) == EX_OK) { bool oldverb = Verbose; @@ -378,10 +383,10 @@ savemail(e, sendbody) snprintf(buf, sizeof buf, "%sdead.letter", _PATH_VARTMP); - sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT; - if (!writable(buf, NULL, sfflags) || + flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT; + if (!writable(buf, NULL, flags) || (fp = safefopen(buf, O_WRONLY|O_CREAT|O_APPEND, - FileMode, sfflags)) == NULL) + FileMode, flags)) == NULL) { state = ESM_PANIC; break; @@ -398,7 +403,9 @@ savemail(e, sendbody) (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); (void) fflush(fp); - if (!ferror(fp)) + if (ferror(fp)) + state = ESM_PANIC; + else { bool oldverb = Verbose; @@ -410,9 +417,7 @@ savemail(e, sendbody) syslog(LOG_NOTICE, "Saved message in %s", buf); #endif state = ESM_DONE; - break; } - state = ESM_PANIC; (void) xfclose(fp, "savemail", buf); break; @@ -434,8 +439,10 @@ savemail(e, sendbody) ** Parameters: ** msg -- the explanatory message. ** returnq -- the queue of people to send the message to. -** sendbody -- if TRUE, also send back the body of the -** message; otherwise just send the header. +** flags -- flags tweaking the operation: +** RTSF_SENDBODY -- include body of message (otherwise +** just send the header). +** RTSF_PMBOUNCE -- this is a postmaster bounce. ** e -- the current envelope. ** ** Returns: @@ -451,10 +458,10 @@ savemail(e, sendbody) #define ERRORFUDGE 100 /* nominal size of error message text */ int -returntosender(msg, returnq, sendbody, e) +returntosender(msg, returnq, flags, e) char *msg; ADDRESS *returnq; - bool sendbody; + int flags; register ENVELOPE *e; { register ENVELOPE *ee; @@ -509,16 +516,21 @@ returntosender(msg, returnq, sendbody, e) ee->e_flags &= ~EF_OLDSTYLE; ee->e_sendqueue = returnq; ee->e_msgsize = ERRORFUDGE; - if (sendbody) + if (bitset(RTSF_SEND_BODY, flags)) ee->e_msgsize += e->e_msgsize; else ee->e_flags |= EF_NO_BODY_RETN; initsys(ee); for (q = returnq; q != NULL; q = q->q_next) { + extern bool pruneroute __P((char *)); + if (bitset(QBADADDR, q->q_flags)) continue; + q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); + q->q_flags |= QPINGONFAILURE; + if (!DontPruneRoutes && pruneroute(q->q_paddr)) { register ADDRESS *p; @@ -543,8 +555,10 @@ returntosender(msg, returnq, sendbody, e) { if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags)) p = "return to sender"; - else + else if (bitset(RTSF_PM_BOUNCE, flags)) p = "postmaster notify"; + else + p = "DSN"; syslog(LOG_INFO, "%s: %s: %s: %s", e->e_id, ee->e_id, p, shortenstring(msg, 203)); } @@ -589,6 +603,13 @@ returntosender(msg, returnq, sendbody, e) addheader("Subject", msg, &ee->e_header); p = "return-receipt"; } + else if (bitset(RTSF_PM_BOUNCE, flags)) + { + snprintf(buf, sizeof buf, "Postmaster notify: %.*s", + sizeof buf - 20, msg); + addheader("Subject", buf, &ee->e_header); + p = "postmaster-notification"; + } else { snprintf(buf, sizeof buf, "Returned mail: %.*s", @@ -608,6 +629,8 @@ returntosender(msg, returnq, sendbody, e) returndepth--; return (-1); } + ee->e_from.q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); + ee->e_from.q_flags |= QPINGONFAILURE; ee->e_sender = ee->e_from.q_paddr; /* push state into submessage */ @@ -623,7 +646,7 @@ returntosender(msg, returnq, sendbody, e) sendall(ee, SM_DEFAULT); /* restore state */ - dropenvelope(ee); + dropenvelope(ee, TRUE); CurEnv = oldcur; returndepth--; @@ -647,7 +670,6 @@ returntosender(msg, returnq, sendbody, e) ** mci -- the mailer connection information. ** e -- the envelope we are working in. ** separator -- any possible MIME separator. -** flags -- to modify the behaviour. ** ** Returns: ** none @@ -667,8 +689,8 @@ errbody(mci, e, separator) register ADDRESS *q; bool printheader; bool sendbody; + bool pm_notify; char buf[MAXLINE]; - extern char *xuntextify(); if (bitset(MCIF_INHEADER, mci->mci_flags)) { @@ -699,10 +721,17 @@ errbody(mci, e, separator) ** Output introductory information. */ - for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) - if (bitset(QBADADDR, q->q_flags)) - break; - if (q == NULL && + pm_notify = FALSE; + p = hvalue("subject", e->e_header); + if (p != NULL && strncmp(p, "Postmaster ", 11) == 0) + pm_notify = TRUE; + else + { + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + if (bitset(QBADADDR, q->q_flags)) + break; + } + if (!pm_notify && q == NULL && !bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags)) { putline(" **********************************************", @@ -757,16 +786,63 @@ errbody(mci, e, separator) printheader = TRUE; for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) { - if (bitset(QBADADDR, q->q_flags)) + if (!bitset(QBADADDR, q->q_flags) || + !bitset(QPINGONFAILURE, q->q_flags)) + continue; + + if (printheader) { - if (!bitset(QPINGONFAILURE, q->q_flags)) - continue; - p = "unrecoverable error"; + putline(" ----- The following addresses had permanent fatal errors -----", + mci); + printheader = FALSE; } - else if (!bitset(QPRIMARY, q->q_flags)) + + snprintf(buf, sizeof buf, "%s", shortenstring(q->q_paddr, 203)); + putline(buf, mci); + if (q->q_alias != NULL) + { + snprintf(buf, sizeof buf, " (expanded from: %s)", + shortenstring(q->q_alias->q_paddr, 203)); + putline(buf, mci); + } + } + if (!printheader) + putline("", mci); + + printheader = TRUE; + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + { + if (bitset(QBADADDR, q->q_flags) || + !bitset(QPRIMARY, q->q_flags) || + !bitset(QDELAYED, q->q_flags)) + continue; + + if (printheader) + { + putline(" ----- The following addresses had transient non-fatal errors -----", + mci); + printheader = FALSE; + } + + snprintf(buf, sizeof buf, "%s", shortenstring(q->q_paddr, 203)); + putline(buf, mci); + if (q->q_alias != NULL) + { + snprintf(buf, sizeof buf, " (expanded from: %s)", + shortenstring(q->q_alias->q_paddr, 203)); + putline(buf, mci); + } + } + if (!printheader) + putline("", mci); + + printheader = TRUE; + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + { + if (bitset(QBADADDR, q->q_flags) || + !bitset(QPRIMARY, q->q_flags) || + bitset(QDELAYED, q->q_flags)) continue; - else if (bitset(QDELAYED, q->q_flags)) - p = "transient failure"; else if (!bitset(QPINGONSUCCESS, q->q_flags)) continue; else if (bitset(QRELAYED, q->q_flags)) @@ -785,7 +861,7 @@ errbody(mci, e, separator) if (printheader) { - putline(" ----- The following addresses have delivery notifications -----", + putline(" ----- The following addresses had successful delivery notifications -----", mci); printheader = FALSE; } @@ -801,7 +877,7 @@ errbody(mci, e, separator) } } if (!printheader) - putline("\n", mci); + putline("", mci); /* ** Output transcript of errors @@ -1164,14 +1240,16 @@ smtptodsn(smtpstat) ** ** Parameters: ** t -- the text to convert. +** taboo -- additional characters that must be encoded. ** ** Returns: ** The xtext-ified version of the same string. */ char * -xtextify(t) +xtextify(t, taboo) register char *t; + char *taboo; { register char *p; int l; @@ -1179,6 +1257,9 @@ xtextify(t) static char *bp = NULL; static int bplen = 0; + if (taboo == NULL) + taboo = ""; + /* figure out how long this xtext will have to be */ nbogus = l = 0; for (p = t; *p != '\0'; p++) @@ -1186,7 +1267,8 @@ xtextify(t) register int c = (*p & 0xff); /* ASCII dependence here -- this is the way the spec words it */ - if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(') + if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' || + strchr(taboo, c) != NULL) nbogus++; l++; } @@ -1209,7 +1291,8 @@ xtextify(t) register int c = (*t++ & 0xff); /* ASCII dependence here -- this is the way the spec words it */ - if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(') + if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' || + strchr(taboo, c) != NULL) { *p++ = '+'; *p++ = "0123456789abcdef"[c >> 4]; @@ -1298,6 +1381,7 @@ xuntextify(t) c -= 'a' - 10; *p++ |= c; } + *p = '\0'; return bp; } /* |