X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fdeliver.c;h=b5aa9b9a75d1a211622ca73b0a3b75dc6ad3f9f3;hb=dadff1d47e54962b0fdf98e8ce5cef42b6cb7fb5;hp=cc43c921a27d8786dbda533e25b105e4e5b547d0;hpb=7ade712cc84d7f822f04baf2f46daee81701174d;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/deliver.c b/src/src/deliver.c index cc43c921a..b5aa9b9a7 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -2,13 +2,14 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2014 */ +/* Copyright (c) University of Cambridge 1995 - 2015 */ /* See the file NOTICE for conditions of use and distribution. */ /* The main code for delivering a message. */ #include "exim.h" +#include /* Data block for keeping track of subprocesses for parallel remote @@ -149,9 +150,9 @@ else } deliver_recipients = addr; -deliver_address_data = addr->p.address_data; -deliver_domain_data = addr->p.domain_data; -deliver_localpart_data = addr->p.localpart_data; +deliver_address_data = addr->prop.address_data; +deliver_domain_data = addr->prop.domain_data; +deliver_localpart_data = addr->prop.localpart_data; /* These may be unset for multiple addresses */ @@ -676,40 +677,78 @@ while (addr->parent != NULL) +/************************************************* +* Delivery logging support functions * +*************************************************/ + +/* The LOGGING() checks in d_log_interface() are complicated for backwards +compatibility. When outgoing interface logging was originally added, it was +conditional on just incoming_interface (which is off by default). The +outgoing_interface option is on by default to preserve this behaviour, but +you can enable incoming_interface and disable outgoing_interface to get I= +fields on incoming lines only. + +Arguments: + s The log line buffer + sizep Pointer to the buffer size + ptrp Pointer to current index into buffer + addr The address to be logged + +Returns: New value for s +*/ + +static uschar * +d_log_interface(uschar *s, int *sizep, int *ptrp) +{ +if (LOGGING(incoming_interface) && LOGGING(outgoing_interface) + && sending_ip_address != NULL) + { + s = string_append(s, sizep, ptrp, 2, US" I=[", sending_ip_address); + if (LOGGING(outgoing_port)) + s = string_append(s, sizep, ptrp, 2, US"]:", + string_sprintf("%d", sending_port)); + else + s = string_cat(s, sizep, ptrp, "]", 1); + } +return s; +} + + static uschar * -d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr) +d_hostlog(uschar *s, int *sizep, int *ptrp, address_item *addr) { - s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, - US" [", addr->host_used->address, US"]"); - if ((log_extra_selector & LX_outgoing_port) != 0) - s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", - addr->host_used->port)); - return s; +s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, + US" [", addr->host_used->address, US"]"); +if (LOGGING(outgoing_port)) + s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", + addr->host_used->port)); +return d_log_interface(s, sizep, ptrp); } + + #ifdef SUPPORT_TLS static uschar * d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr) { - if ((log_extra_selector & LX_tls_cipher) != 0 && addr->cipher != NULL) - s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher); - if ((log_extra_selector & LX_tls_certificate_verified) != 0 && - addr->cipher != NULL) - s = string_append(s, sizep, ptrp, 2, US" CV=", - testflag(addr, af_cert_verified) - ? +if (LOGGING(tls_cipher) && addr->cipher != NULL) + s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher); +if (LOGGING(tls_certificate_verified) && addr->cipher != NULL) + s = string_append(s, sizep, ptrp, 2, US" CV=", + testflag(addr, af_cert_verified) + ? #ifdef EXPERIMENTAL_DANE - testflag(addr, af_dane_verified) - ? "dane" - : + testflag(addr, af_dane_verified) + ? "dane" + : #endif - "yes" - : "no"); - if ((log_extra_selector & LX_tls_peerdn) != 0 && addr->peerdn != NULL) - s = string_append(s, sizep, ptrp, 3, US" DN=\"", - string_printing(addr->peerdn), US"\""); - return s; + "yes" + : "no"); +if (LOGGING(tls_peerdn) && addr->peerdn != NULL) + s = string_append(s, sizep, ptrp, 3, US" DN=\"", + string_printing(addr->peerdn), US"\""); +return s; } #endif @@ -808,7 +847,7 @@ pointer to a single host item in their host list, for use by the transport. */ s = reset_point = store_get(size); -log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE); +log_address = string_log_address(addr, LOGGING(all_parents), TRUE); if (msg) s = string_append(s, &size, &ptr, 3, host_and_ident(TRUE), US" ", log_address); else @@ -817,16 +856,19 @@ else s = string_append(s, &size, &ptr, 2, US"> ", log_address); } -if (log_extra_selector & LX_incoming_interface && sending_ip_address) - s = string_append(s, &size, &ptr, 3, US" I=[", sending_ip_address, US"]"); - /* for the port: string_sprintf("%d", sending_port) */ - -if ((log_extra_selector & LX_sender_on_delivery) != 0 || msg) - s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">"); +if (LOGGING(sender_on_delivery) || msg) + s = string_append(s, &size, &ptr, 3, US" F=<", +#ifdef EXPERIMENTAL_INTERNATIONAL + testflag(addr, af_utf8_downcvt) + ? string_address_utf8_to_alabel(sender_address, NULL) + : +#endif + sender_address, + US">"); #ifdef EXPERIMENTAL_SRS -if(addr->p.srs_sender) - s = string_append(s, &size, &ptr, 3, US" SRS=<", addr->p.srs_sender, US">"); +if(addr->prop.srs_sender) + s = string_append(s, &size, &ptr, 3, US" SRS=<", addr->prop.srs_sender, US">"); #endif /* You might think that the return path must always be set for a successful @@ -834,8 +876,7 @@ delivery; indeed, I did for some time, until this statement crashed. The case when it is not set is for a delivery to /dev/null which is optimised by not being run at all. */ -if (used_return_path != NULL && - (log_extra_selector & LX_return_path_on_delivery) != 0) +if (used_return_path != NULL && LOGGING(return_path_on_delivery)) s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">"); if (msg) @@ -847,7 +888,7 @@ if (addr->router != NULL) s = string_append(s, &size, &ptr, 2, US" T=", addr->transport->name); -if ((log_extra_selector & LX_delivery_size) != 0) +if (LOGGING(delivery_size)) s = string_append(s, &size, &ptr, 2, US" S=", string_sprintf("%d", transport_count)); @@ -857,6 +898,7 @@ if (addr->transport->info->local) { if (addr->host_list) s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name); + s = d_log_interface(s, &size, &ptr); if (addr->shadow_message != NULL) s = string_cat(s, &size, &ptr, addr->shadow_message, Ustrlen(addr->shadow_message)); @@ -894,7 +936,7 @@ else if (addr->auth_id) { s = string_append(s, &size, &ptr, 2, US":", addr->auth_id); - if (log_extra_selector & LX_smtp_mailauth && addr->auth_sndr) + if (LOGGING(smtp_mailauth) && addr->auth_sndr) s = string_append(s, &size, &ptr, 2, US":", addr->auth_sndr); } } @@ -907,8 +949,7 @@ else /* confirmation message (SMTP (host_used) and LMTP (driver_name)) */ -if (log_extra_selector & LX_smtp_confirmation && - addr->message && +if (LOGGING(smtp_confirmation) && addr->message && (addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0)) { unsigned i; @@ -928,11 +969,11 @@ if (log_extra_selector & LX_smtp_confirmation && /* Time on queue and actual time taken to deliver */ -if ((log_extra_selector & LX_queue_time) != 0) +if (LOGGING(queue_time)) s = string_append(s, &size, &ptr, 2, US" QT=", readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) ); -if ((log_extra_selector & LX_deliver_time) != 0) +if (LOGGING(deliver_time)) s = string_append(s, &size, &ptr, 2, US" DT=", readconf_printtime(addr->more_errno)); @@ -1093,7 +1134,7 @@ if (addr->return_file >= 0 && addr->return_filename != NULL) /* Handle returning options, but only if there is an address to return the text to. */ - if (sender_address[0] != 0 || addr->p.errors_address != NULL) + if (sender_address[0] != 0 || addr->prop.errors_address != NULL) { if (tb->return_output) { @@ -1163,16 +1204,8 @@ if (result == OK) delivery_log(LOG_MAIN, addr, logchar, NULL); #ifdef SUPPORT_TLS - if (tls_out.ourcert) - { - tls_free_cert(tls_out.ourcert); - tls_out.ourcert = NULL; - } - if (tls_out.peercert) - { - tls_free_cert(tls_out.peercert); - tls_out.peercert = NULL; - } + tls_free_cert(&tls_out.ourcert); + tls_free_cert(&tls_out.peercert); tls_out.cipher = NULL; tls_out.peerdn = NULL; tls_out.ocsp = OCSP_NOT_REQ; @@ -1231,8 +1264,7 @@ else if (result == DEFER || result == PANIC) /* Create the address string for logging. Must not do this earlier, because an OK result may be changed to FAIL when a pipe returns text. */ - log_address = string_log_address(addr, - (log_write_selector & L_all_parents) != 0, result == OK); + log_address = string_log_address(addr, LOGGING(all_parents), result == OK); s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address)); @@ -1310,7 +1342,7 @@ else if (!testflag(addr, af_ignore_error) && (addr->special_action == SPECIAL_FREEZE || - (sender_address[0] == 0 && addr->p.errors_address == NULL) + (sender_address[0] == 0 && addr->prop.errors_address == NULL) )) { frozen_info = (addr->special_action == SPECIAL_FREEZE)? US"" : @@ -1343,18 +1375,16 @@ else /* Create the address string for logging. Must not do this earlier, because an OK result may be changed to FAIL when a pipe returns text. */ - log_address = string_log_address(addr, - (log_write_selector & L_all_parents) != 0, result == OK); + log_address = string_log_address(addr, LOGGING(all_parents), result == OK); s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address)); - if ((log_extra_selector & LX_sender_on_delivery) != 0) + if (LOGGING(sender_on_delivery)) s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">"); /* Return path may not be set if no delivery actually happened */ - if (used_return_path != NULL && - (log_extra_selector & LX_return_path_on_delivery) != 0) + if (used_return_path != NULL && LOGGING(return_path_on_delivery)) s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">"); if (addr->router != NULL) @@ -1810,11 +1840,11 @@ transport_instance *tp = addr->transport; /* Set up the return path from the errors or sender address. If the transport has its own return path setting, expand it and replace the existing value. */ -if(addr->p.errors_address != NULL) - return_path = addr->p.errors_address; +if(addr->prop.errors_address != NULL) + return_path = addr->prop.errors_address; #ifdef EXPERIMENTAL_SRS -else if(addr->p.srs_sender != NULL) - return_path = addr->p.srs_sender; +else if(addr->prop.srs_sender != NULL) + return_path = addr->prop.srs_sender; #endif else return_path = sender_address; @@ -2426,9 +2456,9 @@ while (addr_local != NULL) (addr->flags & (af_pfr|af_file)) == (next->flags & (af_pfr|af_file)) && (!uses_lp || Ustrcmp(next->local_part, addr->local_part) == 0) && (!uses_dom || Ustrcmp(next->domain, addr->domain) == 0) && - same_strings(next->p.errors_address, addr->p.errors_address) && - same_headers(next->p.extra_headers, addr->p.extra_headers) && - same_strings(next->p.remove_headers, addr->p.remove_headers) && + same_strings(next->prop.errors_address, addr->prop.errors_address) && + same_headers(next->prop.extra_headers, addr->prop.extra_headers) && + same_strings(next->prop.remove_headers, addr->prop.remove_headers) && same_ugid(tp, addr, next) && ((addr->host_list == NULL && next->host_list == NULL) || (addr->host_list != NULL && next->host_list != NULL && @@ -3128,15 +3158,17 @@ while (!done) break; case '2': - addr->peercert = NULL; if (*ptr) (void) tls_import_cert(ptr, &addr->peercert); + else + addr->peercert = NULL; break; case '3': - addr->ourcert = NULL; if (*ptr) (void) tls_import_cert(ptr, &addr->ourcert); + else + addr->ourcert = NULL; break; # ifndef DISABLE_OCSP @@ -3950,13 +3982,13 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) if ( (multi_domain || Ustrcmp(next->domain, addr->domain) == 0) && tp == next->transport && same_hosts(next->host_list, addr->host_list) - && same_strings(next->p.errors_address, addr->p.errors_address) - && same_headers(next->p.extra_headers, addr->p.extra_headers) + && same_strings(next->prop.errors_address, addr->prop.errors_address) + && same_headers(next->prop.extra_headers, addr->prop.extra_headers) && same_ugid(tp, next, addr) - && ( next->p.remove_headers == addr->p.remove_headers - || ( next->p.remove_headers != NULL - && addr->p.remove_headers != NULL - && Ustrcmp(next->p.remove_headers, addr->p.remove_headers) == 0 + && ( next->prop.remove_headers == addr->prop.remove_headers + || ( next->prop.remove_headers + && addr->prop.remove_headers + && Ustrcmp(next->prop.remove_headers, addr->prop.remove_headers) == 0 ) ) && ( !multi_domain || ( ( @@ -4000,11 +4032,11 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) /* Compute the return path, expanding a new one if required. The old one must be set first, as it might be referred to in the expansion. */ - if(addr->p.errors_address != NULL) - return_path = addr->p.errors_address; + if(addr->prop.errors_address != NULL) + return_path = addr->prop.errors_address; #ifdef EXPERIMENTAL_SRS - else if(addr->p.srs_sender != NULL) - return_path = addr->p.srs_sender; + else if(addr->prop.srs_sender != NULL) + return_path = addr->prop.srs_sender; #endif else return_path = sender_address; @@ -4448,7 +4480,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) } /* Local interface address/port */ - if (log_extra_selector & LX_incoming_interface && sending_ip_address) + if (LOGGING(incoming_interface) && sending_ip_address) { uschar * ptr = big_buffer; sprintf(CS ptr, "%.128s", sending_ip_address); @@ -4808,15 +4840,12 @@ print_address_error(address_item *addr, FILE *f, uschar *t) int count = Ustrlen(t); uschar *s = testflag(addr, af_pass_message)? addr->message : NULL; -if (s == NULL) - { - if (addr->user_message != NULL) s = addr->user_message; else return; - } +if (!s && !(s = addr->user_message)) + return; fprintf(f, "\n %s", t); -while (*s != 0) - { +while (*s) if (*s == '\\' && s[1] == 'n') { fprintf(f, "\n "); @@ -4833,7 +4862,6 @@ while (*s != 0) count = 0; } } - } } @@ -4845,9 +4873,9 @@ while (*s != 0) a bounce or a warning message. It tries to format the message reasonably as required by RFC 3461 by adding a space after each newline -we assume that this function is only called if addr->host_used is set and if so -a useable addr->message is available containing some Exim description with ": \n" -ending, followed by the L/SMTP error message. +it uses the same logic as print_address_error() above. if af_pass_message is true +and addr->message is set it uses the remote host answer. if not addr->user_message +is used instead if available. Arguments: addr the address @@ -4859,21 +4887,23 @@ Returns: nothing static void print_dsn_diagnostic_code(const address_item *addr, FILE *f) { -uschar * s; - -/* check host_used, af_pass_message flag and addr->message for safety reasons */ -if (!addr->host_used && testflag(addr, af_pass_message) && addr->message) - return; +uschar *s = testflag(addr, af_pass_message) ? addr->message : NULL; -/* search first ": ". we assume to find the remote-MTA answer there */ -DEBUG(D_deliver) - debug_printf("DSN Diagnostic-Code: addr->dsn_message = %s\n", addr->message); -if (!(s = Ustrstr(addr->message, ": "))) - return; /* not found, bail out */ +/* af_pass_message and addr->message set ? print remote host answer */ +if (s) + { + DEBUG(D_deliver) + debug_printf("DSN Diagnostic-Code: addr->message = %s\n", addr->message); -fprintf(f, "Diagnostic-Code: smtp; "); + /* search first ": ". we assume to find the remote-MTA answer there */ + if (!(s = Ustrstr(addr->message, ": "))) + return; /* not found, bail out */ + s += 2; /* skip ": " */ + fprintf(f, "Diagnostic-Code: smtp; "); + } +/* no message available. do nothing */ +else return; -s += 2; /* skip ": " */ while (*s) if (*s == '\\' && s[1] == 'n') { @@ -5593,10 +5623,17 @@ if (process_recipients != RECIP_IGNORE) { recipient_item *r = recipients_list + i; address_item *new = deliver_make_addr(r->address, FALSE); - new->p.errors_address = r->errors_to; + new->prop.errors_address = r->errors_to; #ifdef EXPERIMENTAL_INTERNATIONAL - new->p.utf8 = message_smtputf8; - DEBUG(D_deliver) debug_printf("utf8: %c\n", message_smtputf8 ? 'T':'F'); + if ((new->prop.utf8_msg = message_smtputf8)) + { + new->prop.utf8_downcvt = message_utf8_downconvert == 1; + new->prop.utf8_downcvt_maybe = message_utf8_downconvert == -1; + DEBUG(D_deliver) debug_printf("utf8, downconvert %s\n", + new->prop.utf8_downcvt ? "yes" + : new->prop.utf8_downcvt_maybe ? "ifneeded" + : "no"); + } #endif if (r->pno >= 0) @@ -5606,7 +5643,8 @@ if (process_recipients != RECIP_IGNORE) to be passed on to other DSN enabled MTAs */ new->dsn_flags = r->dsn_flags & rf_dsnflags; new->dsn_orcpt = r->orcpt; - DEBUG(D_deliver) debug_printf("DSN: set orcpt: %s flags: %d\n", new->dsn_orcpt, new->dsn_flags); + DEBUG(D_deliver) debug_printf("DSN: set orcpt: %s flags: %d\n", + new->dsn_orcpt, new->dsn_flags); switch (process_recipients) { @@ -6193,8 +6231,8 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ /* Just in case some router parameter refers to it. */ - return_path = (addr->p.errors_address != NULL)? - addr->p.errors_address : sender_address; + return_path = (addr->prop.errors_address != NULL)? + addr->prop.errors_address : sender_address; /* If a router defers an address, add a retry item. Whether or not to use the local part in the key is a property of the router. */ @@ -6264,8 +6302,8 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ if (addr_remote == addr && addr->router->same_domain_copy_routing && - addr->p.extra_headers == NULL && - addr->p.remove_headers == NULL && + addr->prop.extra_headers == NULL && + addr->prop.remove_headers == NULL && old_domain == addr->domain) { address_item **chain = &addr_route; @@ -6292,7 +6330,7 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ addr2->transport = addr->transport; addr2->host_list = addr->host_list; addr2->fallback_hosts = addr->fallback_hosts; - addr2->p.errors_address = addr->p.errors_address; + addr2->prop.errors_address = addr->prop.errors_address; copyflag(addr2, addr, af_hide_child | af_local_host_removed); DEBUG(D_deliver|D_route) @@ -6664,29 +6702,36 @@ else if (!dont_deliver) retry_update(&addr_defer, &addr_failed, &addr_succeed); addr_dsntmp = addr_succeed; addr_senddsn = NULL; -while(addr_dsntmp != NULL) +while(addr_dsntmp) { - DEBUG(D_deliver) - debug_printf("DSN: processing router : %s\n", addr_dsntmp->router->name); - - DEBUG(D_deliver) - debug_printf("DSN: processing successful delivery address: %s\n", addr_dsntmp->address); - /* af_ignore_error not honored here. it's not an error */ - - DEBUG(D_deliver) debug_printf("DSN: Sender_address: %s\n", sender_address); - DEBUG(D_deliver) debug_printf("DSN: orcpt: %s flags: %d\n", addr_dsntmp->dsn_orcpt, addr_dsntmp->dsn_flags); - DEBUG(D_deliver) debug_printf("DSN: envid: %s ret: %d\n", dsn_envid, dsn_ret); - DEBUG(D_deliver) debug_printf("DSN: Final recipient: %s\n", addr_dsntmp->address); - DEBUG(D_deliver) debug_printf("DSN: Remote SMTP server supports DSN: %d\n", addr_dsntmp->dsn_aware); + DEBUG(D_deliver) + { + debug_printf("DSN: processing router : %s\n" + "DSN: processing successful delivery address: %s\n" + "DSN: Sender_address: %s\n" + "DSN: orcpt: %s flags: %d\n" + "DSN: envid: %s ret: %d\n" + "DSN: Final recipient: %s\n" + "DSN: Remote SMTP server supports DSN: %d\n", + addr_dsntmp->router->name, + addr_dsntmp->address, + sender_address, + addr_dsntmp->dsn_orcpt, addr_dsntmp->dsn_flags, + dsn_envid, dsn_ret, + addr_dsntmp->address, + addr_dsntmp->dsn_aware + ); + } /* send report if next hop not DSN aware or a router flagged "last DSN hop" and a report was requested */ - if (((addr_dsntmp->dsn_aware != dsn_support_yes) || - ((addr_dsntmp->dsn_flags & rf_dsnlasthop) != 0)) - && - (((addr_dsntmp->dsn_flags & rf_dsnflags) != 0) && - ((addr_dsntmp->dsn_flags & rf_notify_success) != 0))) + if ( ( addr_dsntmp->dsn_aware != dsn_support_yes + || addr_dsntmp->dsn_flags & rf_dsnlasthop + ) + && addr_dsntmp->dsn_flags & rf_dsnflags + && addr_dsntmp->dsn_flags & rf_notify_success + ) { /* copy and relink address_item and send report with all of them at once later */ address_item *addr_next; @@ -6696,14 +6741,12 @@ while(addr_dsntmp != NULL) addr_senddsn->next = addr_next; } else - { - DEBUG(D_deliver) debug_printf("DSN: *** NOT SENDING DSN SUCCESS Message ***\n"); - } + DEBUG(D_deliver) debug_printf("DSN: not sending DSN success message\n"); addr_dsntmp = addr_dsntmp->next; } -if (addr_senddsn != NULL) +if (addr_senddsn) { pid_t pid; int fd; @@ -6858,10 +6901,10 @@ while (addr_failed != NULL) If neither of these cases obtains, something has gone wrong. Log the incident, but then ignore the error. */ - if (sender_address[0] == 0 && addr_failed->p.errors_address == NULL) + if (sender_address[0] == 0 && addr_failed->prop.errors_address == NULL) { - if (!testflag(addr_failed, af_retry_timedout) && - !testflag(addr_failed, af_ignore_error)) + if ( !testflag(addr_failed, af_retry_timedout) + && !testflag(addr_failed, af_ignore_error)) { log_write(0, LOG_MAIN|LOG_PANIC, "internal error: bounce message " "failure is neither frozen nor ignored (it's been ignored)"); @@ -6874,8 +6917,8 @@ while (addr_failed != NULL) mark the recipient done. */ if ( testflag(addr_failed, af_ignore_error) - || ( ((addr_failed->dsn_flags & rf_dsnflags) != 0) - && ((addr_failed->dsn_flags & rf_notify_failure) != rf_notify_failure)) + || ( addr_failed->dsn_flags & rf_dsnflags + && (addr_failed->dsn_flags & rf_notify_failure) != rf_notify_failure) ) { addr = addr_failed; @@ -6902,8 +6945,8 @@ while (addr_failed != NULL) else { - bounce_recipient = addr_failed->p.errors_address - ? addr_failed->p.errors_address : sender_address; + bounce_recipient = addr_failed->prop.errors_address + ? addr_failed->prop.errors_address : sender_address; /* Make a subprocess to send a message */ @@ -6938,8 +6981,8 @@ while (addr_failed != NULL) paddr = &addr_failed; for (addr = addr_failed; addr != NULL; addr = *paddr) - if (Ustrcmp(bounce_recipient, addr->p.errors_address - ? addr->p.errors_address : sender_address) == 0) + if (Ustrcmp(bounce_recipient, addr->prop.errors_address + ? addr->prop.errors_address : sender_address) == 0) { /* The same - dechain */ *paddr = addr->next; *pmsgchain = addr; @@ -7140,10 +7183,18 @@ wording. */ } /* output machine readable part */ - fprintf(f, "--%s\n" - "Content-type: message/delivery-status\n\n" - "Reporting-MTA: dns; %s\n", - bound, smtp_active_hostname); +#ifdef EXPERIMENTAL_INTERNATIONAL + if (message_smtputf8) + fprintf(f, "--%s\n" + "Content-type: message/global-delivery-status\n\n" + "Reporting-MTA: dns; %s\n", + bound, smtp_active_hostname); + else +#endif + fprintf(f, "--%s\n" + "Content-type: message/delivery-status\n\n" + "Reporting-MTA: dns; %s\n", + bound, smtp_active_hostname); if (dsn_envid) { @@ -7218,9 +7269,16 @@ wording. */ } } - fputs(topt & topt_no_body ? "Content-type: text/rfc822-headers\n\n" - : "Content-type: message/rfc822\n\n", - f); +#ifdef EXPERIMENTAL_INTERNATIONAL + if (message_smtputf8) + fputs(topt & topt_no_body ? "Content-type: message/global-headers\n\n" + : "Content-type: message/global\n\n", + f); + else +#endif + fputs(topt & topt_no_body ? "Content-type: text/rfc822-headers\n\n" + : "Content-type: message/rfc822\n\n", + f); fflush(f); transport_filter_argv = NULL; /* Just in case */ @@ -7338,7 +7396,7 @@ if (addr_defer == NULL) /* Log the end of this message, with queue time if requested. */ - if ((log_extra_selector & LX_queue_time_overall) != 0) + if (LOGGING(queue_time_overall)) log_write(0, LOG_MAIN, "Completed QT=%s", readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) ); else @@ -7435,7 +7493,7 @@ else if (addr_defer != (address_item *)(+1)) DEBUG(D_deliver) debug_printf("one_time: adding %s in place of %s\n", otaddr->address, otaddr->parent->address); receive_add_recipient(otaddr->address, t); - recipients_list[recipients_count-1].errors_to = otaddr->p.errors_address; + recipients_list[recipients_count-1].errors_to = otaddr->prop.errors_address; tree_add_nonrecipient(otaddr->parent->address); update_spool = TRUE; } @@ -7447,7 +7505,7 @@ else if (addr_defer != (address_item *)(+1)) if (sender_address[0] != 0) { - if (addr->p.errors_address == NULL) + if (addr->prop.errors_address == NULL) { if (Ustrstr(recipients, sender_address) == NULL) recipients = string_sprintf("%s%s%s", recipients, @@ -7455,9 +7513,9 @@ else if (addr_defer != (address_item *)(+1)) } else { - if (Ustrstr(recipients, addr->p.errors_address) == NULL) + if (Ustrstr(recipients, addr->prop.errors_address) == NULL) recipients = string_sprintf("%s%s%s", recipients, - (recipients[0] == 0)? "" : ",", addr->p.errors_address); + (recipients[0] == 0)? "" : ",", addr->prop.errors_address); } } } @@ -7861,7 +7919,7 @@ if (!regex_PRDR) regex_PRDR = regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE); #endif -#ifdef SUPPORT_TLS +#ifdef EXPERIMENTAL_INTERNATIONAL if (!regex_UTF8) regex_UTF8 = regex_must_compile(US"\\n250[\\s\\-]SMTPUTF8(\\s|\\n|$)", FALSE, TRUE); #endif @@ -7877,17 +7935,36 @@ if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA = uschar * deliver_get_sender_address (uschar * id) { +int rc; +uschar * new_sender_address, + * save_sender_address; + if (!spool_open_datafile(id)) return NULL; +/* Save and restore the global sender_address. I'm not sure if we should +not save/restore all the other global variables too, because +spool_read_header() may change all of them. But OTOH, when this +deliver_get_sender_address() gets called, the current message is done +already and nobody needs the globals anymore. (HS12, 2015-08-21) */ + sprintf(CS spoolname, "%s-H", id); -if (spool_read_header(spoolname, TRUE, TRUE) != spool_read_OK) +save_sender_address = sender_address; + +rc = spool_read_header(spoolname, TRUE, TRUE); + +new_sender_address = sender_address; +sender_address = save_sender_address; + +if (rc != spool_read_OK) return NULL; +assert(new_sender_address); + (void)close(deliver_datafile); deliver_datafile = -1; -return sender_address; +return new_sender_address; } /* vi: aw ai sw=2