Restrict line lengths in bounces. Bug 1760
[exim.git] / src / src / moan.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2015 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8 /* Functions for sending messages to sender or to mailmaster. */
9
10
11 #include "exim.h"
12
13
14
15 /*************************************************
16 *            Write From: line for DSN            *
17 *************************************************/
18
19 /* This function is called to write the From: line in automatically generated
20 messages - bounces, warnings, etc. It expands a configuration item in order to
21 get the text. If the expansion fails, a panic is logged and the default value
22 for the option is used.
23
24 Argument:   the FILE to write to
25 Returns:    nothing
26 */
27
28 void
29 moan_write_from(FILE *f)
30 {
31 uschar *s = expand_string(dsn_from);
32 if (s == NULL)
33   {
34   log_write(0, LOG_MAIN|LOG_PANIC,
35     "Failed to expand dsn_from (using default): %s", expand_string_message);
36   s = expand_string(US DEFAULT_DSN_FROM);
37   }
38 fprintf(f, "From: %s\n", s);
39 }
40
41
42
43 /*************************************************
44 *              Send error message                *
45 *************************************************/
46
47 /* This function sends an error message by opening a pipe to a new process
48 running Exim, and writing a message to it using the "-t" option. This is not
49 used for delivery failures, which have their own code for handing failed
50 addresses.
51
52 Arguments:
53   recipient      addressee for the message
54   ident          identifies the type of error
55   eblock         chain of error_blocks containing data about the error
56   headers        the message's headers
57   message_file   FILE containing the body of the message
58   firstline      contains first line of file, if it was read to check for
59                    "From ", but it turned out not to be
60
61 Returns:         TRUE if message successfully sent
62 */
63
64 static BOOL
65 moan_send_message(uschar *recipient, int ident, error_block *eblock,
66   header_line *headers, FILE *message_file, uschar *firstline)
67 {
68 int written = 0;
69 int fd;
70 int status;
71 int count = 0;
72 int size_limit = bounce_return_size_limit;
73 FILE *f;
74 int pid = child_open_exim(&fd);
75
76 /* Creation of child failed */
77
78 if (pid < 0)
79   {
80   DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
81     strerror(errno));
82   return FALSE;
83   }
84 else DEBUG(D_any) debug_printf("Child process %d for sending message\n", pid);
85
86 /* Creation of child succeeded */
87
88 f = fdopen(fd, "wb");
89 if (errors_reply_to) fprintf(f, "Reply-To: %s\n", errors_reply_to);
90 fprintf(f, "Auto-Submitted: auto-replied\n");
91 moan_write_from(f);
92 fprintf(f, "To: %s\n", recipient);
93
94 switch(ident)
95   {
96   case ERRMESS_BADARGADDRESS:
97     fprintf(f,
98       "Subject: Mail failure - malformed recipient address\n\n");
99     fprintf(f,
100       "A message that you sent contained a recipient address that was incorrectly\n"
101       "constructed:\n\n");
102     fprintf(f, "  %s  %s\n", eblock->text1, eblock->text2);
103     count = Ustrlen(eblock->text1);
104     if (count > 0 && eblock->text1[count-1] == '.')
105       fprintf(f,
106         "\nRecipient addresses must not end with a '.' character.\n");
107     fprintf(f,
108       "\nThe message has not been delivered to any recipients.\n");
109     break;
110
111   case ERRMESS_BADNOADDRESS:
112   case ERRMESS_BADADDRESS:
113     fprintf(f,
114       "Subject: Mail failure - malformed recipient address\n\n");
115     fprintf(f,
116       "A message that you sent contained one or more recipient addresses that were\n"
117       "incorrectly constructed:\n\n");
118
119     while (eblock != NULL)
120       {
121       fprintf(f, "  %s: %s\n", eblock->text1, eblock->text2);
122       count++;
123       eblock = eblock->next;
124       }
125
126     fprintf(f, (count == 1)? "\nThis address has been ignored. " :
127       "\nThese addresses have been ignored. ");
128
129     fprintf(f, (ident == ERRMESS_BADADDRESS)?
130       "The other addresses in the message were\n"
131       "syntactically valid and have been passed on for an attempt at delivery.\n" :
132
133       "There were no other addresses in your\n"
134       "message, and so no attempt at delivery was possible.\n");
135     break;
136
137   case ERRMESS_IGADDRESS:
138     fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
139     fprintf(f,
140       "A message that you sent using the -t command line option contained no\n"
141       "addresses that were not also on the command line, and were therefore\n"
142       "suppressed. This left no recipient addresses, and so no delivery could\n"
143       "be attempted.\n");
144     break;
145
146   case ERRMESS_NOADDRESS:
147     fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
148     fprintf(f,
149       "A message that you sent contained no recipient addresses, and therefore no\n"
150       "delivery could be attempted.\n");
151     break;
152
153   case ERRMESS_IOERR:
154     fprintf(f, "Subject: Mail failure - system failure\n\n");
155     fprintf(f,
156       "A system failure was encountered while processing a message that you sent,\n"
157       "so it has not been possible to deliver it. The error was:\n\n%s\n",
158       eblock->text1);
159     break;
160
161   case ERRMESS_VLONGHEADER:
162     fprintf(f, "Subject: Mail failure - overlong header section\n\n");
163     fprintf(f,
164       "A message that you sent contained a header section that was excessively\n"
165       "long and could not be handled by the mail transmission software. The\n"
166       "message has not been delivered to any recipients.\n");
167     break;
168
169   case ERRMESS_VLONGHDRLINE:
170     fprintf(f, "Subject: Mail failure - overlong header line\n\n");
171     fprintf(f,
172       "A message that you sent contained a header line that was excessively\n"
173       "long and could not be handled by the mail transmission software. The\n"
174       "message has not been delivered to any recipients.\n");
175     break;
176
177   case ERRMESS_TOOBIG:
178     fprintf(f, "Subject: Mail failure - message too big\n\n");
179     fprintf(f,
180       "A message that you sent was longer than the maximum size allowed on this\n"
181       "system. It was not delivered to any recipients.\n");
182     break;
183
184   case ERRMESS_TOOMANYRECIP:
185     fprintf(f, "Subject: Mail failure - too many recipients\n\n");
186     fprintf(f,
187       "A message that you sent contained more recipients than allowed on this\n"
188       "system. It was not delivered to any recipients.\n");
189     break;
190
191   case ERRMESS_LOCAL_SCAN:
192   case ERRMESS_LOCAL_ACL:
193     fprintf(f, "Subject: Mail failure - rejected by local scanning code\n\n");
194     fprintf(f,
195       "A message that you sent was rejected by the local scanning code that\n"
196       "checks incoming messages on this system.");
197       if (eblock->text1)
198         fprintf(f, " The following error was given:\n\n  %s", eblock->text1);
199   fprintf(f, "\n");
200   break;
201
202 #ifdef EXPERIMENTAL_DMARC
203   case ERRMESS_DMARC_FORENSIC:
204     bounce_return_message = TRUE;
205     bounce_return_body    = FALSE;
206     fprintf(f,
207           "Subject: DMARC Forensic Report for %s from IP %s\n\n",
208           ((eblock == NULL) ? US"Unknown" : eblock->text2),
209           sender_host_address);
210     fprintf(f,
211       "A message claiming to be from you has failed the published DMARC\n"
212       "policy for your domain.\n\n");
213     while (eblock != NULL)
214       {
215       fprintf(f, "  %s: %s\n", eblock->text1, eblock->text2);
216       count++;
217       eblock = eblock->next;
218       }
219   break;
220 #endif
221
222   default:
223     fprintf(f, "Subject: Mail failure\n\n");
224     fprintf(f,
225       "A message that you sent has caused the error routine to be entered with\n"
226       "an unknown error number (%d).\n", ident);
227     break;
228   }
229
230 /* Now, if configured, copy the message; first the headers and then the rest of
231 the input if available, up to the configured limit, if the option for including
232 message bodies in bounces is set. */
233
234 if (bounce_return_message)
235   {
236   if (bounce_return_body)
237     {
238     fprintf(f, "\n"
239       "------ This is a copy of your message, including all the headers.");
240     if (size_limit == 0 || size_limit > thismessage_size_limit)
241       size_limit = thismessage_size_limit;
242     if (size_limit > 0 && size_limit < message_size)
243       {
244       int x = size_limit;
245       uschar *k = US"";
246       if ((x & 1023) == 0)
247         {
248         k = US"K";
249         x >>= 10;
250         }
251       fprintf(f, "\n"
252         "------ No more than %d%s characters of the body are included.\n\n",
253           x, k);
254       }
255     else fprintf(f, " ------\n\n");
256     }
257   else
258     {
259     fprintf(f, "\n"
260       "------ This is a copy of the headers that were received before the "
261       "error\n       was detected.\n\n");
262     }
263
264   /* If the error occurred before the Received: header was created, its text
265   field will still be NULL; just omit such a header line. */
266
267   while (headers)
268     {
269     if (headers->text != NULL) fprintf(f, "%s", CS headers->text);
270     headers = headers->next;
271     }
272
273   if (ident != ERRMESS_VLONGHEADER && ident != ERRMESS_VLONGHDRLINE)
274     fputc('\n', f);
275
276   /* After early detection of an error, the message file may be STDIN,
277   in which case we might have to terminate on a line containing just "."
278   as well as on EOF. We may already have the first line in memory. */
279
280   if (bounce_return_body && message_file)
281     {
282     int ch;
283     enum {midline, beginline, haddot} state = beginline;
284     BOOL enddot = dot_ends && message_file == stdin;
285     uschar * buf = store_get(bounce_return_linesize_limit+2);
286
287     if (firstline) fprintf(f, "%s", CS firstline);
288
289     while (fgets(buf, bounce_return_linesize_limit+2, message_file))
290       {
291       int len;
292
293       if (enddot && *buf == '.' && buf[1] == '\n')
294         {
295         fputc('.', f);
296         break;
297         }
298
299       len = Ustrlen(buf);
300       if (buf[len-1] != '\n')
301         {       /* eat rest of partial line */
302         int ch;
303         while ((ch = fgetc(message_file)) != EOF && ch != '\n') ;
304         }
305
306       if (size_limit > 0 && len > size_limit - written)
307         {
308         buf[size_limit - written] = '\0';
309         fputs(buf, f);
310         break;
311         }
312
313       fputs(buf, f);
314       }
315     }
316 #ifdef EXPERIMENTAL_DMARC
317   /* Overkill, but use exact test in case future code gets inserted */
318   else if (bounce_return_body && message_file == NULL)
319     {
320     /*XXX limit line length here? */
321     /* This doesn't print newlines, disable until can parse and fix
322      * output to be legible.  */
323     fprintf(f, "%s", expand_string(US"$message_body"));
324     }
325 #endif
326   }
327 /* Close the file, which should send an EOF to the child process
328 that is receiving the message. Wait for it to finish, without a timeout. */
329
330 (void)fclose(f);
331 status = child_close(pid, 0);  /* Waits for child to close */
332 if (status != 0)
333   {
334   uschar *msg = US"Child mail process returned status";
335   if (status == -257)
336     log_write(0, LOG_MAIN, "%s %d: errno=%d: %s", msg, status, errno,
337       strerror(errno));
338   else
339     log_write(0, LOG_MAIN, "%s %d", msg, status);
340   return FALSE;
341   }
342
343 return TRUE;
344 }
345
346
347
348 /*************************************************
349 *          Send message to sender                *
350 *************************************************/
351
352 /* This function is called when errors are detected during the receipt of a
353 message. Delivery failures are handled separately in deliver.c.
354
355 If there is a valid sender_address, and the failing message is not a local
356 error message, then this function calls moan_send_message to send a message to
357 that person. If the sender's address is null, then an error has occurred with a
358 message that was generated by a mailer daemon. All we can do is to write
359 information to log files. The same action is taken if local_error_message is
360 set - this can happen for non null-senders in certain configurations where exim
361 doesn't run setuid root.
362
363 Arguments:
364   ident         identifies the particular error
365   eblock        chain of error_blocks containing data about the error
366   headers       message's headers (chain)
367   message_file  a FILE where the body of the message can be read
368   check_sender  if TRUE, read the first line of the file for a possible
369                   "From " sender (if a trusted caller)
370
371 Returns:        FALSE if there is no sender_address to send to;
372                 else the return from moan_send_message()
373 */
374
375 BOOL
376 moan_to_sender(int ident, error_block *eblock, header_line *headers,
377   FILE *message_file, BOOL check_sender)
378 {
379 uschar *firstline = NULL;
380 uschar *msg = US"Error while reading message with no usable sender address";
381
382 if (message_reference)
383   msg = string_sprintf("%s (R=%s)", msg, message_reference);
384
385 /* Find the sender from a From line if permitted and possible */
386
387 if (check_sender && message_file && trusted_caller &&
388     Ufgets(big_buffer, BIG_BUFFER_SIZE, message_file) != NULL)
389   {
390   uschar *new_sender = NULL;
391   if (regex_match_and_setup(regex_From, big_buffer, 0, -1))
392     new_sender = expand_string(uucp_from_sender);
393   if (new_sender) sender_address = new_sender;
394     else firstline = big_buffer;
395   }
396
397 /* If viable sender address, send a message */
398
399 if (sender_address && sender_address[0] && !local_error_message)
400   return moan_send_message(sender_address, ident, eblock, headers,
401     message_file, firstline);
402
403 /* Otherwise, we can only log */
404
405 switch(ident)
406   {
407   case ERRMESS_BADARGADDRESS:
408   case ERRMESS_BADNOADDRESS:
409   case ERRMESS_BADADDRESS:
410   log_write(0, LOG_MAIN, "%s: at least one malformed recipient address: "
411     "%s - %s", msg, eblock->text1, eblock->text2);
412   break;
413
414   case ERRMESS_IGADDRESS:
415   case ERRMESS_NOADDRESS:
416   log_write(0, LOG_MAIN, "%s: no recipient addresses", msg);
417   break;
418
419   /* This error has already been logged. */
420   case ERRMESS_IOERR:
421   break;
422
423   case ERRMESS_VLONGHEADER:
424   log_write(0, LOG_MAIN, "%s: excessively long message header section read "
425     "(more than %d characters)", msg, header_maxsize);
426   break;
427
428   case ERRMESS_VLONGHDRLINE:
429   log_write(0, LOG_MAIN, "%s: excessively long message header line read "
430     "(more than %d characters)", msg, header_line_maxsize);
431   break;
432
433   case ERRMESS_TOOBIG:
434   log_write(0, LOG_MAIN, "%s: message too big (limit set to %d)", msg,
435     thismessage_size_limit);
436   break;
437
438   case ERRMESS_TOOMANYRECIP:
439   log_write(0, LOG_MAIN, "%s: too many recipients (max set to %d)", msg,
440     recipients_max);
441   break;
442
443   case ERRMESS_LOCAL_SCAN:
444   log_write(0, LOG_MAIN, "%s: rejected by local_scan: %s", msg, eblock->text1);
445   break;
446
447   case ERRMESS_LOCAL_ACL:
448   log_write(0, LOG_MAIN, "%s: rejected by non-SMTP ACL: %s", msg, eblock->text1);
449   break;
450
451   default:
452   log_write(0, LOG_MAIN|LOG_PANIC, "%s: unknown error number %d", msg,
453     ident);
454   break;
455   }
456
457 return FALSE;
458 }
459
460
461
462 /*************************************************
463 *            Send message to someone             *
464 *************************************************/
465
466 /* This is called when exim is configured to tell someone (often the
467 mailmaster) about some incident.
468
469 Arguments:
470   who           address to send mail to
471   addr          chain of deferred addresses whose details are to be included
472   subject       subject text for the message
473   format        a printf() format for the body of the message
474   ...           arguments for the format
475
476 Returns:        nothing
477 */
478
479 void
480 moan_tell_someone(uschar *who, address_item *addr,
481   const uschar *subject, const char *format, ...)
482 {
483 FILE *f;
484 va_list ap;
485 int fd;
486 int pid = child_open_exim(&fd);
487
488 if (pid < 0)
489   {
490   DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
491     strerror(errno));
492   return;
493   }
494
495 f = fdopen(fd, "wb");
496 fprintf(f, "Auto-Submitted: auto-replied\n");
497 moan_write_from(f);
498 fprintf(f, "To: %s\n", who);
499 fprintf(f, "Subject: %s\n\n", subject);
500 va_start(ap, format);
501 vfprintf(f, format, ap);
502 va_end(ap);
503
504 if (addr != NULL)
505   {
506   fprintf(f, "\nThe following address(es) have yet to be delivered:\n");
507   for (; addr != NULL; addr = addr->next)
508     {
509     uschar *parent = (addr->parent == NULL)? NULL : addr->parent->address;
510     fprintf(f, "  %s", addr->address);
511     if (parent != NULL) fprintf(f, " <%s>", parent);
512     if (addr->basic_errno > 0) fprintf(f, ": %s", strerror(addr->basic_errno));
513     if (addr->message != NULL) fprintf(f, ": %s", addr->message);
514     fprintf(f, "\n");
515     }
516   }
517
518 (void)fclose(f);
519 child_close(pid, 0);  /* Waits for child to close; no timeout */
520 }
521
522
523
524 /*************************************************
525 *            Handle SMTP batch error             *
526 *************************************************/
527
528 /* This is called when something goes wrong in batched (-bS) SMTP input.
529 Information is written to stdout and/or stderr, and Exim exits with a non-zero
530 completion code. BSMTP is almost always called by some other program, so it is
531 up to that program to interpret the return code and do something with the error
532 information, and also to preserve the batch input file for human analysis.
533
534 Formerly, Exim used to attempt to continue after some errors, but this strategy
535 has been abandoned as it can lead to loss of messages.
536
537 Arguments:
538   cmd_buffer   the command causing the error, or NULL
539   format       a printf() format
540   ...          arguments for the format
541
542 Returns:       does not return; exits from the program
543                exit code = 1 if some messages were accepted
544                exit code = 2 if no messages were accepted
545 */
546
547 void
548 moan_smtp_batch(uschar *cmd_buffer, const char *format, ...)
549 {
550 va_list ap;
551 int yield = (receive_messagecount > 0)? 1 : 2;
552
553 DEBUG(D_any) debug_printf("Handling error in batched SMTP input\n");
554
555 /* On stdout, write stuff that a program could parse fairly easily. */
556
557 va_start(ap, format);
558 vfprintf(stdout, format, ap);
559 va_end(ap);
560
561 fprintf(stdout, "\nTransaction started in line %d\n",
562   bsmtp_transaction_linecount);
563 fprintf(stdout,   "Error detected in line %d\n", receive_linecount);
564 if (cmd_buffer != NULL) fprintf(stdout, "%s\n", cmd_buffer);
565
566 /* On stderr, write stuff for human consumption */
567
568 fprintf(stderr,
569   "An error was detected while processing a file of BSMTP input.\n"
570   "The error message was:\n\n  ");
571
572 va_start(ap, format);
573 vfprintf(stderr, format, ap);
574 va_end(ap);
575
576 fprintf(stderr,
577   "\n\nThe SMTP transaction started in line %d.\n"
578       "The error was detected in line %d.\n",
579   bsmtp_transaction_linecount, receive_linecount);
580
581 if (cmd_buffer != NULL)
582   {
583   fprintf(stderr, "The SMTP command at fault was:\n\n   %s\n\n",
584     cmd_buffer);
585   }
586
587 fprintf(stderr, "%d previous message%s successfully processed.\n",
588   receive_messagecount, (receive_messagecount == 1)? " was" : "s were");
589
590 fprintf(stderr, "The rest of the batch was abandoned.\n");
591
592 exim_exit(yield);
593 }
594
595
596
597
598 /*************************************************
599 *         Check for error copies                 *
600 *************************************************/
601
602 /* This function is passed the recipient of an error message, and must check
603 the error_copies string to see whether there is an additional recipient list to
604 which errors for this recipient must be bcc'd. The incoming recipient is always
605 fully qualified.
606
607 Argument:   recipient address
608 Returns:    additional recipient list or NULL
609 */
610
611 uschar *
612 moan_check_errorcopy(uschar *recipient)
613 {
614 uschar *item, *localpart, *domain;
615 const uschar *listptr = errors_copy;
616 uschar *yield = NULL;
617 uschar buffer[256];
618 int sep = 0;
619 int llen;
620
621 if (errors_copy == NULL) return NULL;
622
623 /* Set up pointer to the local part and domain, and compute the
624 length of the local part. */
625
626 localpart = recipient;
627 domain = Ustrrchr(recipient, '@');
628 if (domain == NULL) return NULL;  /* should not occur, but avoid crash */
629 llen = domain++ - recipient;
630
631 /* Scan through the configured items */
632
633 while ((item = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer)))
634        != NULL)
635   {
636   const uschar *newaddress = item;
637   const uschar *pattern = string_dequote(&newaddress);
638
639   /* If no new address found, just skip this item. */
640
641   while (isspace(*newaddress)) newaddress++;
642   if (*newaddress == 0) continue;
643
644   /* We now have an item to match as an address in item, and the additional
645   address in newaddress. If the pattern matches, expand the new address string
646   and return it. During expansion, make local part and domain available for
647   insertion. This requires a copy to be made; we can't just temporarily
648   terminate it, as the whole address is required for $0. */
649
650   if (match_address_list(recipient, TRUE, TRUE, &pattern, NULL, 0, UCHAR_MAX+1,
651         NULL) == OK)
652     {
653     deliver_localpart = string_copyn(localpart, llen);
654     deliver_domain = domain;
655     yield = expand_string_copy(newaddress);
656     deliver_domain = deliver_localpart = NULL;
657     if (yield == NULL)
658       log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand %s when processing "
659         "errors_copy: %s", newaddress, expand_string_message);
660     break;
661     }
662   }
663
664 DEBUG(D_any) debug_printf("errors_copy check returned %s\n",
665   (yield == NULL)? US"NULL" : yield);
666
667 expand_nmax = -1;
668 return yield;
669 }
670
671
672
673 /************************************************
674 *        Handle skipped syntax errors           *
675 ************************************************/
676
677 /* This function is called by the redirect router when it has skipped over one
678 or more syntax errors in the list of addresses. If there is an address to mail
679 to, send a message, and always write the information to the log. In the case of
680 a filter file, a "syntax error" might actually be something else, such as the
681 inability to open a log file. Thus, the wording of the error message is
682 general.
683
684 Arguments:
685   rname             the router name
686   eblock            chain of error blocks
687   syntax_errors_to  address to send mail to, or NULL
688   some              TRUE if some addresses were generated; FALSE if none were
689   custom            custom message text
690
691 Returns:            FALSE if string expansion failed; TRUE otherwise
692 */
693
694 BOOL
695 moan_skipped_syntax_errors(uschar *rname, error_block *eblock,
696   uschar *syntax_errors_to, BOOL some, uschar *custom)
697 {
698 int pid, fd;
699 uschar *s, *t;
700 FILE *f;
701 error_block *e;
702
703 for (e = eblock; e != NULL; e = e->next)
704   {
705   if (e->text2 != NULL)
706     log_write(0, LOG_MAIN, "%s router: skipped error: %s in \"%s\"",
707       rname, e->text1, e->text2);
708   else
709     log_write(0, LOG_MAIN, "%s router: skipped error: %s", rname,
710       e->text1);
711   }
712
713 if (syntax_errors_to == NULL) return TRUE;
714
715 s = expand_string(syntax_errors_to);
716 if (s == NULL)
717   {
718   log_write(0, LOG_MAIN, "%s router failed to expand %s: %s", rname,
719     syntax_errors_to, expand_string_message);
720   return FALSE;
721   }
722
723 /* If we can't create a process to send the message, just forget about
724 it. */
725
726 pid = child_open_exim(&fd);
727
728 if (pid < 0)
729   {
730   DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
731     strerror(errno));
732   return TRUE;
733   }
734
735 f = fdopen(fd, "wb");
736 fprintf(f, "Auto-Submitted: auto-replied\n");
737 moan_write_from(f);
738 fprintf(f, "To: %s\n", s);
739 fprintf(f, "Subject: error(s) in forwarding or filtering\n\n");
740
741 if (custom != NULL)
742   {
743   t = expand_string(custom);
744   if (t == NULL)
745     {
746     log_write(0, LOG_MAIN, "%s router failed to expand %s: %s", rname,
747       custom, expand_string_message);
748     return FALSE;
749     }
750   fprintf(f, "%s\n\n", t);
751   }
752
753 fprintf(f, "The %s router encountered the following error(s):\n\n",
754   rname);
755
756 for (e = eblock; e != NULL; e = e->next)
757   {
758   fprintf(f, "  %s", e->text1);
759   if (e->text2 != NULL)
760     fprintf(f, " in the address\n  \"%s\"", e->text2);
761   fprintf(f, "\n\n");
762   }
763
764 if (some)
765   fprintf(f, "Other addresses were processed normally.\n");
766 else
767   fprintf(f, "No valid addresses were generated.\n");
768
769 (void)fclose(f);
770 child_close(pid, 0);  /* Waits for child to close; no timeout */
771
772 return TRUE;
773 }
774
775 /* End of moan.c */