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