summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/src/EDITME4
-rw-r--r--src/src/config.h.defaults1
-rw-r--r--src/src/deliver.c40
-rw-r--r--src/src/exim.c3
-rw-r--r--src/src/expand.c10
-rw-r--r--src/src/globals.c11
-rw-r--r--src/src/globals.h12
-rw-r--r--src/src/structs.h3
-rw-r--r--src/src/transport.c4
-rw-r--r--src/src/transports/smtp.c84
-rw-r--r--src/src/transports/smtp.h3
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. */