1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 */
7 /* See the file NOTICE for conditions of use and distribution. */
9 /* Functions for sending messages to sender or to mailmaster. */
16 /*************************************************
17 * Write From: line for DSN *
18 *************************************************/
20 /* This function is called to write the From: line in automatically generated
21 messages - bounces, warnings, etc. It expands a configuration item in order to
22 get the text. If the expansion fails, a panic is logged and the default value
23 for the option is used.
25 Argument: the FILE to write to
30 moan_write_from(FILE *f)
32 uschar * s = expand_string(dsn_from);
35 log_write(0, LOG_MAIN|LOG_PANIC,
36 "Failed to expand dsn_from (using default): %s", expand_string_message);
37 s = expand_string(US DEFAULT_DSN_FROM);
39 fprintf(f, "From: %s\n", s);
44 /*************************************************
45 * Write References: line for DSN *
46 *************************************************/
48 /* Generate a References: header if there is in the header_list
49 at least one of Message-ID:, References:, or In-Reply-To: (see RFC 2822).
51 Arguments: f the FILE to write to
52 message_id optional already-found message-id, or NULL
58 moan_write_references(FILE * fp, uschar * message_id)
63 for (h = header_list; h; h = h->next)
64 if (h->type == htype_id)
66 message_id = Ustrchr(h->text, ':') + 1;
67 Uskip_whitespace(&message_id);
70 for (h = header_list; h; h = h->next)
71 if (h->type != htype_old && strncmpic(US"References:", h->text, 11) == 0)
75 for (h = header_list; h; h = h->next)
76 if (h->type != htype_old && strncmpic(US"In-Reply-To:", h->text, 12) == 0)
79 /* We limit the total length of references. Although there is no fixed
80 limit, some systems do not like headers growing beyond recognition.
81 Keep the first message ID for the thread root and the last few for
82 the position inside the thread, up to a maximum of 12 altogether. */
86 fprintf(fp, "References:");
91 uschar * referenced_ids[12];
92 int reference_count = 0;
94 s = Ustrchr(h->text, ':') + 1;
95 f.parse_allow_group = FALSE;
96 while (*s && (s = parse_message_id(s, &id, &error)))
97 if (reference_count == nelem(referenced_ids))
99 memmove(referenced_ids + 1, referenced_ids + 2,
100 sizeof(referenced_ids) - 2*sizeof(uschar *));
101 referenced_ids[reference_count - 1] = id;
104 referenced_ids[reference_count++] = id;
106 for (int i = 0; i < reference_count; ++i)
107 fprintf(fp, " %s", referenced_ids[i]);
110 /* The message id will have a newline on the end of it. */
112 if (message_id) fprintf(fp, " %s", message_id);
113 else fprintf(fp, "\n");
119 /*************************************************
120 * Send error message *
121 *************************************************/
123 /* This function sends an error message by opening a pipe to a new process
124 running Exim, and writing a message to it using the "-t" option. This is not
125 used for delivery failures, which have their own code for handing failed
129 recipient addressee for the message
130 ident identifies the type of error
131 eblock chain of error_blocks containing data about the error
132 headers the message's headers
133 message_file FILE containing the body of the message
134 firstline contains first line of file, if it was read to check for
135 "From ", but it turned out not to be
137 Returns: TRUE if message successfully sent
141 moan_send_message(uschar *recipient, int ident, error_block *eblock,
142 header_line *headers, FILE *message_file, uschar *firstline)
148 int size_limit = bounce_return_size_limit;
155 /* For DMARC if there is a specific sender set, expand the variable for the
156 header From: and grab the address from that for the envelope FROM. */
158 if ( ident == ERRMESS_DMARC_FORENSIC
159 && dmarc_forensic_sender
160 && (s = expand_string(dmarc_forensic_sender))
162 && (s2 = expand_string(string_sprintf("${address:%s}", s)))
165 pid = child_open_exim2(&fd, s2, bounce_sender_authentication,
166 US"moan_send_message");
170 pid = child_open_exim(&fd, US"moan_send_message");
174 pid = child_open_exim(&fd, US"moan_send_message");
179 DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
183 else DEBUG(D_any) debug_printf("Child process %d for sending message\n", pid);
185 /* Creation of child succeeded */
187 fp = fdopen(fd, "wb");
188 if (errors_reply_to) fprintf(fp, "Reply-To: %s\n", errors_reply_to);
189 fprintf(fp, "Auto-Submitted: auto-replied\n");
193 fprintf(fp, "From: %s\n", s);
198 fprintf(fp, "To: %s\n", recipient);
199 moan_write_references(fp, NULL);
203 case ERRMESS_BADARGADDRESS:
205 "Subject: Mail failure - malformed recipient address\n\n");
207 "A message that you sent contained a recipient address that was incorrectly\n"
209 fprintf(fp, " %s %s\n", eblock->text1, eblock->text2);
210 count = Ustrlen(eblock->text1);
211 if (count > 0 && eblock->text1[count-1] == '.')
213 "\nRecipient addresses must not end with a '.' character.\n");
215 "\nThe message has not been delivered to any recipients.\n");
218 case ERRMESS_BADNOADDRESS:
219 case ERRMESS_BADADDRESS:
221 "Subject: Mail failure - malformed recipient address\n\n");
223 "A message that you sent contained one or more recipient addresses that were\n"
224 "incorrectly constructed:\n\n");
228 fprintf(fp, " %s: %s\n", eblock->text1, eblock->text2);
230 eblock = eblock->next;
233 fprintf(fp, (count == 1)? "\nThis address has been ignored. " :
234 "\nThese addresses have been ignored. ");
236 fprintf(fp, (ident == ERRMESS_BADADDRESS)?
237 "The other addresses in the message were\n"
238 "syntactically valid and have been passed on for an attempt at delivery.\n" :
240 "There were no other addresses in your\n"
241 "message, and so no attempt at delivery was possible.\n");
244 case ERRMESS_IGADDRESS:
245 fprintf(fp, "Subject: Mail failure - no recipient addresses\n\n");
247 "A message that you sent using the -t command line option contained no\n"
248 "addresses that were not also on the command line, and were therefore\n"
249 "suppressed. This left no recipient addresses, and so no delivery could\n"
253 case ERRMESS_NOADDRESS:
254 fprintf(fp, "Subject: Mail failure - no recipient addresses\n\n");
256 "A message that you sent contained no recipient addresses, and therefore no\n"
257 "delivery could be attempted.\n");
261 fprintf(fp, "Subject: Mail failure - system failure\n\n");
263 "A system failure was encountered while processing a message that you sent,\n"
264 "so it has not been possible to deliver it. The error was:\n\n%s\n",
268 case ERRMESS_VLONGHEADER:
269 fprintf(fp, "Subject: Mail failure - overlong header section\n\n");
271 "A message that you sent contained a header section that was excessively\n"
272 "long and could not be handled by the mail transmission software. The\n"
273 "message has not been delivered to any recipients.\n");
276 case ERRMESS_VLONGHDRLINE:
277 fprintf(fp, "Subject: Mail failure - overlong header line\n\n");
279 "A message that you sent contained a header line that was excessively\n"
280 "long and could not be handled by the mail transmission software. The\n"
281 "message has not been delivered to any recipients.\n");
285 fprintf(fp, "Subject: Mail failure - message too big\n\n");
287 "A message that you sent was longer than the maximum size allowed on this\n"
288 "system. It was not delivered to any recipients.\n");
291 case ERRMESS_TOOMANYRECIP:
292 fprintf(fp, "Subject: Mail failure - too many recipients\n\n");
294 "A message that you sent contained more recipients than allowed on this\n"
295 "system. It was not delivered to any recipients.\n");
298 case ERRMESS_LOCAL_SCAN:
299 case ERRMESS_LOCAL_ACL:
300 fprintf(fp, "Subject: Mail failure - rejected by local scanning code\n\n");
302 "A message that you sent was rejected by the local scanning code that\n"
303 "checks incoming messages on this system.");
305 fprintf(fp, " The following error was given:\n\n %s", eblock->text1);
310 case ERRMESS_DMARC_FORENSIC:
311 bounce_return_message = TRUE;
312 bounce_return_body = FALSE;
313 fprintf(fp, "Subject: DMARC Forensic Report for %s from IP %s\n\n",
314 eblock ? eblock->text2 : US"Unknown",
315 sender_host_address);
317 "A message claiming to be from you has failed the published DMARC\n"
318 "policy for your domain.\n\n");
321 fprintf(fp, " %s: %s\n", eblock->text1, eblock->text2);
323 eblock = eblock->next;
329 fprintf(fp, "Subject: Mail failure\n\n");
331 "A message that you sent has caused the error routine to be entered with\n"
332 "an unknown error number (%d).\n", ident);
336 /* Now, if configured, copy the message; first the headers and then the rest of
337 the input if available, up to the configured limit, if the option for including
338 message bodies in bounces is set. */
340 if (bounce_return_message)
342 if (bounce_return_body)
345 "------ This is a copy of your message, including all the headers.");
346 if (size_limit == 0 || size_limit > thismessage_size_limit)
347 size_limit = thismessage_size_limit;
348 if (size_limit > 0 && size_limit < message_size)
358 "------ No more than %d%s characters of the body are included.\n\n",
361 else fprintf(fp, " ------\n\n");
366 "------ This is a copy of the headers that were received before the "
367 "error\n was detected.\n\n");
370 /* If the error occurred before the Received: header was created, its text
371 field will still be NULL; just omit such a header line. */
375 if (headers->text != NULL) fprintf(fp, "%s", CS headers->text);
376 headers = headers->next;
379 if (ident != ERRMESS_VLONGHEADER && ident != ERRMESS_VLONGHDRLINE)
382 /* After early detection of an error, the message file may be STDIN,
383 in which case we might have to terminate on a line containing just "."
384 as well as on EOF. We may already have the first line in memory. */
386 if (bounce_return_body && message_file)
388 BOOL enddot = f.dot_ends && message_file == stdin;
389 uschar * buf = store_get(bounce_return_linesize_limit+2, TRUE);
391 if (firstline) fprintf(fp, "%s", CS firstline);
393 while (fgets(CS buf, bounce_return_linesize_limit+2, message_file))
397 if (enddot && *buf == '.' && buf[1] == '\n')
404 if (buf[len-1] != '\n')
405 { /* eat rest of partial line */
407 while ((ch = fgetc(message_file)) != EOF && ch != '\n') ;
410 if (size_limit > 0 && len > size_limit - written)
412 buf[size_limit - written] = '\0';
421 /* Overkill, but use exact test in case future code gets inserted */
422 else if (bounce_return_body && message_file == NULL)
424 /*XXX limit line length here? */
425 /* This doesn't print newlines, disable until can parse and fix
426 * output to be legible. */
427 fprintf(fp, "%s", expand_string(US"$message_body"));
431 /* Close the file, which should send an EOF to the child process
432 that is receiving the message. Wait for it to finish, without a timeout. */
435 status = child_close(pid, 0); /* Waits for child to close */
438 uschar *msg = US"Child mail process returned status";
440 log_write(0, LOG_MAIN, "%s %d: errno=%d: %s", msg, status, errno,
443 log_write(0, LOG_MAIN, "%s %d", msg, status);
452 /*************************************************
453 * Send message to sender *
454 *************************************************/
456 /* This function is called when errors are detected during the receipt of a
457 message. Delivery failures are handled separately in deliver.c.
459 If there is a valid sender_address, and the failing message is not a local
460 error message, then this function calls moan_send_message to send a message to
461 that person. If the sender's address is null, then an error has occurred with a
462 message that was generated by a mailer daemon. All we can do is to write
463 information to log files. The same action is taken if local_error_message is
464 set - this can happen for non null-senders in certain configurations where exim
465 doesn't run setuid root.
468 ident identifies the particular error
469 eblock chain of error_blocks containing data about the error
470 headers message's headers (chain)
471 message_file a FILE where the body of the message can be read
472 check_sender if TRUE, read the first line of the file for a possible
473 "From " sender (if a trusted caller)
475 Returns: FALSE if there is no sender_address to send to;
476 else the return from moan_send_message()
480 moan_to_sender(int ident, error_block *eblock, header_line *headers,
481 FILE *message_file, BOOL check_sender)
483 uschar *firstline = NULL;
484 uschar *msg = US"Error while reading message with no usable sender address";
486 if (message_reference)
487 msg = string_sprintf("%s (R=%s)", msg, message_reference);
489 /* Find the sender from a From line if permitted and possible */
491 if (check_sender && message_file && f.trusted_caller &&
492 Ufgets(big_buffer, BIG_BUFFER_SIZE, message_file) != NULL)
494 uschar *new_sender = NULL;
495 if (regex_match_and_setup(regex_From, big_buffer, 0, -1))
496 new_sender = expand_string(uucp_from_sender);
497 if (new_sender) sender_address = new_sender;
498 else firstline = big_buffer;
501 /* If viable sender address, send a message */
503 if (sender_address && sender_address[0] && !f.local_error_message)
504 return moan_send_message(sender_address, ident, eblock, headers,
505 message_file, firstline);
507 /* Otherwise, we can only log */
511 case ERRMESS_BADARGADDRESS:
512 case ERRMESS_BADNOADDRESS:
513 case ERRMESS_BADADDRESS:
514 log_write(0, LOG_MAIN, "%s: at least one malformed recipient address: "
515 "%s - %s", msg, eblock->text1, eblock->text2);
518 case ERRMESS_IGADDRESS:
519 case ERRMESS_NOADDRESS:
520 log_write(0, LOG_MAIN, "%s: no recipient addresses", msg);
523 /* This error has already been logged. */
527 case ERRMESS_VLONGHEADER:
528 log_write(0, LOG_MAIN, "%s: excessively long message header section read "
529 "(more than %d characters)", msg, header_maxsize);
532 case ERRMESS_VLONGHDRLINE:
533 log_write(0, LOG_MAIN, "%s: excessively long message header line read "
534 "(more than %d characters)", msg, header_line_maxsize);
538 log_write(0, LOG_MAIN, "%s: message too big (limit set to %d)", msg,
539 thismessage_size_limit);
542 case ERRMESS_TOOMANYRECIP:
543 log_write(0, LOG_MAIN, "%s: too many recipients (max set to %d)", msg,
547 case ERRMESS_LOCAL_SCAN:
548 log_write(0, LOG_MAIN, "%s: rejected by local_scan: %s", msg, eblock->text1);
551 case ERRMESS_LOCAL_ACL:
552 log_write(0, LOG_MAIN, "%s: rejected by non-SMTP ACL: %s", msg, eblock->text1);
556 log_write(0, LOG_MAIN|LOG_PANIC, "%s: unknown error number %d", msg,
566 /*************************************************
567 * Send message to someone *
568 *************************************************/
570 /* This is called when exim is configured to tell someone (often the
571 mailmaster) about some incident.
574 who address to send mail to
575 addr chain of deferred addresses whose details are to be included
576 subject subject text for the message
577 format a printf() format for the body of the message
578 ... arguments for the format
584 moan_tell_someone(uschar *who, address_item *addr,
585 const uschar *subject, const char *format, ...)
590 int pid = child_open_exim(&fd, US"moan_tell_someone");
594 DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
599 f = fdopen(fd, "wb");
600 fprintf(f, "Auto-Submitted: auto-replied\n");
602 fprintf(f, "To: %s\n", who);
603 moan_write_references(f, NULL);
604 fprintf(f, "Subject: %s\n\n", subject);
605 va_start(ap, format);
606 vfprintf(f, format, ap);
611 fprintf(f, "\nThe following address(es) have yet to be delivered:\n");
612 for (; addr; addr = addr->next)
614 uschar * parent = addr->parent ? addr->parent->address : NULL;
615 fprintf(f, " %s", addr->address);
616 if (parent) fprintf(f, " <%s>", parent);
617 if (addr->basic_errno > 0) fprintf(f, ": %s", strerror(addr->basic_errno));
618 if (addr->message) fprintf(f, ": %s", addr->message);
624 child_close(pid, 0); /* Waits for child to close; no timeout */
629 /*************************************************
630 * Handle SMTP batch error *
631 *************************************************/
633 /* This is called when something goes wrong in batched (-bS) SMTP input.
634 Information is written to stdout and/or stderr, and Exim exits with a non-zero
635 completion code. BSMTP is almost always called by some other program, so it is
636 up to that program to interpret the return code and do something with the error
637 information, and also to preserve the batch input file for human analysis.
639 Formerly, Exim used to attempt to continue after some errors, but this strategy
640 has been abandoned as it can lead to loss of messages.
643 cmd_buffer the command causing the error, or NULL
644 format a printf() format
645 ... arguments for the format
647 Returns: does not return; exits from the program
648 exit code = 1 if some messages were accepted
649 exit code = 2 if no messages were accepted
653 moan_smtp_batch(uschar *cmd_buffer, const char *format, ...)
656 int yield = (receive_messagecount > 0)? 1 : 2;
658 DEBUG(D_any) debug_printf("Handling error in batched SMTP input\n");
660 /* On stdout, write stuff that a program could parse fairly easily. */
662 va_start(ap, format);
663 vfprintf(stdout, format, ap);
666 fprintf(stdout, "\nTransaction started in line %d\n",
667 bsmtp_transaction_linecount);
668 fprintf(stdout, "Error detected in line %d\n", receive_linecount);
669 if (cmd_buffer != NULL) fprintf(stdout, "%s\n", cmd_buffer);
671 /* On stderr, write stuff for human consumption */
674 "An error was detected while processing a file of BSMTP input.\n"
675 "The error message was:\n\n ");
677 va_start(ap, format);
678 vfprintf(stderr, format, ap);
682 "\n\nThe SMTP transaction started in line %d.\n"
683 "The error was detected in line %d.\n",
684 bsmtp_transaction_linecount, receive_linecount);
686 if (cmd_buffer != NULL)
688 fprintf(stderr, "The SMTP command at fault was:\n\n %s\n\n",
692 fprintf(stderr, "%d previous message%s successfully processed.\n",
693 receive_messagecount, (receive_messagecount == 1)? " was" : "s were");
695 fprintf(stderr, "The rest of the batch was abandoned.\n");
703 /*************************************************
704 * Check for error copies *
705 *************************************************/
707 /* This function is passed the recipient of an error message, and must check
708 the error_copies string to see whether there is an additional recipient list to
709 which errors for this recipient must be bcc'd. The incoming recipient is always
712 Argument: recipient address
713 Returns: additional recipient list or NULL
717 moan_check_errorcopy(uschar *recipient)
719 uschar *item, *localpart, *domain;
720 const uschar *listptr = errors_copy;
721 uschar *yield = NULL;
725 if (errors_copy == NULL) return NULL;
727 /* Set up pointer to the local part and domain, and compute the
728 length of the local part. */
730 localpart = recipient;
731 domain = Ustrrchr(recipient, '@');
732 if (domain == NULL) return NULL; /* should not occur, but avoid crash */
733 llen = domain++ - recipient;
735 /* Scan through the configured items */
737 while ((item = string_nextinlist(&listptr, &sep, NULL, 0)))
739 const uschar *newaddress = item;
740 const uschar *pattern = string_dequote(&newaddress);
742 /* If no new address found, just skip this item. */
744 while (isspace(*newaddress)) newaddress++;
745 if (*newaddress == 0) continue;
747 /* We now have an item to match as an address in item, and the additional
748 address in newaddress. If the pattern matches, expand the new address string
749 and return it. During expansion, make local part and domain available for
750 insertion. This requires a copy to be made; we can't just temporarily
751 terminate it, as the whole address is required for $0. */
753 if (match_address_list(recipient, TRUE, TRUE, &pattern, NULL, 0, UCHAR_MAX+1,
756 deliver_localpart = string_copyn(localpart, llen);
757 deliver_domain = domain;
758 yield = expand_string_copy(newaddress);
759 deliver_domain = deliver_localpart = NULL;
761 log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand %s when processing "
762 "errors_copy: %s", newaddress, expand_string_message);
767 DEBUG(D_any) debug_printf("errors_copy check returned %s\n",
768 (yield == NULL)? US"NULL" : yield);
776 /************************************************
777 * Handle skipped syntax errors *
778 ************************************************/
780 /* This function is called by the redirect router when it has skipped over one
781 or more syntax errors in the list of addresses. If there is an address to mail
782 to, send a message, and always write the information to the log. In the case of
783 a filter file, a "syntax error" might actually be something else, such as the
784 inability to open a log file. Thus, the wording of the error message is
788 rname the router name
789 eblock chain of error blocks
790 syntax_errors_to address to send mail to, or NULL
791 some TRUE if some addresses were generated; FALSE if none were
792 custom custom message text
794 Returns: FALSE if string expansion failed; TRUE otherwise
798 moan_skipped_syntax_errors(uschar *rname, error_block *eblock,
799 uschar *syntax_errors_to, BOOL some, uschar *custom)
805 for (error_block * e = eblock; e; e = e->next)
806 if (e->text2 != NULL)
807 log_write(0, LOG_MAIN, "%s router: skipped error: %s in \"%s\"",
808 rname, e->text1, e->text2);
810 log_write(0, LOG_MAIN, "%s router: skipped error: %s", rname,
813 if (!syntax_errors_to) return TRUE;
815 if (!(s = expand_string(syntax_errors_to)))
817 log_write(0, LOG_MAIN, "%s router failed to expand %s: %s", rname,
818 syntax_errors_to, expand_string_message);
822 /* If we can't create a process to send the message, just forget about
825 pid = child_open_exim(&fd, US"moan_skipped_syntax_errors");
829 DEBUG(D_any) debug_printf("Failed to create child to send message: %s\n",
834 f = fdopen(fd, "wb");
835 fprintf(f, "Auto-Submitted: auto-replied\n");
837 fprintf(f, "To: %s\n", s);
838 fprintf(f, "Subject: error(s) in forwarding or filtering\n\n");
839 moan_write_references(f, NULL);
843 if (!(t = expand_string(custom)))
845 log_write(0, LOG_MAIN, "%s router failed to expand %s: %s", rname,
846 custom, expand_string_message);
849 fprintf(f, "%s\n\n", t);
852 fprintf(f, "The %s router encountered the following error(s):\n\n",
855 for (error_block * e = eblock; e; e = e->next)
857 fprintf(f, " %s", e->text1);
858 if (e->text2 != NULL)
859 fprintf(f, " in the address\n \"%s\"", e->text2);
864 fprintf(f, "Other addresses were processed normally.\n");
866 fprintf(f, "No valid addresses were generated.\n");
869 child_close(pid, 0); /* Waits for child to close; no timeout */