X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsrc%2Fdeliver.c;h=5000f1cbc38a22b2f408c3798c0b1cfd431d5e92;hb=e0eb00cd78f2dbf91aba5dffa579177b1e1815a1;hp=2ee69d37e93a7565e1db069b2b1395c40b52c666;hpb=bd21a787cdeef803334a6c7bf50d23b2a18cbd6f;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/deliver.c b/src/src/deliver.c index 2ee69d37e..5000f1cbc 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -718,27 +718,27 @@ d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr) -#ifdef EXPERIMENTAL_TPDA -int -tpda_raise_event(uschar * action, uschar * event, uschar * ev_data) +#ifdef EXPERIMENTAL_EVENT +uschar * +event_raise(uschar * action, uschar * event, uschar * ev_data) { uschar * s; if (action) { DEBUG(D_deliver) - debug_printf("TPDA(%s): tpda_event_action=|%s| tpda_delivery_IP=%s\n", + debug_printf("Event(%s): event_action=|%s| delivery_IP=%s\n", event, action, deliver_host_address); - tpda_event = event; - tpda_data = ev_data; + event_name = event; + event_data = ev_data; if (!(s = expand_string(action)) && *expand_string_message) log_write(0, LOG_MAIN|LOG_PANIC, - "failed to expand tpda_event_action %s in %s: %s\n", + "failed to expand event_action %s in %s: %s\n", event, transport_name, expand_string_message); - tpda_event = tpda_data = NULL; + event_name = event_data = NULL; /* If the expansion returns anything but an empty string, flag for the caller to modify his normal processing @@ -746,18 +746,19 @@ if (action) if (s && *s) { DEBUG(D_deliver) - debug_printf("TPDA(%s): event_action returned \"%s\"\n", event, s); - return DEFER; + debug_printf("Event(%s): event_action returned \"%s\"\n", event, s); + return s; } } -return OK; +return NULL; } static void -tpda_msg_event(uschar * event, address_item * addr) +msg_event_raise(uschar * event, address_item * addr) { uschar * save_domain = deliver_domain; uschar * save_local = deliver_localpart; +uschar * save_host = deliver_host; if (!addr->transport) return; @@ -766,16 +767,18 @@ router_name = addr->router ? addr->router->name : NULL; transport_name = addr->transport->name; deliver_domain = addr->domain; deliver_localpart = addr->local_part; +deliver_host = addr->host_used ? addr->host_used->name : NULL; -(void) tpda_raise_event(addr->transport->tpda_event_action, event, +(void) event_raise(addr->transport->event_action, event, addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0 ? addr->message : NULL); +deliver_host = save_host; deliver_localpart = save_local; deliver_domain = save_domain; router_name = transport_name = NULL; } -#endif /*EXPERIMENTAL_TPDA*/ +#endif /*EXPERIMENTAL_EVENT*/ @@ -795,13 +798,12 @@ int ptr = 0; /* expanding buffer, for */ uschar *s; /* building log lines; */ void *reset_point; /* released afterwards. */ - /* Log the delivery on the main log. We use an extensible string to build up the log line, and reset the store afterwards. Remote deliveries should always have a pointer to the host item that succeeded; local deliveries can have a pointer to a single host item in their host list, for use by the transport. */ -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT /* presume no successful remote delivery */ lookup_dnssec_authenticated = NULL; #endif @@ -868,9 +870,10 @@ else if (continue_sequence > 1) s = string_cat(s, &size, &ptr, US"*", 1); -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT deliver_host_address = addr->host_used->address; deliver_host_port = addr->host_used->port; + deliver_host = addr->host_used->name; /* DNS lookup status */ lookup_dnssec_authenticated = addr->host_used->dnssec==DS_YES ? US"yes" @@ -936,9 +939,8 @@ store we used to build the line after writing it. */ s[ptr] = 0; log_write(0, flags, "%s", s); -#ifdef EXPERIMENTAL_TPDA -/*XXX cutthrough calls this also for non-delivery...*/ -tpda_msg_event(US"msg:delivery", addr); +#ifdef EXPERIMENTAL_EVENT +if (!msg) msg_event_raise(US"msg:delivery", addr); #endif store_reset(reset_point); @@ -979,7 +981,6 @@ int ptr = 0; /* expanding buffer, for */ uschar *s; /* building log lines; */ void *reset_point; /* released afterwards. */ - DEBUG(D_deliver) debug_printf("post-process %s (%d)\n", addr->address, result); /* Set up driver kind and name for logging. Disable logging if the router or @@ -1137,7 +1138,7 @@ if (result == OK) child_done(addr, now); } - /* Certificates for logging (via TPDA) */ + /* Certificates for logging (via events) */ #ifdef SUPPORT_TLS tls_out.ourcert = addr->ourcert; addr->ourcert = NULL; @@ -1255,6 +1256,11 @@ else if (result == DEFER || result == PANIC) s = string_append(s, &size, &ptr, 2, US": ", US strerror(addr->basic_errno)); + if (addr->host_used) + s = string_append(s, &size, &ptr, 5, + US" H=", addr->host_used->name, + US" [", addr->host_used->address, US"]"); + if (addr->message != NULL) s = string_append(s, &size, &ptr, 2, US": ", addr->message); @@ -1375,8 +1381,8 @@ else log_write(0, LOG_MAIN, "** %s", s); -#ifdef EXPERIMENTAL_TPDA - tpda_msg_event(US"msg:fail:delivery", addr); +#ifdef EXPERIMENTAL_EVENT + msg_event_raise(US"msg:fail:delivery", addr); #endif store_reset(reset_point); @@ -2988,16 +2994,15 @@ while (!done) to get all available data from pipe. unfinished has to be true as well. */ if (remaining < required) + { if (unfinished) continue; - else - { - msg = string_sprintf("failed to read pipe from transport process " - "%d for transport %s: required size=%d > remaining size=%d and unfinished=false", - pid, addr->transport->driver_name, required, remaining); - done = TRUE; - break; - } + msg = string_sprintf("failed to read pipe from transport process " + "%d for transport %s: required size=%d > remaining size=%d and unfinished=false", + pid, addr->transport->driver_name, required, remaining); + done = TRUE; + break; + } /* step behind the header */ ptr += PIPE_HEADER_SIZE; @@ -3703,7 +3708,7 @@ if (size > 99999) /* two write() calls would increase the complexity of reading from pipe */ /* convert size to human readable string prepended by id and subid */ -header_length = snprintf(writebuffer, PIPE_HEADER_SIZE+1, "%c%c%05d", id, subid, size); +header_length = snprintf(CS writebuffer, PIPE_HEADER_SIZE+1, "%c%c%05d", id, subid, size); if (header_length != PIPE_HEADER_SIZE) { log_write(0, LOG_MAIN|LOG_PANIC_DIE, "header snprintf failed\n"); @@ -3839,9 +3844,20 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) } /* Get the flag which specifies whether the transport can handle different - domains that nevertheless resolve to the same set of hosts. */ - - multi_domain = tp->multi_domain; + domains that nevertheless resolve to the same set of hosts. If it needs + expanding, get variables set: $address_data, $domain_data, $localpart_data, + $host, $host_address, $host_port. */ + if (tp->expand_multi_domain) + deliver_set_expansions(addr); + + if (exp_bool(addr, US"transport", tp->name, D_transport, + US"multi_domain", tp->multi_domain, tp->expand_multi_domain, + &multi_domain) != OK) + { + deliver_set_expansions(NULL); + remote_post_process(addr, LOG_MAIN|LOG_PANIC, addr->message, fallback); + continue; + } /* Get the maximum it can handle in one envelope, with zero meaning unlimited, which is forced for the MUA wrapper case. */ @@ -3910,26 +3926,35 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) entirely different domains. The host list pointers can be NULL in the case where the hosts are defined in the transport. There is also a configured maximum limit of addresses that can be handled at once (see comments above - for how it is computed). */ + for how it is computed). + If the transport does not handle multiple domains, enforce that also, + and if it might need a per-address check for this, re-evaluate it. + */ while ((next = *anchor) != NULL && address_count < address_count_max) { - 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_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))) + BOOL md; + 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_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 + ) ) + && ( !multi_domain + || ( ( + !tp->expand_multi_domain || (deliver_set_expansions(next), 1), + exp_bool(addr, + US"transport", next->transport->name, D_transport, + US"multi_domain", next->transport->multi_domain, + next->transport->expand_multi_domain, &md) == OK + ) + && md + ) ) ) { *anchor = next->next; next->next = NULL; @@ -3939,6 +3964,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) address_count++; } else anchor = &(next->next); + deliver_set_expansions(NULL); } /* If we are acting as an MUA wrapper, all addresses must go in a single @@ -4342,9 +4368,9 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) #ifndef DISABLE_PRDR if (addr->flags & af_prdr_used) rmt_dlv_checked_write(fd, 'P', '0', NULL, 0); - #endif +#endif - #ifdef EXPERIMENTAL_DSN +#ifdef EXPERIMENTAL_DSN memcpy(big_buffer, &addr->dsn_aware, sizeof(addr->dsn_aware)); rmt_dlv_checked_write(fd, 'D', '0', big_buffer, sizeof(addr->dsn_aware)); DEBUG(D_deliver) debug_printf("DSN write: addr->dsn_aware = %d\n", addr->dsn_aware); @@ -4718,6 +4744,10 @@ if (ancestor != addr) string_printing(original)); } +if (addr->host_used) + fprintf(f, "\n host %s [%s]", + addr->host_used->name, addr->host_used->address); + fprintf(f, "%s", CS se); return yield; } @@ -4784,8 +4814,56 @@ while (*s != 0) } +#ifdef EXPERIMENTAL_DSN +/*********************************************************** +* Print Diagnostic-Code for an address * +************************************************************/ +/* This function is called to print the error information out of an address for +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. + +Arguments: + addr the address + f the FILE to print on +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; + +/* 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 */ + +fprintf(f, "Diagnostic-Code: smtp; "); + +s += 2; /* skip ": " */ +while (*s) + if (*s == '\\' && s[1] == 'n') + { + fputs("\n ", f); /* as defined in RFC 3461 */ + s += 2; + } + else + fputc(*s++, f); + +fputc('\n', f); +} +#endif /* EXPERIMENTAL_DSN */ /************************************************* @@ -5576,7 +5654,7 @@ if (process_recipients != RECIP_IGNORE) break; } -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT if (process_recipients != RECIP_ACCEPT) { uschar * save_local = deliver_localpart; @@ -5587,7 +5665,7 @@ if (process_recipients != RECIP_IGNORE) deliver_domain = expand_string( string_sprintf("${domain:%s}", new->address)); - (void) tpda_raise_event(delivery_event_action, + (void) event_raise(event_action, US"msg:fail:internal", new->message); deliver_localpart = save_local; @@ -6550,6 +6628,7 @@ if (mua_wrapper) { uschar *s = (addr_failed->user_message != NULL)? addr_failed->user_message : addr_failed->message; + host_item * host; fprintf(stderr, "Delivery failed: "); if (addr_failed->basic_errno > 0) @@ -6557,6 +6636,8 @@ if (mua_wrapper) fprintf(stderr, "%s", strerror(addr_failed->basic_errno)); if (s != NULL) fprintf(stderr, ": "); } + if ((host = addr_failed->host_used)) + fprintf(stderr, "H=%s [%s]: ", host->name, host->address); if (s == NULL) { if (addr_failed->basic_errno <= 0) fprintf(stderr, "unknown error"); @@ -6648,14 +6729,13 @@ if (addr_senddsn != NULL) FILE *f = fdopen(fd, "wb"); /* header only as required by RFC. only failure DSN needs to honor RET=FULL */ int topt = topt_add_return_path | topt_no_body; - uschar boundaryStr[64]; + uschar * bound; DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address); /* build unique id for MIME boundary */ - snprintf(boundaryStr, sizeof(boundaryStr)-1, TIME_T_FMT "-eximdsn-%d", - time(NULL), rand()); - DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", boundaryStr); + bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand()); + DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", bound); if (errors_reply_to) fprintf(f, "Reply-To: %s\n", errors_reply_to); @@ -6672,7 +6752,7 @@ if (addr_senddsn != NULL) "This message was created automatically by mail delivery software.\n" " ----- The following addresses had successful delivery notifications -----\n", - qualify_domain_sender, sender_address, boundaryStr, boundaryStr); + qualify_domain_sender, sender_address, bound, bound); addr_dsntmp = addr_senddsn; while(addr_dsntmp) @@ -6690,7 +6770,7 @@ if (addr_senddsn != NULL) fprintf(f, "--%s\n" "Content-type: message/delivery-status\n\n" "Reporting-MTA: dns; %s\n", - boundaryStr, smtp_active_hostname); + bound, smtp_active_hostname); if (dsn_envid != NULL) { /* must be decoded from xtext: see RFC 3461:6.3a */ @@ -6723,7 +6803,7 @@ if (addr_senddsn != NULL) fputc('\n', f); } - fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", boundaryStr); + fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", bound); fflush(f); transport_filter_argv = NULL; /* Just in case */ @@ -6733,8 +6813,7 @@ if (addr_senddsn != NULL) transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0); fflush(f); - fprintf(f,"\n"); - fprintf(f,"--%s--\n", boundaryStr); + fprintf(f,"\n--%s--\n", bound); fflush(f); fclose(f); @@ -6859,7 +6938,7 @@ while (addr_failed != NULL) int max = (bounce_return_size_limit/DELIVER_IN_BUFFER_SIZE + 1) * DELIVER_IN_BUFFER_SIZE; #ifdef EXPERIMENTAL_DSN - uschar boundaryStr[64]; + uschar * bound; uschar *dsnlimitmsg; uschar *dsnnotifyhdr; int topt; @@ -6919,13 +6998,12 @@ while (addr_failed != NULL) #ifdef EXPERIMENTAL_DSN /* generate boundary string and output MIME-Headers */ - snprintf(boundaryStr, sizeof(boundaryStr)-1, TIME_T_FMT "-eximdsn-%d", - time(NULL), rand()); + bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand()); fprintf(f, "Content-Type: multipart/report;" " report-type=delivery-status; boundary=%s\n" "MIME-Version: 1.0\n", - boundaryStr); + bound); #endif /* Open a template file if one is provided. Log failure to open, but @@ -6955,7 +7033,7 @@ while (addr_failed != NULL) /* output human readable part as text/plain section */ fprintf(f, "--%s\n" "Content-type: text/plain; charset=us-ascii\n\n", - boundaryStr); + bound); #endif if ((emf_text = next_emf(emf, US"intro"))) @@ -7088,7 +7166,7 @@ wording. */ fprintf(f, "--%s\n" "Content-type: message/delivery-status\n\n" "Reporting-MTA: dns; %s\n", - boundaryStr, smtp_active_hostname); + bound, smtp_active_hostname); if (dsn_envid) { @@ -7108,8 +7186,11 @@ wording. */ "Status: 5.0.0\n", addr->address); if (addr->host_used && addr->host_used->name) - fprintf(f, "Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n", - addr->host_used->name, addr->basic_errno); + { + fprintf(f, "Remote-MTA: dns; %s\n", + addr->host_used->name); + print_dsn_diagnostic_code(addr, f); + } } #endif @@ -7190,7 +7271,7 @@ wording. */ bounce_return_size_limit is always honored. */ - fprintf(f, "\n--%s\n", boundaryStr); + fprintf(f, "\n--%s\n", bound); dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned"; dsnnotifyhdr = NULL; @@ -7235,7 +7316,7 @@ wording. */ if (emf) (void)fclose(emf); - fprintf(f, "\n--%s--\n", boundaryStr); + fprintf(f, "\n--%s--\n", bound); #endif /*EXPERIMENTAL_DSN*/ /* Close the file, which should send an EOF to the child process @@ -7352,8 +7433,8 @@ if (addr_defer == NULL) /* Unset deliver_freeze so that we won't try to move the spool files further down */ deliver_freeze = FALSE; -#ifdef EXPERIMENTAL_TPDA - (void) tpda_raise_event(delivery_event_action, US"msg:complete", NULL); +#ifdef EXPERIMENTAL_EVENT + (void) event_raise(event_action, US"msg:complete", NULL); #endif } @@ -7541,7 +7622,7 @@ else if (addr_defer != (address_item *)(+1)) FILE *wmf = NULL; FILE *f = fdopen(fd, "wb"); #ifdef EXPERIMENTAL_DSN - uschar boundaryStr[64]; + uschar * bound; #endif if (warn_message_file) @@ -7565,13 +7646,12 @@ else if (addr_defer != (address_item *)(+1)) #ifdef EXPERIMENTAL_DSN /* generated boundary string and output MIME-Headers */ - snprintf(boundaryStr, sizeof(boundaryStr)-1, - TIME_T_FMT "-eximdsn-%d", time(NULL), rand()); + bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand()); fprintf(f, "Content-Type: multipart/report;" " report-type=delivery-status; boundary=%s\n" "MIME-Version: 1.0\n", - boundaryStr); + bound); #endif if ((wmf_text = next_emf(wmf, US"header"))) @@ -7584,7 +7664,7 @@ else if (addr_defer != (address_item *)(+1)) /* output human readable part as text/plain section */ fprintf(f, "--%s\n" "Content-type: text/plain; charset=us-ascii\n\n", - boundaryStr); + bound); #endif if ((wmf_text = next_emf(wmf, US"intro"))) @@ -7661,7 +7741,7 @@ else if (addr_defer != (address_item *)(+1)) fprintf(f, "\n--%s\n" "Content-type: message/delivery-status\n\n" "Reporting-MTA: dns; %s\n", - boundaryStr, + bound, smtp_active_hostname); @@ -7685,14 +7765,17 @@ else if (addr_defer != (address_item *)(+1)) fprintf(f,"Final-Recipient: rfc822;%s\n", addr_dsndefer->address); fprintf(f,"Status: 4.0.0\n"); if (addr_dsndefer->host_used && addr_dsndefer->host_used->name) - fprintf(f,"Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n", - addr_dsndefer->host_used->name, addr_dsndefer->basic_errno); + { + fprintf(f,"Remote-MTA: dns; %s\n", + addr_dsndefer->host_used->name); + print_dsn_diagnostic_code(addr_dsndefer, f); + } addr_dsndefer = addr_dsndefer->next; } fprintf(f, "\n--%s\n" "Content-type: text/rfc822-headers\n\n", - boundaryStr); + bound); fflush(f); /* header only as required by RFC. only failure DSN needs to honor RET=FULL */ @@ -7703,7 +7786,7 @@ else if (addr_defer != (address_item *)(+1)) transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0); fflush(f); - fprintf(f,"\n--%s--\n", boundaryStr); + fprintf(f,"\n--%s--\n", bound); fflush(f); #endif /*EXPERIMENTAL_DSN*/