diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/src/EDITME | 4 | ||||
-rw-r--r-- | src/src/config.h.defaults | 1 | ||||
-rw-r--r-- | src/src/deliver.c | 40 | ||||
-rw-r--r-- | src/src/exim.c | 3 | ||||
-rw-r--r-- | src/src/expand.c | 10 | ||||
-rw-r--r-- | src/src/globals.c | 11 | ||||
-rw-r--r-- | src/src/globals.h | 12 | ||||
-rw-r--r-- | src/src/structs.h | 3 | ||||
-rw-r--r-- | src/src/transport.c | 4 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 84 | ||||
-rw-r--r-- | src/src/transports/smtp.h | 3 |
11 files changed, 170 insertions, 5 deletions
diff --git a/src/src/EDITME b/src/src/EDITME index e29c1eb25..1db70f715 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -469,6 +469,10 @@ EXIM_MONITOR=eximon.bin # Uncomment the following line to add Per-Recipient-Data-Response support. # EXPERIMENTAL_PRDR=yes +# Uncomment the following line to support Transport post-delivery actions, +# eg. for logging to a database. +# EXPERIMENTAL_TPDA=yes + ############################################################################### # THESE ARE THINGS YOU MIGHT WANT TO SPECIFY # diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 1594f6858..bf7ac63fb 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -170,6 +170,7 @@ it's a default value. */ #define EXPERIMENTAL_PRDR #define EXPERIMENTAL_SPF #define EXPERIMENTAL_SRS +#define EXPERIMENTAL_TPDA /* For developers */ #define WANT_DEEPER_PRINTF_CHECKS diff --git a/src/src/deliver.c b/src/src/deliver.c index 23e63d553..bc6a69fbf 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -695,6 +695,15 @@ 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 + tpda_delivery_ip = NULL; /* presume no successful remote delivery */ + tpda_delivery_port = 0; + tpda_delivery_fqdn = NULL; + tpda_delivery_local_part = NULL; + tpda_delivery_domain = NULL; + tpda_delivery_confirmation = NULL; +#endif + s = reset_point = store_get(size); log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE); @@ -741,7 +750,12 @@ if ((log_extra_selector & LX_delivery_size) != 0) if (addr->transport->info->local) { if (addr->host_list != NULL) + { s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name); + #ifdef EXPERIMENTAL_TPDA + tpda_delivery_fqdn = addr->host_list->name; + #endif + } if (addr->shadow_message != NULL) s = string_cat(s, &size, &ptr, addr->shadow_message, Ustrlen(addr->shadow_message)); @@ -760,6 +774,15 @@ else addr->host_used->port)); if (continue_sequence > 1) s = string_cat(s, &size, &ptr, US"*", 1); + + #ifdef EXPERIMENTAL_TPDA + tpda_delivery_ip = addr->host_used->address; + tpda_delivery_port = addr->host_used->port; + tpda_delivery_fqdn = addr->host_used->name; + tpda_delivery_local_part = addr->local_part; + tpda_delivery_domain = addr->domain; + tpda_delivery_confirmation = addr->message; + #endif } #ifdef SUPPORT_TLS @@ -827,6 +850,23 @@ store we used to build the line after writing it. */ s[ptr] = 0; log_write(0, flags, "%s", s); + +#ifdef EXPERIMENTAL_TPDA +if (addr->transport->tpda_delivery_action) + { + DEBUG(D_deliver) + debug_printf(" TPDA(Delivery): tpda_deliver_action=|%s| tpda_delivery_IP=%s\n", + addr->transport->tpda_delivery_action, tpda_delivery_ip); + + router_name = addr->router->name; + transport_name = addr->transport->name; + if (!expand_string(addr->transport->tpda_delivery_action) && *expand_string_message) + log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand tpda_deliver_action in %s: %s\n", + transport_name, expand_string_message); + router_name = NULL; + transport_name = NULL; + } +#endif store_reset(reset_point); return; } diff --git a/src/src/exim.c b/src/src/exim.c index 8ab0456d8..c5053ba7c 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -825,6 +825,9 @@ fprintf(f, "Support for:"); #ifdef EXPERIMENTAL_PRDR fprintf(f, " Experimental_PRDR"); #endif +#ifdef EXPERIMENTAL_TPDA + fprintf(f, " Experimental_TPDA"); +#endif fprintf(f, "\n"); fprintf(f, "Lookups (built-in):"); diff --git a/src/src/expand.c b/src/src/expand.c index edef45dba..a22ee2af4 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -677,6 +677,16 @@ static var_entry var_table[] = { { "tod_logfile", vtype_todlf, NULL }, { "tod_zone", vtype_todzone, NULL }, { "tod_zulu", vtype_todzulu, NULL }, +#ifdef EXPERIMENTAL_TPDA + { "tpda_defer_errno", vtype_int, &tpda_defer_errno }, + { "tpda_defer_errstr", vtype_stringptr, &tpda_defer_errstr }, + { "tpda_delivery_confirmation", vtype_stringptr, &tpda_delivery_confirmation }, + { "tpda_delivery_domain", vtype_stringptr, &tpda_delivery_domain }, + { "tpda_delivery_fqdn", vtype_stringptr, &tpda_delivery_fqdn }, + { "tpda_delivery_ip", vtype_stringptr, &tpda_delivery_ip }, + { "tpda_delivery_local_part",vtype_stringptr,&tpda_delivery_local_part }, + { "tpda_delivery_port", vtype_int, &tpda_delivery_port }, +#endif { "transport_name", vtype_stringptr, &transport_name }, { "value", vtype_stringptr, &lookup_value }, { "version_number", vtype_stringptr, &version_string }, diff --git a/src/src/globals.c b/src/src/globals.c index 05bb0ae86..d4589cd18 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1280,6 +1280,17 @@ int thismessage_size_limit = 0; int timeout_frozen_after = 0; BOOL timestamps_utc = FALSE; +#ifdef EXPERIMENTAL_TPDA +int tpda_defer_errno = 0; +uschar *tpda_defer_errstr = NULL; +uschar *tpda_delivery_ip = NULL; +int tpda_delivery_port = 0; +uschar *tpda_delivery_fqdn = NULL; +uschar *tpda_delivery_local_part= NULL; +uschar *tpda_delivery_domain = NULL; +uschar *tpda_delivery_confirmation = NULL; +#endif + transport_instance *transports = NULL; transport_instance transport_defaults = { diff --git a/src/src/globals.h b/src/src/globals.h index 2cc16881b..104b5fa7a 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -834,6 +834,18 @@ extern int test_harness_load_avg; /* For use when testing */ extern int thismessage_size_limit; /* Limit for this message */ extern int timeout_frozen_after; /* Max time to keep frozen messages */ extern BOOL timestamps_utc; /* Use UTC for all times */ + +#ifdef EXPERIMENTAL_TPDA +extern int tpda_defer_errno; /* error number set when a remote delivery is deferred with a host error */ +extern uschar *tpda_defer_errstr; /* error string set when a remote delivery is deferred with a host error */ +extern uschar *tpda_delivery_ip; /* IP of host, which has accepted delivery */ +extern int tpda_delivery_port; /* port of host, which has accepted delivery */ +extern uschar *tpda_delivery_fqdn; /* FQDN of host, which has accepted delivery */ +extern uschar *tpda_delivery_local_part;/* local part of address being delivered */ +extern uschar *tpda_delivery_domain; /* domain part of address being delivered */ +extern uschar *tpda_delivery_confirmation; /* SMTP confirmation message */ +#endif + extern uschar *transport_name; /* Name of transport last started */ extern int transport_count; /* Count of bytes transported */ extern int transport_newlines; /* Accurate count of number of newline chars transported */ diff --git a/src/src/structs.h b/src/src/structs.h index 53aa2106b..baf9a0f85 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -184,6 +184,9 @@ typedef struct transport_instance { BOOL log_fail_output; BOOL log_defer_output; BOOL retry_use_local_part; /* Defaults true for local, false for remote */ +#ifdef EXPERIMENTAL_TPDA + uschar *tpda_delivery_action; /* String to expand on success */ +#endif } transport_instance; diff --git a/src/src/transport.c b/src/src/transport.c index 7dd1afb85..d2540be62 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -94,6 +94,10 @@ optionlist optionlist_transports[] = { (void *)offsetof(transport_instance, shadow_condition) }, { "shadow_transport", opt_stringptr|opt_public, (void *)offsetof(transport_instance, shadow) }, +#ifdef EXPERIMENTAL_TPDA + { "tpda_delivery_action",opt_stringptr | opt_public, + (void *)offsetof(transport_instance, tpda_delivery_action) }, +#endif { "transport_filter", opt_stringptr|opt_public, (void *)offsetof(transport_instance, filter_command) }, { "transport_filter_timeout", opt_time|opt_public, diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 25cc5490a..9918f3116 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -156,6 +156,10 @@ optionlist smtp_transport_options[] = { { "tls_verify_certificates", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) } #endif +#ifdef EXPERIMENTAL_TPDA + ,{ "tpda_host_defer_action", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, tpda_host_defer_action) }, +#endif }; /* Size of the options list. An extern variable has to be used so that its @@ -233,6 +237,9 @@ smtp_transport_options_block smtp_transport_option_defaults = { NULL, /* dkim_sign_headers */ NULL /* dkim_strict */ #endif +#ifdef EXPERIMENTAL_TPDA + ,NULL /* tpda_host_defer_action */ +#endif }; @@ -577,6 +584,59 @@ else +#ifdef EXPERIMENTAL_TPDA +/************************************************* +* Post-defer action * +*************************************************/ + +/* This expands an arbitrary per-transport string. + It might, for example, be used to write to the database log. + +Arguments: + ob transport options block + addr the address item containing error information + host the current host + +Returns: nothing +*/ + +static void +tpda_deferred(smtp_transport_options_block *ob, address_item *addr, host_item *host) +{ +uschar *action = ob->tpda_host_defer_action; +if (!action) + return; + +tpda_delivery_ip = string_copy(host->address); +tpda_delivery_port = (host->port == PORT_NONE)? 25 : host->port; +tpda_delivery_fqdn = string_copy(host->name); +tpda_delivery_local_part = string_copy(addr->local_part); +tpda_delivery_domain = string_copy(addr->domain); +tpda_defer_errno = addr->basic_errno; + +tpda_defer_errstr = addr->message + ? addr->basic_errno > 0 + ? string_sprintf("%s: %s", addr->message, strerror(addr->basic_errno)) + : string_copy(addr->message) + : addr->basic_errno > 0 + ? string_copy(strerror(addr->basic_errno)) + : NULL; + +DEBUG(D_transport) + debug_printf(" TPDA(host defer): tpda_host_defer_action=|%s| tpda_delivery_IP=%s\n", + action, tpda_delivery_ip); + +router_name = addr->router->name; +transport_name = addr->transport->name; +if (!expand_string(action) && *expand_string_message) + log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand tpda_defer_action in %s: %s\n", + transport_name, expand_string_message); +router_name = transport_name = NULL; +} +#endif + + + /************************************************* * Synchronize SMTP responses * *************************************************/ @@ -976,7 +1036,7 @@ smtp_auth(uschar *buffer, unsigned bufsize, address_item *addrlist, host_item *h FALSE); return DEFER; } - + return OK; } @@ -1912,7 +1972,12 @@ if (!ok) ok = TRUE; else /* Set up confirmation if needed - applies only to SMTP */ - if ((log_extra_selector & LX_smtp_confirmation) != 0 && !lmtp) + if ( + #ifndef EXPERIMENTAL_TPDA + (log_extra_selector & LX_smtp_confirmation) != 0 && + #endif + !lmtp + ) { uschar *s = string_printing(buffer); conf = (s == buffer)? (uschar *)string_copy(s) : s; @@ -1991,12 +2056,12 @@ if (!ok) ok = TRUE; else the transport name. See lots of comments in deliver.c about the reasons for the complications when homonyms are involved. Just carry on after write error, as it may prove possible to update the spool file later. */ - + if (testflag(addr, af_homonym)) sprintf(CS buffer, "%.500s/%s\n", addr->unique + 3, tblock->name); else sprintf(CS buffer, "%.500s\n", addr->unique); - + DEBUG(D_deliver) debug_printf("journalling %s", buffer); len = Ustrlen(CS buffer); if (write(journal_fd, buffer, len) != len) @@ -2033,7 +2098,7 @@ if (!ok) ok = TRUE; else sprintf(CS buffer, "%.500s/%s\n", addr->unique + 3, tblock->name); else sprintf(CS buffer, "%.500s\n", addr->unique); - + DEBUG(D_deliver) debug_printf("journalling(PRDR) %s", buffer); len = Ustrlen(CS buffer); if (write(journal_fd, buffer, len) != len) @@ -3051,6 +3116,11 @@ for (cutoff_retry = 0; expired && first_addr->basic_errno != ERRNO_TLSFAILURE) write_logs(first_addr, host); + #ifdef EXPERIMENTAL_TPDA + if (rc == DEFER) + tpda_deferred(ob, first_addr, host); + #endif + /* If STARTTLS was accepted, but there was a failure in setting up the TLS session (usually a certificate screwup), and the host is not in hosts_require_tls, and tls_tempfail_tryclear is true, try again, with @@ -3073,6 +3143,10 @@ for (cutoff_retry = 0; expired && expanded_hosts != NULL, &message_defer, TRUE); if (rc == DEFER && first_addr->basic_errno != ERRNO_AUTHFAIL) write_logs(first_addr, host); + #ifdef EXPERIMENTAL_TPDA + if (rc == DEFER) + tpda_deferred(ob, first_addr, host); + #endif } #endif } diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index 8e85294bc..0d8801647 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -73,6 +73,9 @@ typedef struct { uschar *dkim_sign_headers; uschar *dkim_strict; #endif + #ifdef EXPERIMENTAL_TPDA + uschar *tpda_host_defer_action; + #endif } smtp_transport_options_block; /* Data for reading the private options. */ |