static char SccsId
[] = "@(#)savemail.c 1.4 %G%";
** SAVEMAIL -- Save mail on error
** If the MailBack flag is set, mail it back to the originator
** together with an error message; otherwise, just put it in
** dead.letter in the user's home directory (if he exists on
** Saves the letter, by writing or mailing it back to the
** sender, or by putting it in dead.letter in her home
** WARNING: the user id is reset to the original user.
# define MY_NAME "~MAILER~DAEMON~"
register struct passwd
*pw
;
extern struct passwd
*getpwnam();
** In the unhappy event we don't know who to return the mail
if (From
.q_paddr
== NULL
)
if (parse("root", &From
, 0) == NULL
)
syserr("Cannot parse root!");
** If called from Eric Schmidt's network, do special mailback.
** Fundamentally, this is the mailback case except that
** it returns an OK exit status (assuming the return
** If writing back, do it.
** If the user is still logged in on the same terminal,
** then write the error messages back to hir (sic).
** If not, set the MailBack flag so that it will get
if (p
== NULL
|| freopen(p
, "w", stdout
) == NULL
)
xfile
= fopen(Transcript
, "r");
syserr("Cannot open %s", Transcript
);
printf("\r\nMessage from %s\r\n", MY_NAME
);
printf("Errors occurred while sending mail, transcript follows:\r\n");
while (fgets(buf
, sizeof buf
, xfile
) && !ferror(stdout
))
syserr("savemail: stdout: write err");
** If mailing back, do it.
** Throw away all further output. Don't do aliases, since
** this could cause loops, e.g., if joe mails to x:joe,
** and for some reason the network for x: is down, then
** the response gets sent to x:joe, which gives a
** response, etc. Also force the mail to be delivered
** even if a version of it has already been sent to the
if (MailBack
|| From
.q_mailer
!= &Mailer
[0])
freopen("/dev/null", "w", stdout
);
/* fake up an address header for the from person */
bmove((char *) &From
, (char *) &to_addr
, sizeof to_addr
);
if (parse(MY_NAME
, &From
, -1) == NULL
)
syserr("Can't parse myself!");
i
= deliver(&to_addr
, errhdr
);
bmove((char *) &to_addr
, (char *) &From
, sizeof From
);
syserr("Can't return mail to %s", p
);
** Save the message in dead.letter.
** If we weren't mailing back, and the user is local, we
** should save the message in dead.letter so that the
** poor person doesn't have to type it over again --
** and we all know what poor typists programmers are.
if (From
.q_mailer
== &Mailer
[0] && (pw
= getpwnam(From
.q_user
)) != NULL
)
/* user has a home directory */
syserr("Can't return mail to %s (pw=%u)", From
.q_paddr
, pw
);
/* we have a home directory; open dead.letter */
strcat(buf
, "/dead.letter");
printf("Cannot save mail, sorry\n");
fprintf(xfile
, "----- Mail saved at %s", ctime(&tim
));
while (fgets(buf
, sizeof buf
, stdin
) && !ferror(xfile
))
syserr("savemail: dead.letter: write err");
printf("Letter saved in dead.letter\n");
/* add terminator to writeback message */
** ERRHDR -- Output the header for error mail.
** This is the edit filter to error mailbacks.
** Output the transcript part.
** Output the original message.
** xfile -- the transcript file.
** fp -- the output file.
if ((xfile
= open(Transcript
, 0)) < 0)
syserr("Cannot open %s", Transcript
);
fprintf(fp
, "To: %s\n", To
);
fprintf(fp
, "Subject: Unable to deliver mail\n");
fprintf(fp
, "\n ----- Transcript of session follows -----\n");
while ((i
= read(xfile
, copybuf
, sizeof copybuf
)) > 0)
write(fileno(fp
), copybuf
, i
);
fprintf(fp
, "\n ----- Unsent message follows -----\n");
while ((i
= read(fileno(stdin
), copybuf
, sizeof copybuf
)) > 0)
write(fileno(fp
), copybuf
, i
);
syserr("errhdr: I/O error");