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