|
|
1.1 root 1: # include <pwd.h>
2: # include "sendmail.h"
3:
4: SCCSID(@(#)savemail.c 4.2 8/28/83);
5:
6: /*
7: ** SAVEMAIL -- Save mail on error
8: **
9: ** If mailing back errors, mail it back to the originator
10: ** together with an error message; otherwise, just put it in
11: ** dead.letter in the user's home directory (if he exists on
12: ** this machine).
13: **
14: ** Parameters:
15: ** e -- the envelope containing the message in error.
16: **
17: ** Returns:
18: ** none
19: **
20: ** Side Effects:
21: ** Saves the letter, by writing or mailing it back to the
22: ** sender, or by putting it in dead.letter in her home
23: ** directory.
24: */
25:
26: savemail(e)
27: register ENVELOPE *e;
28: {
29: register struct passwd *pw;
30: register FILE *xfile;
31: char buf[MAXLINE+1];
32: extern struct passwd *getpwnam();
33: register char *p;
34: extern char *ttypath();
35: typedef int (*fnptr)();
36:
37: # ifdef DEBUG
38: if (tTd(6, 1))
39: printf("\nsavemail\n");
40: # endif DEBUG
41:
42: if (bitset(EF_RESPONSE, e->e_flags))
43: return;
44: if (e->e_class < 0)
45: {
46: message(Arpa_Info, "Dumping junk mail");
47: return;
48: }
49: ForceMail = TRUE;
50: e->e_flags &= ~EF_FATALERRS;
51:
52: /*
53: ** In the unhappy event we don't know who to return the mail
54: ** to, make someone up.
55: */
56:
57: if (e->e_from.q_paddr == NULL)
58: {
59: if (parseaddr("root", &e->e_from, 0, '\0') == NULL)
60: {
61: syserr("Cannot parse root!");
62: ExitStat = EX_SOFTWARE;
63: finis();
64: }
65: }
66: e->e_to = NULL;
67:
68: /*
69: ** If called from Eric Schmidt's network, do special mailback.
70: ** Fundamentally, this is the mailback case except that
71: ** it returns an OK exit status (assuming the return
72: ** worked).
73: ** Also, if the from address is not local, mail it back.
74: */
75:
76: if (ErrorMode == EM_BERKNET)
77: {
78: ExitStat = EX_OK;
79: ErrorMode = EM_MAIL;
80: }
81: if (!bitnset(M_LOCAL, e->e_from.q_mailer->m_flags))
82: ErrorMode = EM_MAIL;
83:
84: /*
85: ** If writing back, do it.
86: ** If the user is still logged in on the same terminal,
87: ** then write the error messages back to hir (sic).
88: ** If not, mail back instead.
89: */
90:
91: if (ErrorMode == EM_WRITE)
92: {
93: p = ttypath();
94: if (p == NULL || freopen(p, "w", stdout) == NULL)
95: {
96: ErrorMode = EM_MAIL;
97: errno = 0;
98: }
99: else
100: {
101: expand("$n", buf, &buf[sizeof buf - 1], e);
102: printf("\r\nMessage from %s...\r\n", buf);
103: printf("Errors occurred while sending mail.\r\n");
104: if (e->e_xfp != NULL)
105: {
106: (void) fflush(e->e_xfp);
107: xfile = fopen(queuename(e, 'x'), "r");
108: }
109: else
110: xfile = NULL;
111: if (xfile == NULL)
112: {
113: syserr("Cannot open %s", queuename(e, 'x'));
114: printf("Transcript of session is unavailable.\r\n");
115: }
116: else
117: {
118: printf("Transcript follows:\r\n");
119: while (fgets(buf, sizeof buf, xfile) != NULL &&
120: !ferror(stdout))
121: fputs(buf, stdout);
122: (void) fclose(xfile);
123: }
124: if (ferror(stdout))
125: (void) syserr("savemail: stdout: write err");
126: }
127: }
128:
129: /*
130: ** If mailing back, do it.
131: ** Throw away all further output. Don't do aliases, since
132: ** this could cause loops, e.g., if joe mails to x:joe,
133: ** and for some reason the network for x: is down, then
134: ** the response gets sent to x:joe, which gives a
135: ** response, etc. Also force the mail to be delivered
136: ** even if a version of it has already been sent to the
137: ** sender.
138: */
139:
140: if (ErrorMode == EM_MAIL)
141: {
142: if (e->e_errorqueue == NULL)
143: sendtolist(e->e_from.q_paddr, (ADDRESS *) NULL,
144: &e->e_errorqueue);
145: if (returntosender(e->e_message != NULL ? e->e_message :
146: "Unable to deliver mail",
147: e->e_errorqueue, TRUE) == 0)
148: return;
149: }
150:
151: /*
152: ** Save the message in dead.letter.
153: ** If we weren't mailing back, and the user is local, we
154: ** should save the message in dead.letter so that the
155: ** poor person doesn't have to type it over again --
156: ** and we all know what poor typists programmers are.
157: */
158:
159: p = NULL;
160: if (e->e_from.q_mailer == LocalMailer)
161: {
162: if (e->e_from.q_home != NULL)
163: p = e->e_from.q_home;
164: else if ((pw = getpwnam(e->e_from.q_user)) != NULL)
165: p = pw->pw_dir;
166: }
167: if (p == NULL)
168: {
169: syserr("Can't return mail to %s", e->e_from.q_paddr);
170: # ifdef DEBUG
171: p = "/usr/tmp";
172: # endif
173: }
174: if (p != NULL && e->e_dfp != NULL)
175: {
176: auto ADDRESS *q;
177: bool oldverb = Verbose;
178:
179: /* we have a home directory; open dead.letter */
180: define('z', p, e);
181: expand("$z/dead.letter", buf, &buf[sizeof buf - 1], e);
182: Verbose = TRUE;
183: message(Arpa_Info, "Saving message in %s", buf);
184: Verbose = oldverb;
185: e->e_to = buf;
186: q = NULL;
187: sendtolist(buf, (ADDRESS *) NULL, &q);
188: (void) deliver(e, q);
189: }
190:
191: /* add terminator to writeback message */
192: if (ErrorMode == EM_WRITE)
193: printf("-----\r\n");
194: }
195: /*
196: ** RETURNTOSENDER -- return a message to the sender with an error.
197: **
198: ** Parameters:
199: ** msg -- the explanatory message.
200: ** returnto -- the queue of people to send the message to.
201: ** sendbody -- if TRUE, also send back the body of the
202: ** message; otherwise just send the header.
203: **
204: ** Returns:
205: ** zero -- if everything went ok.
206: ** else -- some error.
207: **
208: ** Side Effects:
209: ** Returns the current message to the sender via
210: ** mail.
211: */
212:
213: static bool SendBody;
214:
215: #define MAXRETURNS 6 /* max depth of returning messages */
216:
217: returntosender(msg, returnto, sendbody)
218: char *msg;
219: ADDRESS *returnto;
220: bool sendbody;
221: {
222: char buf[MAXNAME];
223: extern putheader(), errbody();
224: register ENVELOPE *ee;
225: extern ENVELOPE *newenvelope();
226: ENVELOPE errenvelope;
227: static int returndepth;
228: register ADDRESS *q;
229:
230: # ifdef DEBUG
231: if (tTd(6, 1))
232: {
233: printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
234: msg, returndepth, CurEnv);
235: printf("\treturnto=");
236: printaddr(returnto, TRUE);
237: }
238: # endif DEBUG
239:
240: if (++returndepth >= MAXRETURNS)
241: {
242: if (returndepth != MAXRETURNS)
243: syserr("returntosender: infinite recursion on %s", returnto->q_paddr);
244: /* don't "unrecurse" and fake a clean exit */
245: /* returndepth--; */
246: return (0);
247: }
248:
249: SendBody = sendbody;
250: define('g', "$f", CurEnv);
251: ee = newenvelope(&errenvelope);
252: ee->e_puthdr = putheader;
253: ee->e_putbody = errbody;
254: ee->e_flags |= EF_RESPONSE;
255: ee->e_sendqueue = returnto;
256: openxscript(ee);
257: for (q = returnto; q != NULL; q = q->q_next)
258: {
259: if (q->q_alias == NULL)
260: addheader("to", q->q_paddr, ee);
261: }
262: (void) sprintf(buf, "Returned mail: %s", msg);
263: addheader("subject", buf, ee);
264:
265: /* fake up an address header for the from person */
266: expand("$n", buf, &buf[sizeof buf - 1], CurEnv);
267: if (parseaddr(buf, &ee->e_from, -1, '\0') == NULL)
268: {
269: syserr("Can't parse myself!");
270: ExitStat = EX_SOFTWARE;
271: returndepth--;
272: return (-1);
273: }
274:
275: /* push state into submessage */
276: CurEnv = ee;
277: define('f', "$n", ee);
278: define('x', "Mail Delivery Subsystem", ee);
279: eatheader(ee);
280:
281: /* actually deliver the error message */
282: sendall(ee, SM_DEFAULT);
283:
284: /* restore state */
285: dropenvelope(ee);
286: CurEnv = CurEnv->e_parent;
287: returndepth--;
288:
289: /* should check for delivery errors here */
290: return (0);
291: }
292: /*
293: ** ERRBODY -- output the body of an error message.
294: **
295: ** Typically this is a copy of the transcript plus a copy of the
296: ** original offending message.
297: **
298: ** Parameters:
299: ** fp -- the output file.
300: ** m -- the mailer to output to.
301: ** e -- the envelope we are working in.
302: **
303: ** Returns:
304: ** none
305: **
306: ** Side Effects:
307: ** Outputs the body of an error message.
308: */
309:
310: errbody(fp, m, e)
311: register FILE *fp;
312: register struct mailer *m;
313: register ENVELOPE *e;
314: {
315: register FILE *xfile;
316: char buf[MAXLINE];
317: char *p;
318:
319: /*
320: ** Output transcript of errors
321: */
322:
323: (void) fflush(stdout);
324: p = queuename(e->e_parent, 'x');
325: if ((xfile = fopen(p, "r")) == NULL)
326: {
327: syserr("Cannot open %s", p);
328: fprintf(fp, " ----- Transcript of session is unavailable -----\n");
329: }
330: else
331: {
332: fprintf(fp, " ----- Transcript of session follows -----\n");
333: if (e->e_xfp != NULL)
334: (void) fflush(e->e_xfp);
335: while (fgets(buf, sizeof buf, xfile) != NULL)
336: putline(buf, fp, m);
337: (void) fclose(xfile);
338: }
339: errno = 0;
340:
341: /*
342: ** Output text of original message
343: */
344:
345: if (NoReturn)
346: fprintf(fp, "\n ----- Return message suppressed -----\n\n");
347: else if (e->e_parent->e_dfp != NULL)
348: {
349: if (SendBody)
350: {
351: putline("\n", fp, m);
352: putline(" ----- Unsent message follows -----\n", fp, m);
353: (void) fflush(fp);
354: putheader(fp, m, e->e_parent);
355: putline("\n", fp, m);
356: putbody(fp, m, e->e_parent);
357: }
358: else
359: {
360: putline("\n", fp, m);
361: putline(" ----- Message header follows -----\n", fp, m);
362: (void) fflush(fp);
363: putheader(fp, m, e->e_parent);
364: }
365: }
366: else
367: {
368: putline("\n", fp, m);
369: putline(" ----- No message was collected -----\n", fp, m);
370: putline("\n", fp, m);
371: }
372:
373: /*
374: ** Cleanup and exit
375: */
376:
377: if (errno != 0)
378: syserr("errbody: I/O error");
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.