date and time created 93/07/13 06:22:10 by eric
[unix-history] / usr / src / usr.sbin / sendmail / src / savemail.c
CommitLineData
b2a81223 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
24634489
KB
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
bee79b64 5 *
417f7a11 6 * %sccs.include.redist.c%
bee79b64 7 */
b2a81223
DF
8
9#ifndef lint
8e5c6745 10static char sccsid[] = "@(#)savemail.c 8.2 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
b2a81223 12
b3cbe40f 13# include <pwd.h>
96faada8 14# include "sendmail.h"
b3cbe40f
EA
15
16/*
17** SAVEMAIL -- Save mail on error
18**
7338e3d4 19** If mailing back errors, mail it back to the originator
b3cbe40f
EA
20** together with an error message; otherwise, just put it in
21** dead.letter in the user's home directory (if he exists on
22** this machine).
23**
24** Parameters:
e6f08ab1 25** e -- the envelope containing the message in error.
b3cbe40f
EA
26**
27** Returns:
28** none
29**
30** Side Effects:
31** Saves the letter, by writing or mailing it back to the
32** sender, or by putting it in dead.letter in her home
33** directory.
b3cbe40f
EA
34*/
35
2e3062fe
EA
36/* defines for state machine */
37# define ESM_REPORT 0 /* report to sender's terminal */
38# define ESM_MAIL 1 /* mail back to sender */
39# define ESM_QUIET 2 /* messages have already been returned */
40# define ESM_DEADLETTER 3 /* save in ~/dead.letter */
41# define ESM_POSTMASTER 4 /* return to postmaster */
42# define ESM_USRTMP 5 /* save in /usr/tmp/dead.letter */
43# define ESM_PANIC 6 /* leave the locked queue/transcript files */
44# define ESM_DONE 7 /* the message is successfully delivered */
45
46
e6f08ab1
EA
47savemail(e)
48 register ENVELOPE *e;
b3cbe40f
EA
49{
50 register struct passwd *pw;
2e3062fe
EA
51 register FILE *fp;
52 int state;
83a871a1 53 auto ADDRESS *q = NULL;
b3cbe40f 54 char buf[MAXLINE+1];
b3cbe40f
EA
55 extern struct passwd *getpwnam();
56 register char *p;
b3cbe40f 57 extern char *ttypath();
40e27d12 58 typedef int (*fnptr)();
b3cbe40f 59
9678c96d 60 if (tTd(6, 1))
bc854e30 61 {
c87034b7
EA
62 printf("\nsavemail, errormode = %c, id = %s\n e_from=",
63 e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id);
bc854e30
EA
64 printaddr(&e->e_from, FALSE);
65 }
ae945718 66
c87034b7
EA
67 if (e->e_id == NULL)
68 {
69 /* can't return a message with no id */
70 return;
71 }
72
e6f08ab1 73 e->e_flags &= ~EF_FATALERRS;
b3cbe40f
EA
74
75 /*
76 ** In the unhappy event we don't know who to return the mail
77 ** to, make someone up.
78 */
79
1bcdf0a2 80 if (CurEnv->e_returnto == NULL)
b3cbe40f 81 {
1bcdf0a2
EA
82 CurEnv->e_returnto = parse("root", (ADDRESS *) NULL, 0);
83 if (CurEnv->e_returnto == NULL)
b3cbe40f 84 {
e0b81669 85 syserr("553 Cannot parse Postmaster!");
b3cbe40f
EA
86 ExitStat = EX_SOFTWARE;
87 finis();
88 }
89 }
e6f08ab1 90 e->e_to = NULL;
b3cbe40f
EA
91
92 /*
2e3062fe
EA
93 ** Basic state machine.
94 **
95 ** This machine runs through the following states:
96 **
97 ** ESM_QUIET Errors have already been printed iff the
98 ** sender is local.
99 ** ESM_REPORT Report directly to the sender's terminal.
100 ** ESM_MAIL Mail response to the sender.
101 ** ESM_DEADLETTER Save response in ~/dead.letter.
102 ** ESM_POSTMASTER Mail response to the postmaster.
103 ** ESM_PANIC Save response anywhere possible.
b3cbe40f
EA
104 */
105
2e3062fe 106 /* determine starting state */
8c8e8e94 107 switch (e->e_errormode)
b3cbe40f 108 {
2e3062fe
EA
109 case EM_WRITE:
110 state = ESM_REPORT;
111 break;
112
113 case EM_BERKNET:
114 /* mail back, but return o.k. exit status */
3b661a43 115 ExitStat = EX_OK;
b3cbe40f 116
2e3062fe
EA
117 /* fall through.... */
118
119 case EM_MAIL:
120 state = ESM_MAIL;
121 break;
122
123 case EM_PRINT:
f4b05990 124 case '\0':
2e3062fe
EA
125 state = ESM_QUIET;
126 break;
b3cbe40f 127
2e3062fe
EA
128 case EM_QUIET:
129 /* no need to return anything at all */
130 return;
f4b05990
EA
131
132 default:
8c8e8e94 133 syserr("554 savemail: bogus errormode x%x\n", e->e_errormode);
f4b05990
EA
134 state = ESM_MAIL;
135 break;
2e3062fe
EA
136 }
137
d6776f09
EA
138 /* if this is already an error response, send to postmaster */
139 if (bitset(EF_RESPONSE, e->e_flags))
140 {
141 if (e->e_parent != NULL &&
142 bitset(EF_RESPONSE, e->e_parent->e_flags))
143 {
144 /* got an error sending a response -- can it */
145 return;
146 }
147 state = ESM_POSTMASTER;
148 }
149
2e3062fe 150 while (state != ESM_DONE)
b3cbe40f 151 {
f4b05990
EA
152 if (tTd(6, 5))
153 printf(" state %d\n", state);
f4b05990 154
2e3062fe 155 switch (state)
b3cbe40f 156 {
f4b05990
EA
157 case ESM_QUIET:
158 if (e->e_from.q_mailer == LocalMailer)
159 state = ESM_DEADLETTER;
160 else
161 state = ESM_MAIL;
162 break;
163
2e3062fe
EA
164 case ESM_REPORT:
165
166 /*
167 ** If the user is still logged in on the same terminal,
168 ** then write the error messages back to hir (sic).
169 */
170
171 p = ttypath();
172 if (p == NULL || freopen(p, "w", stdout) == NULL)
173 {
174 state = ESM_MAIL;
175 break;
176 }
177
2bee003d 178 expand("\201n", buf, &buf[sizeof buf - 1], e);
7338e3d4
EA
179 printf("\r\nMessage from %s...\r\n", buf);
180 printf("Errors occurred while sending mail.\r\n");
912acb74 181 if (e->e_xfp != NULL)
7338e3d4 182 {
912acb74 183 (void) fflush(e->e_xfp);
2e3062fe 184 fp = fopen(queuename(e, 'x'), "r");
7338e3d4
EA
185 }
186 else
2e3062fe
EA
187 fp = NULL;
188 if (fp == NULL)
7338e3d4 189 {
e6f08ab1 190 syserr("Cannot open %s", queuename(e, 'x'));
7338e3d4
EA
191 printf("Transcript of session is unavailable.\r\n");
192 }
193 else
194 {
195 printf("Transcript follows:\r\n");
2e3062fe 196 while (fgets(buf, sizeof buf, fp) != NULL &&
7338e3d4
EA
197 !ferror(stdout))
198 fputs(buf, stdout);
bc854e30 199 (void) xfclose(fp, "savemail transcript", e->e_id);
7338e3d4 200 }
2e3062fe 201 printf("Original message will be saved in dead.letter.\r\n");
2e3062fe
EA
202 state = ESM_DEADLETTER;
203 break;
b3cbe40f 204
2e3062fe 205 case ESM_MAIL:
2e3062fe
EA
206 /*
207 ** If mailing back, do it.
208 ** Throw away all further output. Don't alias,
209 ** since this could cause loops, e.g., if joe
210 ** mails to joe@x, and for some reason the network
211 ** for @x is down, then the response gets sent to
212 ** joe@x, which gives a response, etc. Also force
213 ** the mail to be delivered even if a version of
214 ** it has already been sent to the sender.
215 */
b3cbe40f 216
bc854e30
EA
217 if (strcmp(e->e_from.q_paddr, "<>") != 0)
218 (void) sendtolist(e->e_from.q_paddr,
219 (ADDRESS *) NULL,
220 &e->e_errorqueue, e);
221
222 /* deliver a cc: to the postmaster if desired */
223 if (PostMasterCopy != NULL)
2e3062fe 224 {
bc854e30 225 auto ADDRESS *rlist = NULL;
bb9f418b 226
bc854e30 227 (void) sendtolist(PostMasterCopy,
bb9f418b 228 (ADDRESS *) NULL,
bc854e30
EA
229 &rlist, e);
230 (void) returntosender(e->e_message,
231 rlist, FALSE, e);
232 }
233 q = e->e_errorqueue;
234 if (q == NULL)
235 {
236 /* this is an error-error */
237 state = ESM_POSTMASTER;
238 break;
239 }
35b698c6 240 if (returntosender(e->e_message,
bc854e30
EA
241 q, (e->e_class >= 0), e) == 0)
242 {
243 state = ESM_DONE;
244 break;
245 }
a0225d08 246
bc854e30
EA
247 /* didn't work -- return to postmaster */
248 state = ESM_POSTMASTER;
249 break;
ab0b3f7d 250
bc854e30
EA
251 case ESM_POSTMASTER:
252 /*
253 ** Similar to previous case, but to system postmaster.
254 */
255
f553db48
EA
256 q = NULL;
257 if (sendtolist("postmaster", NULL, &q, e) <= 0)
2e3062fe 258 {
bc854e30
EA
259 syserr("553 cannot parse postmaster!");
260 ExitStat = EX_SOFTWARE;
261 state = ESM_USRTMP;
262 break;
2e3062fe 263 }
35b698c6 264 if (returntosender(e->e_message,
abccefc9 265 q, (e->e_class >= 0), e) == 0)
2e3062fe
EA
266 {
267 state = ESM_DONE;
268 break;
269 }
b3cbe40f 270
bc854e30
EA
271 /* didn't work -- last resort */
272 state = ESM_USRTMP;
2e3062fe 273 break;
b3cbe40f 274
2e3062fe
EA
275 case ESM_DEADLETTER:
276 /*
277 ** Save the message in dead.letter.
278 ** If we weren't mailing back, and the user is
279 ** local, we should save the message in
280 ** ~/dead.letter so that the poor person doesn't
281 ** have to type it over again -- and we all know
282 ** what poor typists UNIX users are.
283 */
b3cbe40f 284
2e3062fe
EA
285 p = NULL;
286 if (e->e_from.q_mailer == LocalMailer)
287 {
288 if (e->e_from.q_home != NULL)
289 p = e->e_from.q_home;
290 else if ((pw = getpwnam(e->e_from.q_user)) != NULL)
291 p = pw->pw_dir;
292 }
293 if (p == NULL)
294 {
0f8f3490 295 /* no local directory */
2e3062fe
EA
296 state = ESM_MAIL;
297 break;
298 }
299 if (e->e_dfp != NULL)
300 {
2e3062fe
EA
301 bool oldverb = Verbose;
302
303 /* we have a home directory; open dead.letter */
304 define('z', p, e);
2bee003d 305 expand("\201z/dead.letter", buf, &buf[sizeof buf - 1], e);
2e3062fe 306 Verbose = TRUE;
b6edea3d 307 message("Saving message in %s", buf);
2e3062fe
EA
308 Verbose = oldverb;
309 e->e_to = buf;
310 q = NULL;
1c7897ef 311 (void) sendtolist(buf, &e->e_from, &q, e);
2e3062fe
EA
312 if (deliver(e, q) == 0)
313 state = ESM_DONE;
314 else
315 state = ESM_MAIL;
316 }
577bce94
EA
317 else
318 {
319 /* no data file -- try mailing back */
320 state = ESM_MAIL;
321 }
2e3062fe
EA
322 break;
323
324 case ESM_USRTMP:
325 /*
326 ** Log the mail in /usr/tmp/dead.letter.
327 */
328
abccefc9
EA
329 if (e->e_class < 0)
330 {
331 state = ESM_DONE;
332 break;
333 }
334
6f7f4e2c
EA
335 fp = dfopen("/usr/tmp/dead.letter",
336 O_WRONLY|O_CREAT|O_APPEND, FileMode);
2e3062fe
EA
337 if (fp == NULL)
338 {
339 state = ESM_PANIC;
340 break;
341 }
342
49a282c6
EA
343 putfromline(fp, FileMailer, e);
344 (*e->e_puthdr)(fp, FileMailer, e);
345 putline("\n", fp, FileMailer);
2f6a8a78 346 (*e->e_putbody)(fp, FileMailer, e, NULL);
49a282c6 347 putline("\n", fp, FileMailer);
2e3062fe
EA
348 (void) fflush(fp);
349 state = ferror(fp) ? ESM_PANIC : ESM_DONE;
bc854e30 350 (void) xfclose(fp, "savemail", "/usr/tmp/dead.letter");
2e3062fe
EA
351 break;
352
353 default:
b6edea3d 354 syserr("554 savemail: unknown state %d", state);
2e3062fe
EA
355
356 /* fall through ... */
357
358 case ESM_PANIC:
2e3062fe 359 /* leave the locked queue & transcript files around */
b6edea3d 360 syserr("554 savemail: cannot save rejected email anywhere");
2e3062fe
EA
361 exit(EX_SOFTWARE);
362 }
363 }
b3cbe40f
EA
364}
365\f/*
aba51985
EA
366** RETURNTOSENDER -- return a message to the sender with an error.
367**
368** Parameters:
369** msg -- the explanatory message.
7a079701 370** returnq -- the queue of people to send the message to.
79bd7c07
EA
371** sendbody -- if TRUE, also send back the body of the
372** message; otherwise just send the header.
a4076aed 373** e -- the current envelope.
aba51985
EA
374**
375** Returns:
376** zero -- if everything went ok.
377** else -- some error.
378**
379** Side Effects:
380** Returns the current message to the sender via
381** mail.
382*/
383
79bd7c07 384static bool SendBody;
aba51985 385
3c7fe765 386#define MAXRETURNS 6 /* max depth of returning messages */
0f104940 387#define ERRORFUDGE 100 /* nominal size of error message text */
3c7fe765 388
a4076aed 389returntosender(msg, returnq, sendbody, e)
aba51985 390 char *msg;
7a079701 391 ADDRESS *returnq;
79bd7c07 392 bool sendbody;
a4076aed 393 register ENVELOPE *e;
aba51985 394{
aba51985 395 char buf[MAXNAME];
dd1fe05b
EA
396 extern putheader(), errbody();
397 register ENVELOPE *ee;
bc854e30 398 ENVELOPE *oldcur = CurEnv;
dd1fe05b 399 ENVELOPE errenvelope;
3c7fe765 400 static int returndepth;
7338e3d4 401 register ADDRESS *q;
3c7fe765 402
cbfdff7c
EA
403 if (returnq == NULL)
404 return (-1);
405
35b698c6
EA
406 if (msg == NULL)
407 msg = "Unable to deliver mail";
408
9678c96d 409 if (tTd(6, 1))
e4d966b5 410 {
bc854e30 411 printf("Return To Sender: msg=\"%s\", depth=%d, e=%x, returnq=",
a4076aed 412 msg, returndepth, e);
7a079701 413 printaddr(returnq, TRUE);
e4d966b5 414 }
e4d966b5 415
3c7fe765
EA
416 if (++returndepth >= MAXRETURNS)
417 {
418 if (returndepth != MAXRETURNS)
b6edea3d 419 syserr("554 returntosender: infinite recursion on %s", returnq->q_paddr);
3c7fe765
EA
420 /* don't "unrecurse" and fake a clean exit */
421 /* returndepth--; */
422 return (0);
423 }
aba51985 424
79bd7c07 425 SendBody = sendbody;
bc854e30 426 define('g', e->e_from.q_paddr, e);
fda58daa 427 ee = newenvelope(&errenvelope, e);
2bee003d 428 define('a', "\201b", ee);
0257ba6d
EA
429 define('r', "internal", ee);
430 define('s', "localhost", ee);
431 define('_', "localhost", ee);
dd1fe05b
EA
432 ee->e_puthdr = putheader;
433 ee->e_putbody = errbody;
7338e3d4 434 ee->e_flags |= EF_RESPONSE;
a4076aed 435 if (!bitset(EF_OLDSTYLE, e->e_flags))
839ae7fa 436 ee->e_flags &= ~EF_OLDSTYLE;
7a079701 437 ee->e_sendqueue = returnq;
0f104940 438 ee->e_msgsize = e->e_msgsize + ERRORFUDGE;
912acb74 439 openxscript(ee);
7a079701 440 for (q = returnq; q != NULL; q = q->q_next)
7338e3d4 441 {
68491765 442 if (bitset(QBADADDR, q->q_flags))
0f104940
EA
443 continue;
444
68491765
EA
445 if (!bitset(QDONTSEND, q->q_flags))
446 ee->e_nrcpts++;
0f104940 447
63d473ff 448 if (!DontPruneRoutes && pruneroute(q->q_paddr))
9e2cf26f 449 parseaddr(q->q_paddr, q, 0, '\0', NULL, e);
63d473ff 450
7338e3d4 451 if (q->q_alias == NULL)
b6919a63 452 addheader("To", q->q_paddr, ee);
7338e3d4 453 }
2e3062fe 454
6e99f903 455# ifdef LOG
68f7099c 456 if (LogLevel > 5)
6e99f903
EA
457 syslog(LOG_INFO, "%s: %s: return to sender: %s",
458 e->e_id, ee->e_id, msg);
459# endif
460
e7d41cfe 461 (void) sprintf(buf, "Returned mail: %s", msg);
b6919a63 462 addheader("Subject", buf, ee);
2f6a8a78
EA
463 if (SendMIMEErrors)
464 {
58645b30 465 addheader("MIME-Version", "1.0", ee);
2f6a8a78
EA
466 (void) sprintf(buf, "%s.%ld/%s",
467 ee->e_id, curtime(), MyHostName);
468 ee->e_msgboundary = newstr(buf);
469 (void) sprintf(buf, "multipart/mixed; boundary=\"%s\"",
470 ee->e_msgboundary);
471 addheader("Content-Type", buf, ee);
472 }
aba51985
EA
473
474 /* fake up an address header for the from person */
2bee003d 475 expand("\201n", buf, &buf[sizeof buf - 1], e);
bc854e30 476 if (parseaddr(buf, &ee->e_from, 1, '\0', NULL, e) == NULL)
aba51985 477 {
b6edea3d 478 syserr("553 Can't parse myself!");
aba51985 479 ExitStat = EX_SOFTWARE;
3c7fe765 480 returndepth--;
aba51985
EA
481 return (-1);
482 }
4a2da288 483 ee->e_sender = ee->e_from.q_paddr;
79bd7c07 484
dd1fe05b
EA
485 /* push state into submessage */
486 CurEnv = ee;
2bee003d 487 define('f', "\201n", ee);
7338e3d4 488 define('x', "Mail Delivery Subsystem", ee);
959cf51d 489 eatheader(ee, TRUE);
dd1fe05b 490
8e5c6745
EA
491 /* mark statistics */
492 markstats(ee, (ADDRESS *) NULL);
493
dd1fe05b 494 /* actually deliver the error message */
f7e74083 495 sendall(ee, SM_DEFAULT);
dd1fe05b 496
dd1fe05b 497 /* restore state */
2cce0c26 498 dropenvelope(ee);
bc854e30 499 CurEnv = oldcur;
3c7fe765 500 returndepth--;
79bd7c07 501
3c7fe765 502 /* should check for delivery errors here */
aba51985
EA
503 return (0);
504}
505\f/*
dd1fe05b 506** ERRBODY -- output the body of an error message.
b3cbe40f 507**
dd1fe05b
EA
508** Typically this is a copy of the transcript plus a copy of the
509** original offending message.
b3cbe40f 510**
b3cbe40f 511** Parameters:
b3cbe40f 512** fp -- the output file.
4db45bf1 513** m -- the mailer to output to.
912acb74 514** e -- the envelope we are working in.
b3cbe40f
EA
515**
516** Returns:
517** none
518**
519** Side Effects:
dd1fe05b 520** Outputs the body of an error message.
b3cbe40f
EA
521*/
522
4db45bf1 523errbody(fp, m, e)
b3cbe40f 524 register FILE *fp;
74c5fe7c 525 register struct mailer *m;
912acb74 526 register ENVELOPE *e;
b3cbe40f 527{
9e3c0a28 528 register FILE *xfile;
e6f08ab1 529 char *p;
7800dbe0
EA
530 register ADDRESS *q;
531 bool printheader;
532 char buf[MAXLINE];
b3cbe40f 533
bc854e30
EA
534 if (e->e_parent == NULL)
535 {
536 syserr("errbody: null parent");
bc854e30
EA
537 putline(" ----- Original message lost -----\n", fp, m);
538 return;
539 }
540
2f6a8a78
EA
541 /*
542 ** Output MIME header.
543 */
544
545 if (e->e_msgboundary != NULL)
546 {
547 putline("This is a MIME-encapsulated message", fp, m);
548 putline("", fp, m);
549 (void) sprintf(buf, "--%s", e->e_msgboundary);
550 putline(buf, fp, m);
551 putline("", fp, m);
552 }
553
44967af8
EA
554 /*
555 ** Output error message header (if specified and available).
556 */
557
558 if (ErrMsgFile != NULL)
559 {
560 if (*ErrMsgFile == '/')
561 {
562 xfile = fopen(ErrMsgFile, "r");
563 if (xfile != NULL)
564 {
565 while (fgets(buf, sizeof buf, xfile) != NULL)
5d99721e
EA
566 {
567 expand(buf, buf, &buf[sizeof buf - 1], e);
44967af8 568 putline(buf, fp, m);
5d99721e 569 }
44967af8 570 (void) fclose(xfile);
7800dbe0 571 putline("\n", fp, m);
44967af8
EA
572 }
573 }
574 else
575 {
5d99721e
EA
576 expand(ErrMsgFile, buf, &buf[sizeof buf - 1], e);
577 putline(buf, fp, m);
2f6a8a78 578 putline("", fp, m);
44967af8
EA
579 }
580 }
581
7800dbe0
EA
582 /*
583 ** Output message introduction
584 */
585
586 printheader = TRUE;
587 for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
588 {
589 if (bitset(QBADADDR, q->q_flags))
590 {
591 if (printheader)
592 {
2f6a8a78 593 putline(" ----- The following addresses failed -----",
7800dbe0
EA
594 fp, m);
595 printheader = FALSE;
596 }
9cdb0b30 597 if (q->q_alias != NULL)
2f6a8a78 598 putline(q->q_alias->q_paddr, fp, m);
9cdb0b30 599 else
2f6a8a78 600 putline(q->q_paddr, fp, m);
7800dbe0
EA
601 }
602 }
603 if (!printheader)
604 putline("\n", fp, m);
605
74c5fe7c
EA
606 /*
607 ** Output transcript of errors
608 */
609
be2fcca9 610 (void) fflush(stdout);
912acb74 611 p = queuename(e->e_parent, 'x');
e6f08ab1 612 if ((xfile = fopen(p, "r")) == NULL)
be2fcca9 613 {
e6f08ab1 614 syserr("Cannot open %s", p);
7800dbe0 615 putline(" ----- Transcript of session is unavailable -----\n", fp, m);
be2fcca9
EA
616 }
617 else
618 {
bc854e30 619 putline(" ----- Transcript of session follows -----\n", fp, m);
912acb74
EA
620 if (e->e_xfp != NULL)
621 (void) fflush(e->e_xfp);
be2fcca9 622 while (fgets(buf, sizeof buf, xfile) != NULL)
4db45bf1 623 putline(buf, fp, m);
bc854e30 624 (void) xfclose(xfile, "errbody xscript", p);
be2fcca9
EA
625 }
626 errno = 0;
74c5fe7c
EA
627
628 /*
629 ** Output text of original message
630 */
631
46b14b48 632 if (NoReturn)
09f53401 633 SendBody = FALSE;
2f6a8a78 634 putline("", fp, m);
bc854e30 635 if (e->e_parent->e_df != NULL)
738043e8 636 {
79bd7c07 637 if (SendBody)
4db45bf1 638 putline(" ----- Unsent message follows -----\n", fp, m);
79bd7c07 639 else
58645b30 640 putline(" ----- Message header follows -----\n", fp, m);
2f6a8a78
EA
641 (void) fflush(fp);
642
643 if (e->e_msgboundary != NULL)
644 {
645 putline("", fp, m);
646 (void) sprintf(buf, "--%s", e->e_msgboundary);
647 putline(buf, fp, m);
58645b30 648 putline("Content-Type: message/rfc822", fp, m);
2f6a8a78
EA
649 putline("", fp, m);
650 }
651 putheader(fp, m, e->e_parent);
652 putline("", fp, m);
653 if (SendBody)
654 putbody(fp, m, e->e_parent, e->e_msgboundary);
58645b30 655 else
cbfdff7c 656 putline(" ----- Message body suppressed -----", fp, m);
738043e8
EA
657 }
658 else
4db45bf1 659 {
4db45bf1 660 putline(" ----- No message was collected -----\n", fp, m);
4db45bf1 661 }
74c5fe7c 662
cbfdff7c
EA
663 if (e->e_msgboundary != NULL)
664 {
665 putline("", fp, m);
666 (void) sprintf(buf, "--%s--", e->e_msgboundary);
667 putline(buf, fp, m);
668 }
2f6a8a78
EA
669 putline("", fp, m);
670
74c5fe7c
EA
671 /*
672 ** Cleanup and exit
673 */
674
b3cbe40f 675 if (errno != 0)
dd1fe05b 676 syserr("errbody: I/O error");
b3cbe40f 677}
63d473ff
EA
678\f/*
679** PRUNEROUTE -- prune an RFC-822 source route
680**
681** Trims down a source route to the last internet-registered hop.
682** This is encouraged by RFC 1123 section 5.3.3.
683**
684** Parameters:
685** addr -- the address
686**
687** Returns:
688** TRUE -- address was modified
689** FALSE -- address could not be pruned
690**
691** Side Effects:
692** modifies addr in-place
693*/
694
695pruneroute(addr)
696 char *addr;
697{
698#ifdef NAMED_BIND
699 char *start, *at, *comma;
700 char c;
701 int rcode;
702 char hostbuf[BUFSIZ];
703 char *mxhosts[MAXMXHOSTS + 1];
704
705 /* check to see if this is really a route-addr */
706 if (*addr != '<' || addr[1] != '@' || addr[strlen(addr) - 1] != '>')
707 return FALSE;
708 start = strchr(addr, ':');
709 at = strrchr(addr, '@');
710 if (start == NULL || at == NULL || at < start)
711 return FALSE;
712
713 /* slice off the angle brackets */
714 strcpy(hostbuf, at + 1);
715 hostbuf[strlen(hostbuf) - 1] = '\0';
716
717 while (start)
718 {
c3577cd6 719 if (getmxrr(hostbuf, mxhosts, FALSE, &rcode) > 0)
63d473ff
EA
720 {
721 strcpy(addr + 1, start + 1);
722 return TRUE;
723 }
724 c = *start;
725 *start = '\0';
726 comma = strrchr(addr, ',');
727 if (comma && comma[1] == '@')
728 strcpy(hostbuf, comma + 2);
729 else
730 comma = 0;
731 *start = c;
732 start = comma;
733 }
734#endif
735 return FALSE;
736}