Also memset(.., 0, ..) the pre-TLS input buffer.
[exim.git] / src / src / moan.c
CommitLineData
0a49a7a4 1/* $Cambridge: exim/src/src/moan.c,v 1.11 2009/11/16 19:50:37 nm4 Exp $ */
059ec3d9
PH
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
0a49a7a4 7/* Copyright (c) University of Cambridge 1995 - 2009 */
059ec3d9
PH
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
0e22dfd1
PH
17/*************************************************
18* Write From: line for DSN *
19*************************************************/
20
21/* This function is called to write the From: line in automatically generated
22messages - bounces, warnings, etc. It expands a configuration item in order to
23get the text. If the expansion fails, a panic is logged and the default value
24for the option is used.
25
26Argument: the FILE to write to
27Returns: nothing
28*/
29
30void
31moan_write_from(FILE *f)
32{
33uschar *s = expand_string(dsn_from);
34if (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 }
40fprintf(f, "From: %s\n", s);
41}
42
43
44
059ec3d9
PH
45/*************************************************
46* Send error message *
47*************************************************/
48
49/* This function sends an error message by opening a pipe to a new process
50running Exim, and writing a message to it using the "-t" option. This is not
51used for delivery failures, which have their own code for handing failed
52addresses.
53
54Arguments:
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
63Returns: TRUE if message successfully sent
64*/
65
66static BOOL
67moan_send_message(uschar *recipient, int ident, error_block *eblock,
68 header_line *headers, FILE *message_file, uschar *firstline)
69{
70int written = 0;
71int fd;
72int status;
73int count = 0;
74int size_limit = bounce_return_size_limit;
75FILE *f;
76int pid = child_open_exim(&fd);
77
78/* Creation of child failed */
79
80if (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 }
86else DEBUG(D_any) debug_printf("Child process %d for sending message\n", pid);
87
88/* Creation of child succeeded */
89
90f = fdopen(fd, "wb");
91if (errors_reply_to != NULL) fprintf(f, "Reply-To: %s\n", errors_reply_to);
456682f5 92fprintf(f, "Auto-Submitted: auto-replied\n");
0e22dfd1 93moan_write_from(f);
059ec3d9
PH
94fprintf(f, "To: %s\n", recipient);
95
96switch(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
715ab376
PH
215/* Now, if configured, copy the message; first the headers and then the rest of
216the input if available, up to the configured limit, if the option for including
217message bodies in bounces is set. */
059ec3d9 218
715ab376 219if (bounce_return_message)
059ec3d9 220 {
715ab376
PH
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
059ec3d9 243 {
715ab376
PH
244 fprintf(f, "\n"
245 "------ This is a copy of the headers that were received before the "
246 "error\n was detected.\n\n");
059ec3d9 247 }
059ec3d9 248
715ab376
PH
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. */
059ec3d9 251
715ab376
PH
252 while (headers != NULL)
253 {
254 if (headers->text != NULL) fprintf(f, "%s", CS headers->text);
255 headers = headers->next;
256 }
059ec3d9 257
715ab376
PH
258 if (ident != ERRMESS_VLONGHEADER && ident != ERRMESS_VLONGHDRLINE)
259 fputc('\n', f);
059ec3d9 260
715ab376
PH
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. */
059ec3d9 264
715ab376 265 if (bounce_return_body && message_file != NULL)
059ec3d9 266 {
715ab376
PH
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)
059ec3d9 272 {
715ab376
PH
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 }
059ec3d9
PH
283 }
284 }
285 }
286
287/* Close the file, which should send an EOF to the child process
288that is receiving the message. Wait for it to finish, without a timeout. */
289
f1e894f3 290(void)fclose(f);
059ec3d9
PH
291status = child_close(pid, 0); /* Waits for child to close */
292if (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
303return 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
313message. Delivery failures are handled separately in deliver.c.
314
315If there is a valid sender_address, and the failing message is not a local
316error message, then this function calls moan_send_message to send a message to
317that person. If the sender's address is null, then an error has occurred with a
318message that was generated by a mailer daemon. All we can do is to write
319information to log files. The same action is taken if local_error_message is
320set - this can happen for non null-senders in certain configurations where exim
321doesn't run setuid root.
322
323Arguments:
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
331Returns: FALSE if there is no sender_address to send to;
332 else the return from moan_send_message()
333*/
334
335BOOL
336moan_to_sender(int ident, error_block *eblock, header_line *headers,
337 FILE *message_file, BOOL check_sender)
338{
339uschar *firstline = NULL;
340uschar *msg = US"Error while reading message with no usable sender address";
341
342if (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
347if (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
359if (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
365switch(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
417return 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
427mailmaster) about some incident.
428
429Arguments:
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
436Returns: nothing
437*/
438
439void
1ba28e2b
PP
440moan_tell_someone(uschar *who, address_item *addr,
441 const uschar *subject, const char *format, ...)
059ec3d9
PH
442{
443FILE *f;
444va_list ap;
445int fd;
446int pid = child_open_exim(&fd);
447
448if (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
455f = fdopen(fd, "wb");
456682f5 456fprintf(f, "Auto-Submitted: auto-replied\n");
0e22dfd1 457moan_write_from(f);
059ec3d9
PH
458fprintf(f, "To: %s\n", who);
459fprintf(f, "Subject: %s\n\n", subject);
460va_start(ap, format);
461vfprintf(f, format, ap);
462va_end(ap);
463
464if (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
f1e894f3 478(void)fclose(f);
059ec3d9
PH
479child_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.
489Information is written to stdout and/or stderr, and Exim exits with a non-zero
490completion code. BSMTP is almost always called by some other program, so it is
491up to that program to interpret the return code and do something with the error
492information, and also to preserve the batch input file for human analysis.
493
494Formerly, Exim used to attempt to continue after some errors, but this strategy
495has been abandoned as it can lead to loss of messages.
496
497Arguments:
498 cmd_buffer the command causing the error, or NULL
499 format a printf() format
500 ... arguments for the format
501
502Returns: 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
507void
1ba28e2b 508moan_smtp_batch(uschar *cmd_buffer, const char *format, ...)
059ec3d9
PH
509{
510va_list ap;
511int yield = (receive_messagecount > 0)? 1 : 2;
512
513DEBUG(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
517va_start(ap, format);
518vfprintf(stdout, format, ap);
519va_end(ap);
520
521fprintf(stdout, "\nTransaction started in line %d\n",
522 bsmtp_transaction_linecount);
523fprintf(stdout, "Error detected in line %d\n", receive_linecount);
524if (cmd_buffer != NULL) fprintf(stdout, "%s\n", cmd_buffer);
525
526/* On stderr, write stuff for human consumption */
527
528fprintf(stderr,
529 "An error was detected while processing a file of BSMTP input.\n"
530 "The error message was:\n\n ");
531
532va_start(ap, format);
533vfprintf(stderr, format, ap);
534va_end(ap);
535
536fprintf(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
541if (cmd_buffer != NULL)
542 {
543 fprintf(stderr, "The SMTP command at fault was:\n\n %s\n\n",
544 cmd_buffer);
545 }
546
547fprintf(stderr, "%d previous message%s successfully processed.\n",
548 receive_messagecount, (receive_messagecount == 1)? " was" : "s were");
549
550fprintf(stderr, "The rest of the batch was abandoned.\n");
551
552exim_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
563the error_copies string to see whether there is an additional recipient list to
564which errors for this recipient must be bcc'd. The incoming recipient is always
565fully qualified.
566
567Argument: recipient address
568Returns: additional recipient list or NULL
569*/
570
571uschar *
572moan_check_errorcopy(uschar *recipient)
573{
574uschar *item, *localpart, *domain;
575uschar *listptr = errors_copy;
576uschar *yield = NULL;
577uschar buffer[256];
578int sep = 0;
579int llen;
580
581if (errors_copy == NULL) return NULL;
582
583/* Set up pointer to the local part and domain, and compute the
584length of the local part. */
585
586localpart = recipient;
bc64a74d 587domain = Ustrrchr(recipient, '@');
059ec3d9
PH
588if (domain == NULL) return NULL; /* should not occur, but avoid crash */
589llen = domain++ - recipient;
590
591/* Scan through the configured items */
592
593while ((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 {
ce9f225c 613 deliver_localpart = string_copyn(localpart, llen);
059ec3d9
PH
614 deliver_domain = domain;
615 yield = expand_string_copy(newaddress);
616 deliver_domain = deliver_localpart = NULL;
617 if (yield == NULL)
618 log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand %s when processing "
619 "errors_copy: %s", newaddress, expand_string_message);
620 break;
621 }
622 }
623
624DEBUG(D_any) debug_printf("errors_copy check returned %s\n",
625 (yield == NULL)? US"NULL" : yield);
626
627expand_nmax = -1;
628return yield;
629}
630
631
632
633/************************************************
634* Handle skipped syntax errors *
635************************************************/
636
637/* This function is called by the redirect router when it has skipped over one
638or more syntax errors in the list of addresses. If there is an address to mail
639to, send a message, and always write the information to the log. In the case of
640a filter file, a "syntax error" might actually be something else, such as the
641inability to open a log file. Thus, the wording of the error message is
642general.
643
644Arguments:
645 rname the router name
646 eblock chain of error blocks
647 syntax_errors_to address to send mail to, or NULL
648 some TRUE if some addresses were generated; FALSE if none were
649 custom custom message text
650
651Returns: FALSE if string expansion failed; TRUE otherwise
652*/
653
654BOOL
655moan_skipped_syntax_errors(uschar *rname, error_block *eblock,
656 uschar *syntax_errors_to, BOOL some, uschar *custom)
657{
658int pid, fd;
659uschar *s, *t;
660FILE *f;
661error_block *e;
662
663for (e = eblock; e != NULL; e = e->next)
664 {
665 if (e->text2 != NULL)
666 log_write(0, LOG_MAIN, "%s router: skipped error: %s in \"%s\"",
667 rname, e->text1, e->text2);
668 else
669 log_write(0, LOG_MAIN, "%s router: skipped error: %s", rname,
670 e->text1);
671 }
672
673if (syntax_errors_to == NULL) return TRUE;
674
675s = expand_string(syntax_errors_to);
676if (s == NULL)
677 {
678 log_write(0, LOG_MAIN, "%s router failed to expand %s: %s", rname,
679 syntax_errors_to, expand_string_message);
680 return FALSE;
681 }
682
683/* If we can't create a process to send the message, just forget about
684it. */
685
686pid = child_open_exim(&fd);
687
688if (pid < 0)
689 {
690 DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
691 strerror(errno));
692 return TRUE;
693 }
694
695f = fdopen(fd, "wb");
456682f5 696fprintf(f, "Auto-Submitted: auto-replied\n");
0e22dfd1 697moan_write_from(f);
059ec3d9
PH
698fprintf(f, "To: %s\n", s);
699fprintf(f, "Subject: error(s) in forwarding or filtering\n\n");
700
701if (custom != NULL)
702 {
703 t = expand_string(custom);
704 if (t == NULL)
705 {
706 log_write(0, LOG_MAIN, "%s router failed to expand %s: %s", rname,
707 custom, expand_string_message);
708 return FALSE;
709 }
710 fprintf(f, "%s\n\n", t);
711 }
712
713fprintf(f, "The %s router encountered the following error(s):\n\n",
714 rname);
715
716for (e = eblock; e != NULL; e = e->next)
717 {
718 fprintf(f, " %s", e->text1);
719 if (e->text2 != NULL)
720 fprintf(f, " in the address\n \"%s\"", e->text2);
721 fprintf(f, "\n\n");
722 }
723
724if (some)
725 fprintf(f, "Other addresses were processed normally.\n");
726else
727 fprintf(f, "No valid addresses were generated.\n");
728
f1e894f3 729(void)fclose(f);
059ec3d9
PH
730child_close(pid, 0); /* Waits for child to close; no timeout */
731
732return TRUE;
733}
734
735/* End of moan.c */