diff options
Diffstat (limited to 'usr.sbin/sendmail/src/savemail.c')
| -rw-r--r-- | usr.sbin/sendmail/src/savemail.c | 230 |
1 files changed, 148 insertions, 82 deletions
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c index f47fc4e0e8cd..6467defcfdbf 100644 --- a/usr.sbin/sendmail/src/savemail.c +++ b/usr.sbin/sendmail/src/savemail.c @@ -33,11 +33,11 @@ */ #ifndef lint -static char sccsid[] = "@(#)savemail.c 8.3 (Berkeley) 7/13/93"; +static char sccsid[] = "@(#)savemail.c 8.28 (Berkeley) 3/11/94"; #endif /* not lint */ -# include <pwd.h> # include "sendmail.h" +# include <pwd.h> /* ** SAVEMAIL -- Save mail on error @@ -69,6 +69,10 @@ static char sccsid[] = "@(#)savemail.c 8.3 (Berkeley) 7/13/93"; # define ESM_PANIC 6 /* leave the locked queue/transcript files */ # define ESM_DONE 7 /* the message is successfully delivered */ +# ifndef _PATH_VARTMP +# define _PATH_VARTMP "/usr/tmp/" +# endif + savemail(e) register ENVELOPE *e; @@ -77,16 +81,19 @@ savemail(e) register FILE *fp; int state; auto ADDRESS *q = NULL; + register char *p; + MCI mcibuf; char buf[MAXLINE+1]; extern struct passwd *getpwnam(); - register char *p; extern char *ttypath(); typedef int (*fnptr)(); + extern bool writable(); if (tTd(6, 1)) { - printf("\nsavemail, errormode = %c, id = %s\n e_from=", - e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id); + printf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=", + e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id, + ExitStat); printaddr(&e->e_from, FALSE); } @@ -96,8 +103,6 @@ savemail(e) return; } - e->e_flags &= ~EF_FATALERRS; - /* ** In the unhappy event we don't know who to return the mail ** to, make someone up. @@ -106,7 +111,8 @@ savemail(e) if (e->e_from.q_paddr == NULL) { e->e_sender = "Postmaster"; - if (parseaddr(e->e_sender, &e->e_from, 0, '\0', NULL, e) == NULL) + if (parseaddr(e->e_sender, &e->e_from, + RF_COPYPARSE|RF_SENDERADDR, '\0', NULL, e) == NULL) { syserr("553 Cannot parse Postmaster!"); ExitStat = EX_SOFTWARE; @@ -238,33 +244,48 @@ savemail(e) ** joe@x, which gives a response, etc. Also force ** the mail to be delivered even if a version of ** it has already been sent to the sender. + ** + ** If this is a configuration or local software + ** error, send to the local postmaster as well, + ** since the originator can't do anything + ** about it anyway. Note that this is a full + ** copy of the message (intentionally) so that + ** the Postmaster can forward things along. */ + if (ExitStat == EX_CONFIG || ExitStat == EX_SOFTWARE) + { + (void) sendtolist("postmaster", + NULLADDR, &e->e_errorqueue, e); + } if (strcmp(e->e_from.q_paddr, "<>") != 0) + { (void) sendtolist(e->e_from.q_paddr, - (ADDRESS *) NULL, - &e->e_errorqueue, e); + NULLADDR, &e->e_errorqueue, e); + } - /* deliver a cc: to the postmaster if desired */ - if (PostMasterCopy != NULL) - { - auto ADDRESS *rlist = NULL; + /* + ** Deliver a non-delivery report to the + ** Postmaster-designate (not necessarily + ** Postmaster). This does not include the + ** body of the message, for privacy reasons. + ** You really shouldn't need this. + */ - (void) sendtolist(PostMasterCopy, - (ADDRESS *) NULL, - &rlist, e); - (void) returntosender(e->e_message, - rlist, FALSE, e); - } - q = e->e_errorqueue; + e->e_flags |= EF_PM_NOTIFY; + + /* check to see if there are any good addresses */ + for (q = e->e_errorqueue; q != NULL; q = q->q_next) + if (!bitset(QBADADDR|QDONTSEND, q->q_flags)) + break; if (q == NULL) { /* this is an error-error */ state = ESM_POSTMASTER; break; } - if (returntosender(e->e_message, - q, (e->e_class >= 0), e) == 0) + if (returntosender(e->e_message, e->e_errorqueue, + (e->e_class >= 0), e) == 0) { state = ESM_DONE; break; @@ -335,7 +356,9 @@ savemail(e) e->e_to = buf; q = NULL; (void) sendtolist(buf, &e->e_from, &q, e); - if (deliver(e, q) == 0) + if (q != NULL && + !bitset(QBADADDR, q->q_flags) && + deliver(e, q) == 0) state = ESM_DONE; else state = ESM_MAIL; @@ -358,19 +381,31 @@ savemail(e) break; } - fp = dfopen("/usr/tmp/dead.letter", - O_WRONLY|O_CREAT|O_APPEND, FileMode); + strcpy(buf, _PATH_VARTMP); + strcat(buf, "dead.letter"); + if (!writable(buf, NULLADDR, SFF_NOSLINK)) + { + state = ESM_PANIC; + break; + } + fp = dfopen(buf, O_WRONLY|O_CREAT|O_APPEND, FileMode); if (fp == NULL) { state = ESM_PANIC; break; } - putfromline(fp, FileMailer, e); - (*e->e_puthdr)(fp, FileMailer, e); - putline("\n", fp, FileMailer); - (*e->e_putbody)(fp, FileMailer, e, NULL); - putline("\n", fp, FileMailer); + bzero(&mcibuf, sizeof mcibuf); + mcibuf.mci_out = fp; + mcibuf.mci_mailer = FileMailer; + if (bitnset(M_7BITS, FileMailer->m_flags)) + mcibuf.mci_flags |= MCIF_7BIT; + + putfromline(&mcibuf, e); + (*e->e_puthdr)(&mcibuf, e); + putline("\n", &mcibuf); + (*e->e_putbody)(&mcibuf, e, NULL); + putline("\n", &mcibuf); (void) fflush(fp); state = ferror(fp) ? ESM_PANIC : ESM_DONE; (void) xfclose(fp, "savemail", "/usr/tmp/dead.letter"); @@ -383,8 +418,7 @@ savemail(e) case ESM_PANIC: /* leave the locked queue & transcript files around */ - syserr("554 savemail: cannot save rejected email anywhere"); - exit(EX_SOFTWARE); + syserr("!554 savemail: cannot save rejected email anywhere"); } } } @@ -450,6 +484,7 @@ returntosender(msg, returnq, sendbody, e) SendBody = sendbody; define('g', e->e_from.q_paddr, e); + define('u', NULL, e); ee = newenvelope(&errenvelope, e); define('a', "\201b", ee); define('r', "internal", ee); @@ -457,12 +492,14 @@ returntosender(msg, returnq, sendbody, e) define('_', "localhost", ee); ee->e_puthdr = putheader; ee->e_putbody = errbody; - ee->e_flags |= EF_RESPONSE; + ee->e_flags |= EF_RESPONSE|EF_METOO; if (!bitset(EF_OLDSTYLE, e->e_flags)) ee->e_flags &= ~EF_OLDSTYLE; ee->e_sendqueue = returnq; - ee->e_msgsize = e->e_msgsize + ERRORFUDGE; - openxscript(ee); + ee->e_msgsize = ERRORFUDGE; + if (!NoReturn) + ee->e_msgsize += e->e_msgsize; + initsys(ee); for (q = returnq; q != NULL; q = q->q_next) { if (bitset(QBADADDR, q->q_flags)) @@ -472,7 +509,7 @@ returntosender(msg, returnq, sendbody, e) ee->e_nrcpts++; if (!DontPruneRoutes && pruneroute(q->q_paddr)) - parseaddr(q->q_paddr, q, 0, '\0', NULL, e); + parseaddr(q->q_paddr, q, RF_COPYPARSE, '\0', NULL, e); if (q->q_alias == NULL) addheader("To", q->q_paddr, ee); @@ -499,7 +536,7 @@ returntosender(msg, returnq, sendbody, e) /* fake up an address header for the from person */ expand("\201n", buf, &buf[sizeof buf - 1], e); - if (parseaddr(buf, &ee->e_from, 1, '\0', NULL, e) == NULL) + if (parseaddr(buf, &ee->e_from, RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL) { syserr("553 Can't parse myself!"); ExitStat = EX_SOFTWARE; @@ -515,7 +552,7 @@ returntosender(msg, returnq, sendbody, e) eatheader(ee, TRUE); /* mark statistics */ - markstats(ee, (ADDRESS *) NULL); + markstats(ee, NULLADDR); /* actually deliver the error message */ sendall(ee, SM_DEFAULT); @@ -535,8 +572,7 @@ returntosender(msg, returnq, sendbody, e) ** original offending message. ** ** Parameters: -** fp -- the output file. -** m -- the mailer to output to. +** mci -- the mailer connection information. ** e -- the envelope we are working in. ** ** Returns: @@ -546,9 +582,8 @@ returntosender(msg, returnq, sendbody, e) ** Outputs the body of an error message. */ -errbody(fp, m, e) - register FILE *fp; - register struct mailer *m; +errbody(mci, e) + register MCI *mci; register ENVELOPE *e; { register FILE *xfile; @@ -560,7 +595,7 @@ errbody(fp, m, e) if (e->e_parent == NULL) { syserr("errbody: null parent"); - putline(" ----- Original message lost -----\n", fp, m); + putline(" ----- Original message lost -----\n", mci); return; } @@ -570,14 +605,41 @@ errbody(fp, m, e) if (e->e_msgboundary != NULL) { - putline("This is a MIME-encapsulated message", fp, m); - putline("", fp, m); + putline("This is a MIME-encapsulated message", mci); + putline("", mci); (void) sprintf(buf, "--%s", e->e_msgboundary); - putline(buf, fp, m); - putline("", fp, m); + putline(buf, mci); + putline("", mci); } /* + ** 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 && + !bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags)) + { + putline(" **********************************************", + mci); + putline(" ** THIS IS A WARNING MESSAGE ONLY **", + mci); + putline(" ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **", + mci); + putline(" **********************************************", + mci); + putline("", mci); + } + sprintf(buf, "The original message was received at %s", + arpadate(ctime(&e->e_parent->e_ctime))); + putline(buf, mci); + expand("from \201_", buf, &buf[sizeof buf - 1], e->e_parent); + putline(buf, mci); + putline("", mci); + + /* ** Output error message header (if specified and available). */ @@ -591,17 +653,17 @@ errbody(fp, m, e) while (fgets(buf, sizeof buf, xfile) != NULL) { expand(buf, buf, &buf[sizeof buf - 1], e); - putline(buf, fp, m); + putline(buf, mci); } (void) fclose(xfile); - putline("\n", fp, m); + putline("\n", mci); } } else { expand(ErrMsgFile, buf, &buf[sizeof buf - 1], e); - putline(buf, fp, m); - putline("", fp, m); + putline(buf, mci); + putline("", mci); } } @@ -617,22 +679,26 @@ errbody(fp, m, e) if (printheader) { putline(" ----- The following addresses had delivery problems -----", - fp, m); + mci); printheader = FALSE; } - if (q->q_alias != NULL) - strcpy(buf, q->q_alias->q_paddr); - else - strcpy(buf, q->q_paddr); + strcpy(buf, q->q_paddr); if (bitset(QBADADDR, q->q_flags)) - strcat(buf, " (hard error -- address deleted)"); + strcat(buf, " (unrecoverable error)"); else - strcat(buf, " (temporary failure -- will retry)"); - putline(buf, fp, m); + strcat(buf, " (transient failure)"); + putline(buf, mci); + if (q->q_alias != NULL) + { + strcpy(buf, " (expanded from: "); + strcat(buf, q->q_alias->q_paddr); + strcat(buf, ")"); + putline(buf, mci); + } } } if (!printheader) - putline("\n", fp, m); + putline("\n", mci); /* ** Output transcript of errors @@ -643,15 +709,15 @@ errbody(fp, m, e) if ((xfile = fopen(p, "r")) == NULL) { syserr("Cannot open %s", p); - putline(" ----- Transcript of session is unavailable -----\n", fp, m); + putline(" ----- Transcript of session is unavailable -----\n", mci); } else { - putline(" ----- Transcript of session follows -----\n", fp, m); + putline(" ----- Transcript of session follows -----\n", mci); if (e->e_xfp != NULL) (void) fflush(e->e_xfp); while (fgets(buf, sizeof buf, xfile) != NULL) - putline(buf, fp, m); + putline(buf, mci); (void) xfclose(xfile, "errbody xscript", p); } errno = 0; @@ -662,42 +728,42 @@ errbody(fp, m, e) if (NoReturn) SendBody = FALSE; - putline("", fp, m); + putline("", mci); if (e->e_parent->e_df != NULL) { if (SendBody) - putline(" ----- Unsent message follows -----\n", fp, m); + putline(" ----- Original message follows -----\n", mci); else - putline(" ----- Message header follows -----\n", fp, m); - (void) fflush(fp); + putline(" ----- Message header follows -----\n", mci); + (void) fflush(mci->mci_out); if (e->e_msgboundary != NULL) { - putline("", fp, m); + putline("", mci); (void) sprintf(buf, "--%s", e->e_msgboundary); - putline(buf, fp, m); - putline("Content-Type: message/rfc822", fp, m); - putline("", fp, m); + putline(buf, mci); + putline("Content-Type: message/rfc822", mci); + putline("", mci); } - putheader(fp, m, e->e_parent); - putline("", fp, m); + putheader(mci, e->e_parent); + putline("", mci); if (SendBody) - putbody(fp, m, e->e_parent, e->e_msgboundary); + putbody(mci, e->e_parent, e->e_msgboundary); else - putline(" ----- Message body suppressed -----", fp, m); + putline(" ----- Message body suppressed -----", mci); } else { - putline(" ----- No message was collected -----\n", fp, m); + putline(" ----- No message was collected -----\n", mci); } if (e->e_msgboundary != NULL) { - putline("", fp, m); + putline("", mci); (void) sprintf(buf, "--%s--", e->e_msgboundary); - putline(buf, fp, m); + putline(buf, mci); } - putline("", fp, m); + putline("", mci); /* ** Cleanup and exit @@ -726,7 +792,7 @@ errbody(fp, m, e) pruneroute(addr) char *addr; { -#ifdef NAMED_BIND +#if NAMED_BIND char *start, *at, *comma; char c; int rcode; |
