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