Merge branch 'list_safety'
[exim.git] / src / src / moan.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
0a49a7a4 5/* Copyright (c) University of Cambridge 1995 - 2009 */
059ec3d9
PH
6/* See the file NOTICE for conditions of use and distribution. */
7
8/* Functions for sending messages to sender or to mailmaster. */
9
10
11#include "exim.h"
12
13
14
0e22dfd1
PH
15/*************************************************
16* Write From: line for DSN *
17*************************************************/
18
19/* This function is called to write the From: line in automatically generated
20messages - bounces, warnings, etc. It expands a configuration item in order to
21get the text. If the expansion fails, a panic is logged and the default value
22for the option is used.
23
24Argument: the FILE to write to
25Returns: nothing
26*/
27
28void
29moan_write_from(FILE *f)
30{
31uschar *s = expand_string(dsn_from);
32if (s == NULL)
33 {
34 log_write(0, LOG_MAIN|LOG_PANIC,
35 "Failed to expand dsn_from (using default): %s", expand_string_message);
36 s = expand_string(US DEFAULT_DSN_FROM);
37 }
38fprintf(f, "From: %s\n", s);
39}
40
41
42
059ec3d9
PH
43/*************************************************
44* Send error message *
45*************************************************/
46
47/* This function sends an error message by opening a pipe to a new process
48running Exim, and writing a message to it using the "-t" option. This is not
49used for delivery failures, which have their own code for handing failed
50addresses.
51
52Arguments:
53 recipient addressee for the message
54 ident identifies the type of error
55 eblock chain of error_blocks containing data about the error
56 headers the message's headers
57 message_file FILE containing the body of the message
58 firstline contains first line of file, if it was read to check for
59 "From ", but it turned out not to be
60
61Returns: TRUE if message successfully sent
62*/
63
64static BOOL
65moan_send_message(uschar *recipient, int ident, error_block *eblock,
66 header_line *headers, FILE *message_file, uschar *firstline)
67{
68int written = 0;
69int fd;
70int status;
71int count = 0;
72int size_limit = bounce_return_size_limit;
73FILE *f;
74int pid = child_open_exim(&fd);
75
76/* Creation of child failed */
77
78if (pid < 0)
79 {
80 DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
81 strerror(errno));
82 return FALSE;
83 }
84else DEBUG(D_any) debug_printf("Child process %d for sending message\n", pid);
85
86/* Creation of child succeeded */
87
88f = fdopen(fd, "wb");
89if (errors_reply_to != NULL) fprintf(f, "Reply-To: %s\n", errors_reply_to);
456682f5 90fprintf(f, "Auto-Submitted: auto-replied\n");
0e22dfd1 91moan_write_from(f);
059ec3d9
PH
92fprintf(f, "To: %s\n", recipient);
93
94switch(ident)
95 {
96 case ERRMESS_BADARGADDRESS:
97 fprintf(f,
98 "Subject: Mail failure - malformed recipient address\n\n");
99 fprintf(f,
100 "A message that you sent contained a recipient address that was incorrectly\n"
101 "constructed:\n\n");
102 fprintf(f, " %s %s\n", eblock->text1, eblock->text2);
103 count = Ustrlen(eblock->text1);
104 if (count > 0 && eblock->text1[count-1] == '.')
105 fprintf(f,
106 "\nRecipient addresses must not end with a '.' character.\n");
107 fprintf(f,
108 "\nThe message has not been delivered to any recipients.\n");
109 break;
110
111 case ERRMESS_BADNOADDRESS:
112 case ERRMESS_BADADDRESS:
113 fprintf(f,
114 "Subject: Mail failure - malformed recipient address\n\n");
115 fprintf(f,
116 "A message that you sent contained one or more recipient addresses that were\n"
117 "incorrectly constructed:\n\n");
118
119 while (eblock != NULL)
120 {
121 fprintf(f, " %s: %s\n", eblock->text1, eblock->text2);
122 count++;
123 eblock = eblock->next;
124 }
125
126 fprintf(f, (count == 1)? "\nThis address has been ignored. " :
127 "\nThese addresses have been ignored. ");
128
129 fprintf(f, (ident == ERRMESS_BADADDRESS)?
130 "The other addresses in the message were\n"
131 "syntactically valid and have been passed on for an attempt at delivery.\n" :
132
133 "There were no other addresses in your\n"
134 "message, and so no attempt at delivery was possible.\n");
135 break;
136
137 case ERRMESS_IGADDRESS:
138 fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
139 fprintf(f,
140 "A message that you sent using the -t command line option contained no\n"
141 "addresses that were not also on the command line, and were therefore\n"
142 "suppressed. This left no recipient addresses, and so no delivery could\n"
143 "be attempted.\n");
144 break;
145
146 case ERRMESS_NOADDRESS:
147 fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
148 fprintf(f,
149 "A message that you sent contained no recipient addresses, and therefore no\n"
150 "delivery could be attempted.\n");
151 break;
152
153 case ERRMESS_IOERR:
154 fprintf(f, "Subject: Mail failure - system failure\n\n");
155 fprintf(f,
156 "A system failure was encountered while processing a message that you sent,\n"
157 "so it has not been possible to deliver it. The error was:\n\n%s\n",
158 eblock->text1);
159 break;
160
161 case ERRMESS_VLONGHEADER:
162 fprintf(f, "Subject: Mail failure - overlong header section\n\n");
163 fprintf(f,
164 "A message that you sent contained a header section that was excessively\n"
165 "long and could not be handled by the mail transmission software. The\n"
166 "message has not been delivered to any recipients.\n");
167 break;
168
169 case ERRMESS_VLONGHDRLINE:
170 fprintf(f, "Subject: Mail failure - overlong header line\n\n");
171 fprintf(f,
172 "A message that you sent contained a header line that was excessively\n"
173 "long and could not be handled by the mail transmission software. The\n"
174 "message has not been delivered to any recipients.\n");
175 break;
176
177 case ERRMESS_TOOBIG:
178 fprintf(f, "Subject: Mail failure - message too big\n\n");
179 fprintf(f,
180 "A message that you sent was longer than the maximum size allowed on this\n"
181 "system. It was not delivered to any recipients.\n");
182 break;
183
184 case ERRMESS_TOOMANYRECIP:
185 fprintf(f, "Subject: Mail failure - too many recipients\n\n");
186 fprintf(f,
187 "A message that you sent contained more recipients than allowed on this\n"
188 "system. It was not delivered to any recipients.\n");
189 break;
190
191 case ERRMESS_LOCAL_SCAN:
192 case ERRMESS_LOCAL_ACL:
193 fprintf(f, "Subject: Mail failure - rejected by local scanning code\n\n");
194 fprintf(f,
195 "A message that you sent was rejected by the local scanning code that\n"
196 "checks incoming messages on this system.");
197 if (eblock->text1 != NULL)
198 {
199 fprintf(f,
200 " The following error was given:\n\n %s", eblock->text1);
201 }
202 fprintf(f, "\n");
203 break;
204
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
715ab376
PH
213/* Now, if configured, copy the message; first the headers and then the rest of
214the input if available, up to the configured limit, if the option for including
215message bodies in bounces is set. */
059ec3d9 216
715ab376 217if (bounce_return_message)
059ec3d9 218 {
715ab376
PH
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
059ec3d9 241 {
715ab376
PH
242 fprintf(f, "\n"
243 "------ This is a copy of the headers that were received before the "
244 "error\n was detected.\n\n");
059ec3d9 245 }
059ec3d9 246
715ab376
PH
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. */
059ec3d9 249
715ab376
PH
250 while (headers != NULL)
251 {
252 if (headers->text != NULL) fprintf(f, "%s", CS headers->text);
253 headers = headers->next;
254 }
059ec3d9 255
715ab376
PH
256 if (ident != ERRMESS_VLONGHEADER && ident != ERRMESS_VLONGHDRLINE)
257 fputc('\n', f);
059ec3d9 258
715ab376
PH
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. */
059ec3d9 262
715ab376 263 if (bounce_return_body && message_file != NULL)
059ec3d9 264 {
715ab376
PH
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)
059ec3d9 270 {
715ab376
PH
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 }
059ec3d9
PH
281 }
282 }
283 }
284
285/* Close the file, which should send an EOF to the child process
286that is receiving the message. Wait for it to finish, without a timeout. */
287
f1e894f3 288(void)fclose(f);
059ec3d9
PH
289status = child_close(pid, 0); /* Waits for child to close */
290if (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
301return 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
311message. Delivery failures are handled separately in deliver.c.
312
313If there is a valid sender_address, and the failing message is not a local
314error message, then this function calls moan_send_message to send a message to
315that person. If the sender's address is null, then an error has occurred with a
316message that was generated by a mailer daemon. All we can do is to write
317information to log files. The same action is taken if local_error_message is
318set - this can happen for non null-senders in certain configurations where exim
319doesn't run setuid root.
320
321Arguments:
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
329Returns: FALSE if there is no sender_address to send to;
330 else the return from moan_send_message()
331*/
332
333BOOL
334moan_to_sender(int ident, error_block *eblock, header_line *headers,
335 FILE *message_file, BOOL check_sender)
336{
337uschar *firstline = NULL;
338uschar *msg = US"Error while reading message with no usable sender address";
339
340if (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
345if (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
357if (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
363switch(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
415return 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
425mailmaster) about some incident.
426
427Arguments:
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
434Returns: nothing
435*/
436
437void
1ba28e2b
PP
438moan_tell_someone(uschar *who, address_item *addr,
439 const uschar *subject, const char *format, ...)
059ec3d9
PH
440{
441FILE *f;
442va_list ap;
443int fd;
444int pid = child_open_exim(&fd);
445
446if (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
453f = fdopen(fd, "wb");
456682f5 454fprintf(f, "Auto-Submitted: auto-replied\n");
0e22dfd1 455moan_write_from(f);
059ec3d9
PH
456fprintf(f, "To: %s\n", who);
457fprintf(f, "Subject: %s\n\n", subject);
458va_start(ap, format);
459vfprintf(f, format, ap);
460va_end(ap);
461
462if (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
f1e894f3 476(void)fclose(f);
059ec3d9
PH
477child_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.
487Information is written to stdout and/or stderr, and Exim exits with a non-zero
488completion code. BSMTP is almost always called by some other program, so it is
489up to that program to interpret the return code and do something with the error
490information, and also to preserve the batch input file for human analysis.
491
492Formerly, Exim used to attempt to continue after some errors, but this strategy
493has been abandoned as it can lead to loss of messages.
494
495Arguments:
496 cmd_buffer the command causing the error, or NULL
497 format a printf() format
498 ... arguments for the format
499
500Returns: 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
505void
1ba28e2b 506moan_smtp_batch(uschar *cmd_buffer, const char *format, ...)
059ec3d9
PH
507{
508va_list ap;
509int yield = (receive_messagecount > 0)? 1 : 2;
510
511DEBUG(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
515va_start(ap, format);
516vfprintf(stdout, format, ap);
517va_end(ap);
518
519fprintf(stdout, "\nTransaction started in line %d\n",
520 bsmtp_transaction_linecount);
521fprintf(stdout, "Error detected in line %d\n", receive_linecount);
522if (cmd_buffer != NULL) fprintf(stdout, "%s\n", cmd_buffer);
523
524/* On stderr, write stuff for human consumption */
525
526fprintf(stderr,
527 "An error was detected while processing a file of BSMTP input.\n"
528 "The error message was:\n\n ");
529
530va_start(ap, format);
531vfprintf(stderr, format, ap);
532va_end(ap);
533
534fprintf(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
539if (cmd_buffer != NULL)
540 {
541 fprintf(stderr, "The SMTP command at fault was:\n\n %s\n\n",
542 cmd_buffer);
543 }
544
545fprintf(stderr, "%d previous message%s successfully processed.\n",
546 receive_messagecount, (receive_messagecount == 1)? " was" : "s were");
547
548fprintf(stderr, "The rest of the batch was abandoned.\n");
549
550exim_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
561the error_copies string to see whether there is an additional recipient list to
562which errors for this recipient must be bcc'd. The incoming recipient is always
563fully qualified.
564
565Argument: recipient address
566Returns: additional recipient list or NULL
567*/
568
569uschar *
570moan_check_errorcopy(uschar *recipient)
571{
572uschar *item, *localpart, *domain;
573uschar *listptr = errors_copy;
574uschar *yield = NULL;
575uschar buffer[256];
576int sep = 0;
577int llen;
578
579if (errors_copy == NULL) return NULL;
580
581/* Set up pointer to the local part and domain, and compute the
582length of the local part. */
583
584localpart = recipient;
bc64a74d 585domain = Ustrrchr(recipient, '@');
059ec3d9
PH
586if (domain == NULL) return NULL; /* should not occur, but avoid crash */
587llen = domain++ - recipient;
588
589/* Scan through the configured items */
590
591while ((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 {
ce9f225c 611 deliver_localpart = string_copyn(localpart, llen);
059ec3d9
PH
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
622DEBUG(D_any) debug_printf("errors_copy check returned %s\n",
623 (yield == NULL)? US"NULL" : yield);
624
625expand_nmax = -1;
626return 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
636or more syntax errors in the list of addresses. If there is an address to mail
637to, send a message, and always write the information to the log. In the case of
638a filter file, a "syntax error" might actually be something else, such as the
639inability to open a log file. Thus, the wording of the error message is
640general.
641
642Arguments:
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
649Returns: FALSE if string expansion failed; TRUE otherwise
650*/
651
652BOOL
653moan_skipped_syntax_errors(uschar *rname, error_block *eblock,
654 uschar *syntax_errors_to, BOOL some, uschar *custom)
655{
656int pid, fd;
657uschar *s, *t;
658FILE *f;
659error_block *e;
660
661for (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
671if (syntax_errors_to == NULL) return TRUE;
672
673s = expand_string(syntax_errors_to);
674if (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
682it. */
683
684pid = child_open_exim(&fd);
685
686if (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
693f = fdopen(fd, "wb");
456682f5 694fprintf(f, "Auto-Submitted: auto-replied\n");
0e22dfd1 695moan_write_from(f);
059ec3d9
PH
696fprintf(f, "To: %s\n", s);
697fprintf(f, "Subject: error(s) in forwarding or filtering\n\n");
698
699if (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
711fprintf(f, "The %s router encountered the following error(s):\n\n",
712 rname);
713
714for (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
722if (some)
723 fprintf(f, "Other addresses were processed normally.\n");
724else
725 fprintf(f, "No valid addresses were generated.\n");
726
f1e894f3 727(void)fclose(f);
059ec3d9
PH
728child_close(pid, 0); /* Waits for child to close; no timeout */
729
730return TRUE;
731}
732
733/* End of moan.c */