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