X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fdeliver.c;h=5000f1cbc38a22b2f408c3798c0b1cfd431d5e92;hb=e0eb00cd78f2dbf91aba5dffa579177b1e1815a1;hp=6fac6d8db54082cb8a19f5d93e891999f7d8b78e;hpb=c562fd30c03126dd72d76ec43842d9d00fcd8bf3;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/deliver.c b/src/src/deliver.c index 6fac6d8db..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,15 +746,15 @@ 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; @@ -769,7 +769,7 @@ 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); @@ -778,7 +778,7 @@ deliver_localpart = save_local; deliver_domain = save_domain; router_name = transport_name = NULL; } -#endif /*EXPERIMENTAL_TPDA*/ +#endif /*EXPERIMENTAL_EVENT*/ @@ -803,7 +803,7 @@ 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 @@ -870,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" @@ -938,8 +939,8 @@ store we used to build the line after writing it. */ s[ptr] = 0; log_write(0, flags, "%s", s); -#ifdef EXPERIMENTAL_TPDA -if (!msg) tpda_msg_event(US"msg:delivery", addr); +#ifdef EXPERIMENTAL_EVENT +if (!msg) msg_event_raise(US"msg:delivery", addr); #endif store_reset(reset_point); @@ -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; @@ -1380,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); @@ -3843,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. */ @@ -3914,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; @@ -3943,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 @@ -4792,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 */ /************************************************* @@ -5584,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; @@ -5595,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; @@ -6659,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); @@ -6683,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) @@ -6701,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 */ @@ -6734,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 */ @@ -6744,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); @@ -6870,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; @@ -6930,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 @@ -6966,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"))) @@ -7099,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) { @@ -7119,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 @@ -7201,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; @@ -7246,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 @@ -7363,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 } @@ -7552,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) @@ -7576,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"))) @@ -7595,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"))) @@ -7672,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); @@ -7696,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 */ @@ -7714,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*/