X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f3ebb786e451da973560f1c9d8cdb151d25108b5..1d28cc061677bd07d9bed48dd84bd5c590247043:/src/src/moan.c diff --git a/src/src/moan.c b/src/src/moan.c index fea3683ba..ebfd440f6 100644 --- a/src/src/moan.c +++ b/src/src/moan.c @@ -2,8 +2,10 @@ * Exim - an Internet mail transport agent * *************************************************/ +/* Copyright (c) The Exim Maintainers 2020 - 2022 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* Functions for sending messages to sender or to mailmaster. */ @@ -28,7 +30,7 @@ Returns: nothing void moan_write_from(FILE *f) { -uschar *s = expand_string(dsn_from); +uschar * s = expand_string(dsn_from); if (!s) { log_write(0, LOG_MAIN|LOG_PANIC, @@ -40,6 +42,81 @@ fprintf(f, "From: %s\n", s); +/************************************************* +* Write References: line for DSN * +*************************************************/ + +/* Generate a References: header if there is in the header_list +at least one of Message-ID:, References:, or In-Reply-To: (see RFC 2822). + +Arguments: f the FILE to write to + message_id optional already-found message-id, or NULL + +Returns: nothing +*/ + +void +moan_write_references(FILE * fp, uschar * message_id) +{ +header_line * h; + +if (!message_id) + for (h = header_list; h; h = h->next) + if (h->type == htype_id) + { + message_id = Ustrchr(h->text, ':') + 1; + Uskip_whitespace(&message_id); + } + +for (h = header_list; h; h = h->next) + if (h->type != htype_old && strncmpic(US"References:", h->text, 11) == 0) + break; + +if (!h) + for (h = header_list; h; h = h->next) + if (h->type != htype_old && strncmpic(US"In-Reply-To:", h->text, 12) == 0) + break; + +/* We limit the total length of references. Although there is no fixed +limit, some systems do not like headers growing beyond recognition. +Keep the first message ID for the thread root and the last few for +the position inside the thread, up to a maximum of 12 altogether. */ + +if (h || message_id) + { + fprintf(fp, "References:"); + if (h) + { + const uschar * s; + uschar * id, * error; + uschar * referenced_ids[12]; + int reference_count = 0; + + s = Ustrchr(h->text, ':') + 1; + f.parse_allow_group = FALSE; + while (*s && (s = parse_message_id(s, &id, &error))) + if (reference_count == nelem(referenced_ids)) + { + memmove(referenced_ids + 1, referenced_ids + 2, + sizeof(referenced_ids) - 2*sizeof(uschar *)); + referenced_ids[reference_count - 1] = id; + } + else + referenced_ids[reference_count++] = id; + + for (int i = 0; i < reference_count; ++i) + fprintf(fp, " %s", referenced_ids[i]); + } + + /* The message id will have a newline on the end of it. */ + + if (message_id) fprintf(fp, " %s", message_id); + else fprintf(fp, "\n"); + } +} + + + /************************************************* * Send error message * *************************************************/ @@ -73,7 +150,7 @@ int size_limit = bounce_return_size_limit; FILE * fp; int pid; -#ifdef EXPERIMENTAL_DMARC +#ifdef SUPPORT_DMARC uschar * s, * s2; /* For DMARC if there is a specific sender set, expand the variable for the @@ -86,15 +163,16 @@ if ( ident == ERRMESS_DMARC_FORENSIC && (s2 = expand_string(string_sprintf("${address:%s}", s))) && *s2 ) - pid = child_open_exim2(&fd, s2, bounce_sender_authentication); + pid = child_open_exim2(&fd, s2, bounce_sender_authentication, + US"moan_send_message"); else { s = NULL; - pid = child_open_exim(&fd); + pid = child_open_exim(&fd, US"moan_send_message"); } #else -pid = child_open_exim(&fd); +pid = child_open_exim(&fd, US"moan_send_message"); #endif if (pid < 0) @@ -111,7 +189,7 @@ fp = fdopen(fd, "wb"); if (errors_reply_to) fprintf(fp, "Reply-To: %s\n", errors_reply_to); fprintf(fp, "Auto-Submitted: auto-replied\n"); -#ifdef EXPERIMENTAL_DMARC +#ifdef SUPPORT_DMARC if (s) fprintf(fp, "From: %s\n", s); else @@ -119,6 +197,7 @@ else moan_write_from(fp); fprintf(fp, "To: %s\n", recipient); +moan_write_references(fp, NULL); switch(ident) { @@ -145,7 +224,7 @@ switch(ident) "A message that you sent contained one or more recipient addresses that were\n" "incorrectly constructed:\n\n"); - while (eblock != NULL) + while (eblock) { fprintf(fp, " %s: %s\n", eblock->text1, eblock->text2); count++; @@ -228,7 +307,7 @@ switch(ident) fprintf(fp, "\n"); break; -#ifdef EXPERIMENTAL_DMARC +#ifdef SUPPORT_DMARC case ERRMESS_DMARC_FORENSIC: bounce_return_message = TRUE; bounce_return_body = FALSE; @@ -308,7 +387,7 @@ if (bounce_return_message) if (bounce_return_body && message_file) { BOOL enddot = f.dot_ends && message_file == stdin; - uschar * buf = store_get(bounce_return_linesize_limit+2, TRUE); + uschar * buf = store_get(bounce_return_linesize_limit+2, GET_TAINTED); if (firstline) fprintf(fp, "%s", CS firstline); @@ -339,7 +418,7 @@ if (bounce_return_message) fputs(CS buf, fp); } } -#ifdef EXPERIMENTAL_DMARC +#ifdef SUPPORT_DMARC /* Overkill, but use exact test in case future code gets inserted */ else if (bounce_return_body && message_file == NULL) { @@ -509,7 +588,7 @@ moan_tell_someone(uschar *who, address_item *addr, FILE *f; va_list ap; int fd; -int pid = child_open_exim(&fd); +int pid = child_open_exim(&fd, US"moan_tell_someone"); if (pid < 0) { @@ -522,6 +601,7 @@ f = fdopen(fd, "wb"); fprintf(f, "Auto-Submitted: auto-replied\n"); moan_write_from(f); fprintf(f, "To: %s\n", who); +moan_write_references(f, NULL); fprintf(f, "Subject: %s\n\n", subject); va_start(ap, format); vfprintf(f, format, ap); @@ -615,7 +695,7 @@ fprintf(stderr, "%d previous message%s successfully processed.\n", fprintf(stderr, "The rest of the batch was abandoned.\n"); -exim_exit(yield, US"batch"); +exim_exit(yield); } @@ -640,7 +720,6 @@ moan_check_errorcopy(uschar *recipient) uschar *item, *localpart, *domain; const uschar *listptr = errors_copy; uschar *yield = NULL; -uschar buffer[256]; int sep = 0; int llen; @@ -656,8 +735,7 @@ llen = domain++ - recipient; /* Scan through the configured items */ -while ((item = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))) - != NULL) +while ((item = string_nextinlist(&listptr, &sep, NULL, 0))) { const uschar *newaddress = item; const uschar *pattern = string_dequote(&newaddress); @@ -745,7 +823,7 @@ if (!(s = expand_string(syntax_errors_to))) /* If we can't create a process to send the message, just forget about it. */ -pid = child_open_exim(&fd); +pid = child_open_exim(&fd, US"moan_skipped_syntax_errors"); if (pid < 0) { @@ -759,6 +837,7 @@ fprintf(f, "Auto-Submitted: auto-replied\n"); moan_write_from(f); fprintf(f, "To: %s\n", s); fprintf(f, "Subject: error(s) in forwarding or filtering\n\n"); +moan_write_references(f, NULL); if (custom) {