summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/ChangeLog6
-rw-r--r--doc/doc-txt/experimental-spec.txt17
-rw-r--r--src/src/acl.c7
-rw-r--r--src/src/deliver.c12
-rw-r--r--src/src/functions.h1
-rw-r--r--src/src/transports/smtp.c10
-rw-r--r--test/confs/570047
-rw-r--r--test/log/570051
-rw-r--r--test/scripts/5700-events/570020
-rw-r--r--test/stdout/570019
10 files changed, 139 insertions, 51 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 742243c2d..142d81e05 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -90,6 +90,12 @@ JH/18 Bug 1709: When built with TLS support, the tls_advertise_hosts option now
HS/03 Add -bP config_file as a synonym for -bP configure_file, for consistency
with the $config_file variable.
+JH/19 Two additional event types: msg:rcpt:defer and msg:rcpt:host:defer. Both
+ in transport context, after the attempt, and per-recipient. The latter type
+ is per host attempted. The event data is the error message, and the errno
+ information encodes the lookup type (A vs. MX) used for the (first) host,
+ and the trailing two digits of the smtp 4xx reponse.
+
Exim version 4.86
-----------------
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index c93123c39..74614cd3f 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -798,6 +798,8 @@ expansion is done. The current list of events is:
msg:complete after main per message
msg:delivery after transport per recipient
+ msg:rcpt:host:defer after transport per recipient per host
+ msg:rcpt:defer after transport per recipient
msg:host:defer after transport per attempt
msg:fail:delivery after main per recipient
msg:fail:internal after main per recipient
@@ -811,16 +813,20 @@ variable to decide when to act. The value of the variable is a colon-separated
list, defining a position in the tree of possible events; it may be used as
a list or just matched on as a whole. There will be no whitespace.
+New event types may be added in the future.
+
There is an auxilary variable, $event_data, for which the
content is event_dependent:
msg:delivery smtp confirmation mssage
+ msg:rcpt:host:defer error string
+ msg:rcpt:defer error string
msg:host:defer error string
tls:cert verification chain depth
smtp:connect smtp banner
-The msg:host:defer event populates one extra variable, $event_defer_errno.
+The :defer events populate one extra variable, $event_defer_errno.
The following variables are likely to be useful depending on the event type:
@@ -848,7 +854,14 @@ event_action = ${if eq {msg:delivery}{$event_name} \
The string is expanded when each of the supported events occur
and any side-effects of the expansion will happen.
-Note that for complex operations an ACL expansion can be used.
+
+Note that for complex operations an ACL expansion can be used,
+however due to the multiple contexts the Exim operates in
+a) variables set in events raised from transports will not
+ be visible outside that transport call.
+b) acl_m variables in a server context are lost on a new connection,
+ and after helo/ehlo/mail/starttls/rset commands
+
The expansion of the event_action option should normally
diff --git a/src/src/acl.c b/src/src/acl.c
index 064ee6ccb..911ecfed2 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -3743,7 +3743,12 @@ for (; cb != NULL; cb = cb->next)
case ACLC_SET:
{
int old_pool = store_pool;
- if (cb->u.varname[0] == 'c') store_pool = POOL_PERM;
+ if ( cb->u.varname[0] == 'c'
+#ifdef EXPERIMENTAL_EVENT
+ || event_name /* An event is being delivered */
+#endif
+ )
+ store_pool = POOL_PERM;
acl_var_create(cb->u.varname)->data.ptr = string_copy(arg);
store_pool = old_pool;
}
diff --git a/src/src/deliver.c b/src/src/deliver.c
index e1f4e0e29..65f148c07 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -785,12 +785,14 @@ if (action)
return NULL;
}
-static void
+void
msg_event_raise(const uschar * event, const address_item * addr)
{
const uschar * save_domain = deliver_domain;
uschar * save_local = deliver_localpart;
const uschar * save_host = deliver_host;
+const uschar * save_address = deliver_host_address;
+const int save_port = deliver_host_port;
if (!addr->transport)
return;
@@ -802,9 +804,13 @@ deliver_localpart = addr->local_part;
deliver_host = addr->host_used ? addr->host_used->name : NULL;
(void) event_raise(addr->transport->event_action, event,
- addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
- ? addr->message : NULL);
+ addr->host_used
+ || Ustrcmp(addr->transport->driver_name, "smtp") == 0
+ || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
+ ? addr->message : NULL);
+deliver_host_port = save_port;
+deliver_host_address = save_address;
deliver_host = save_host;
deliver_localpart = save_local;
deliver_domain = save_domain;
diff --git a/src/src/functions.h b/src/src/functions.h
index 6f6c643b8..e9f7ab658 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -166,6 +166,7 @@ extern void enq_end(uschar *);
extern BOOL enq_start(uschar *, unsigned);
#ifdef EXPERIMENTAL_EVENT
extern uschar *event_raise(uschar *, const uschar *, uschar *);
+extern void msg_event_raise(const uschar *, const address_item *);
#endif
extern void exim_exit(int);
extern void exim_nullstd(void);
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 59afe42aa..66d632fad 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -919,12 +919,22 @@ while (count-- > 0)
addr->basic_errno = ERRNO_RCPT4XX;
addr->more_errno |= ((buffer[1] - '0')*10 + buffer[2] - '0') << 8;
+#ifdef EXPERIMENTAL_EVENT
+ event_defer_errno = addr->more_errno;
+ msg_event_raise(US"msg:rcpt:host:defer", addr);
+#endif
+
/* Log temporary errors if there are more hosts to be tried.
If not, log this last one in the == line. */
if (host->next)
log_write(0, LOG_MAIN, "H=%s [%s]: %s", host->name, host->address, addr->message);
+#ifdef EXPERIMENTAL_EVENT
+ else
+ msg_event_raise(US"msg:rcpt:defer", addr);
+#endif
+
/* Do not put this message on the list of those waiting for specific
hosts, as otherwise it is likely to be tried too often. */
diff --git a/test/confs/5700 b/test/confs/5700
index 7a060cdb6..db1aa2a6e 100644
--- a/test/confs/5700
+++ b/test/confs/5700
@@ -46,6 +46,18 @@ ev_msg_fail:
domain <$domain> \
reason <$event_data>
+ev_msg_log:
+ accept logwrite = . \
+ $acl_arg1 \
+ ip <$host_address> \
+ port <$host_port> \
+ fqdn <$host> \
+ local_part <$local_part> \
+ domain <$domain> \
+ $acl_arg2 \
+ router <$router_name> \
+ transport <$transport_name>
+
ev_msg:
accept condition = ${if eq {fail} {${listextract{2}{$event_name}}}}
acl = ev_msg_fail
@@ -57,29 +69,21 @@ ev_msg:
logwrite = $this_expansion_will_fail
accept condition = ${if eq {$event_name}{msg:delivery}}
- logwrite = . \
- delivery \
- ip <$host_address> \
- port <$host_port> \
- fqdn <$host> \
- local_part <$local_part> \
- domain <$domain> \
- confirmation <$event_data> \
- router <$router_name> \
- transport <$transport_name>
+ acl = ev_msg_log delivery "confirmation <$event_data>"
accept condition = ${if eq {$event_name}{msg:host:defer}}
- logwrite = . \
- deferral \
- ip <$host_address> \
- port <$host_port> \
- fqdn <$host> \
- local_part <$local_part> \
- domain <$domain> \
- errno <$event_defer_errno> \
- errstr <$event_data> \
- router <$router_name> \
- transport <$transport_name>
+ acl = ev_msg_log "host deferral" \
+ "errno <$event_defer_errno> errstr <$event_data>"
+
+ accept condition = ${if eq {$event_name}{msg:rcpt:defer}}
+ set acl_m_ev_lkup = ${eval:$event_defer_errno & 0xff}
+ set acl_m_ev_lkup = ${if = {$acl_m_ev_lkup}{65} {A} \
+ { ${if = {$acl_m_ev_lkup}{77} {MX} \
+ {$acl_m_ev_lkup}}}}
+ set acl_m_ev_code = 4${eval:$event_defer_errno >>8}
+ acl = ev_msg_log "rcpt deferral" \
+ "err <$event_defer_errno>:<$acl_m_ev_lkup:$acl_m_ev_code> \
+ errstr <$event_data>"
logger:
warn logwrite = event $event_name
@@ -105,6 +109,7 @@ others:
route_list = * 127.0.0.1 byname
self = send
transport = smtp
+ errors_to = ""
no_more
diff --git a/test/log/5700 b/test/log/5700
index 6af2a9011..37eace605 100644
--- a/test/log/5700
+++ b/test/log/5700
@@ -41,17 +41,32 @@
1999-03-02 09:44:33 10HmaZ-0005vi-00 . [127.0.0.1] -> [127.0.0.1]:1224
1999-03-02 09:44:33 10HmaZ-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP timeout after EHLO the.local.host.name: Connection timed out
1999-03-02 09:44:33 10HmaZ-0005vi-00 event msg:host:defer
-1999-03-02 09:44:33 10HmaZ-0005vi-00 . deferral ip <127.0.0.1> port <1224> fqdn <127.0.0.1> local_part <userx> domain <domain1> errno <110> errstr <SMTP timeout after EHLO the.local.host.name: Connection timed out> router <others> transport <smtp>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 . host deferral ip <127.0.0.1> port <1224> fqdn <127.0.0.1> local_part <userx> domain <domain1> errno <110> errstr <SMTP timeout after EHLO the.local.host.name: Connection timed out> router <others> transport <smtp>
1999-03-02 09:44:33 10HmaZ-0005vi-00 == userx@domain1 R=others T=smtp defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after EHLO the.local.host.name
1999-03-02 09:44:33 10HmaZ-0005vi-00 ** userx@domain1: retry timeout exceeded
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> R=10HmaZ-0005vi-00 U=EXIMUSER P=local S=sss
-1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <CALLER@the.local.host.name> R=dump_bounces
-1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbA-0005vi-00 event msg:complete
-1999-03-02 09:44:33 10HmbA-0005vi-00 . finished: 10HmbA-0005vi-00
+1999-03-02 09:44:33 10HmaZ-0005vi-00 userx@domain1: error ignored
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
1999-03-02 09:44:33 10HmaZ-0005vi-00 event msg:complete
1999-03-02 09:44:33 10HmaZ-0005vi-00 . finished: 10HmaZ-0005vi-00
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qqf
+1999-03-02 09:44:33 10HmbA-0005vi-00 event tcp:connect
+1999-03-02 09:44:33 10HmbA-0005vi-00 . [127.0.0.1]:1111
+1999-03-02 09:44:33 10HmbA-0005vi-00 event smtp:connect
+1999-03-02 09:44:33 10HmbA-0005vi-00 . [127.0.0.1] -> [127.0.0.1]:1224
+1999-03-02 09:44:33 10HmbA-0005vi-00 . banner <220 ESMTP>
+1999-03-02 09:44:33 10HmbA-0005vi-00 event msg:rcpt:host:defer
+1999-03-02 09:44:33 10HmbA-0005vi-00 event msg:rcpt:defer
+1999-03-02 09:44:33 10HmbA-0005vi-00 . rcpt deferral ip <127.0.0.1> port <1224> fqdn <127.0.0.1> local_part <userx> domain <domain1> err <12865>:<A:450> errstr <SMTP error from remote mail server after RCPT TO:<userx@domain1>: 450 NOT RIGHT NOW> router <others> transport <smtp>
+1999-03-02 09:44:33 10HmbA-0005vi-00 event tcp:close
+1999-03-02 09:44:33 10HmbA-0005vi-00 . [127.0.0.1] -> [127.0.0.1]:1224
+1999-03-02 09:44:33 10HmbA-0005vi-00 == userx@domain1 R=others T=smtp defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<userx@domain1>: 450 NOT RIGHT NOW
+1999-03-02 09:44:33 10HmbA-0005vi-00 ** userx@domain1: retry timeout exceeded
+1999-03-02 09:44:33 10HmbA-0005vi-00 userx@domain1: error ignored
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbA-0005vi-00 event msg:complete
+1999-03-02 09:44:33 10HmbA-0005vi-00 . finished: 10HmbA-0005vi-00
+1999-03-02 09:44:33 End queue run: pid=pppp -qqf
1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
1999-03-02 09:44:33 Start queue run: pid=pppp -qqf
1999-03-02 09:44:33 10HmbB-0005vi-00 event tcp:connect
@@ -64,24 +79,20 @@
1999-03-02 09:44:33 10HmbB-0005vi-00 ** userx@domain1 R=others T=smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<userx@domain1>: 550 GO AWAY
1999-03-02 09:44:33 10HmbB-0005vi-00 event msg:fail:delivery
1999-03-02 09:44:33 10HmbB-0005vi-00 . refused by fdqn <127.0.0.1> local_part <userx> domain <domain1>
-1999-03-02 09:44:33 10HmbC-0005vi-00 <= <> R=10HmbB-0005vi-00 U=EXIMUSER P=local S=sss
-1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@the.local.host.name> R=dump_bounces
-1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbC-0005vi-00 event msg:complete
-1999-03-02 09:44:33 10HmbC-0005vi-00 . finished: 10HmbC-0005vi-00
+1999-03-02 09:44:33 10HmbB-0005vi-00 userx@domain1: error ignored
1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
1999-03-02 09:44:33 10HmbB-0005vi-00 event msg:complete
1999-03-02 09:44:33 10HmbB-0005vi-00 . finished: 10HmbB-0005vi-00
1999-03-02 09:44:33 End queue run: pid=pppp -qqf
-1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbD-0005vi-00 cancelled by CALLER
-1999-03-02 09:44:33 10HmbD-0005vi-00 event msg:fail:internal
-1999-03-02 09:44:33 10HmbD-0005vi-00 . local_part <userx> domain <domain1> reason <delivery cancelled by administrator>
-1999-03-02 09:44:33 10HmbE-0005vi-00 <= <> R=10HmbD-0005vi-00 U=EXIMUSER P=local S=sss
-1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <CALLER@the.local.host.name> R=dump_bounces
-1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbE-0005vi-00 event msg:complete
-1999-03-02 09:44:33 10HmbE-0005vi-00 . finished: 10HmbE-0005vi-00
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbC-0005vi-00 cancelled by CALLER
+1999-03-02 09:44:33 10HmbC-0005vi-00 event msg:fail:internal
+1999-03-02 09:44:33 10HmbC-0005vi-00 . local_part <userx> domain <domain1> reason <delivery cancelled by administrator>
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= <> R=10HmbC-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmbD-0005vi-00 => :blackhole: <CALLER@the.local.host.name> R=dump_bounces
1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
1999-03-02 09:44:33 10HmbD-0005vi-00 event msg:complete
1999-03-02 09:44:33 10HmbD-0005vi-00 . finished: 10HmbD-0005vi-00
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbC-0005vi-00 event msg:complete
+1999-03-02 09:44:33 10HmbC-0005vi-00 . finished: 10HmbC-0005vi-00
diff --git a/test/scripts/5700-events/5700 b/test/scripts/5700-events/5700
index f7cd8272c..8fb2010f2 100644
--- a/test/scripts/5700-events/5700
+++ b/test/scripts/5700-events/5700
@@ -1,5 +1,5 @@
# Arbitrary expansion after transport
-# (EXPERIMENTAL_TPDA)
+# (EXPERIMENTAL_EVENT)
#
need_ipv4
#
@@ -67,6 +67,24 @@ A message which will hit a timeout at the destination server
#
#
exim -odq userx@domain1
+A message which will get deferred
+****
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250 HELP
+MAIL
+250 OK
+RCPT
+450 NOT RIGHT NOW
+QUIT
+220 OK
+****
+exim -qqf
+****
+#
+exim -odq userx@domain1
A message which will get refused
****
server PORT_S
diff --git a/test/stdout/5700 b/test/stdout/5700
index b185dca05..a8f3b7482 100644
--- a/test/stdout/5700
+++ b/test/stdout/5700
@@ -6,7 +6,7 @@ Connection request from [127.0.0.1]
EHLO the.local.host.name
250-OK
250 HELP
-MAIL FROM:<CALLER@the.local.host.name>
+MAIL FROM:<>
250 OK
RCPT TO:<userx@domain1>
250 OK
@@ -32,7 +32,7 @@ Connection request from [127.0.0.1]
EHLO the.local.host.name
250-OK
250 HELP
-MAIL FROM:<CALLER@the.local.host.name>
+MAIL FROM:<>
250 OK
RCPT TO:<userx@domain2>
250 OK
@@ -64,7 +64,20 @@ Connection request from [127.0.0.1]
EHLO the.local.host.name
250-OK
250 HELP
-MAIL FROM:<CALLER@the.local.host.name>
+MAIL FROM:<>
+250 OK
+RCPT TO:<userx@domain1>
+450 NOT RIGHT NOW
+QUIT
+220 OK
+End of script
+Listening on port 1224 ...
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO the.local.host.name
+250-OK
+250 HELP
+MAIL FROM:<>
250 OK
RCPT TO:<userx@domain1>
550 GO AWAY