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