contents of header lines is done.
.vitem &$message_id$&
-This is an old name for &$message_exim_id$&, which is now deprecated.
+This is an old name for &$message_exim_id$&. It is now deprecated.
.vitem &$message_linecount$&
.vindex "&$message_linecount$&"
Transport post-delivery actions
--------------------------------------------------------------
-An arbitrary per-transport string can be expanded on successful delivery,
+An arbitrary per-transport string can be expanded upon various transport events
and (for SMTP transports) a second string on deferrals caused by a host error.
+Additionally a main-section configuration option can be expanded on some
+per-message events.
This feature may be used, for example, to write exim internal log information
(not available otherwise) into a database.
in your Local/Makefile
-and define the tpda_event_action option in the transport, to
-be expanded when the event fires.
+and define one or both of
+- the tpda_event_action option in the transport
+- the delivery_event_action
+to be expanded when the event fires.
A new variable, $tpda_event, is set to the event type when the
expansion is done. The current list of events is:
- msg:delivery
- msg:host:defer
- tcp:connect
- tcp:close
- tls:cert
- smtp:connect
+ msg:complete main per message
+ msg:delivery transport per recipient
+ msg:host:defer transport per attempt
+ msg:fail:delivery main per recipient
+ msg:fail:internal main per recipient
+ tcp:connect transport per connection
+ tcp:close transport per connection
+ tls:cert transport per certificate in verification chain
+ smtp:connect transport per connection
The expansion is called for all event types, and should use the $tpda_event
value to decide when to act. The variable data is a colon-separated
The msg:host:defer event populates one extra variable, $tpda_defer_errno.
-The following variables are likely to be useful for most event types:
+The following variables are likely to be useful depending on the event type:
router_name, transport_name
local_part, domain
tls_out_peercert
lookup_dnssec_authenticated, tls_out_dane
sending_ip_address, sending_port
+ message_exim_id
An example might look like:
'${quote_pgsql:$message_exim_id}')}} \
} {}}
-The string is expanded after the delivery completes and any
+The string is expanded for each of the supported events and any
side-effects will happen. The result is then discarded.
Note that for complex operations an ACL expansion can be used.
-During the expansion the tpda_event variable will contain the
-string-list "msg:delivery".
-
The expansion of the tpda_event_action option should normally
return an empty string. Should it return anything else the
msg:delivery (ignored)
msg:host:defer (ignored)
+ msg:fail:delivery (ignored)
tcp:connect do not connect
tcp:close (ignored)
tls:cert refuse verification
#endif
+
+
#ifdef EXPERIMENTAL_TPDA
int
tpda_raise_event(uschar * action, uschar * event, uschar * ev_data)
}
return OK;
}
-#endif
+
+static void
+tpda_msg_event(uschar * event, address_item * addr)
+{
+uschar * save_domain = deliver_domain;
+uschar * save_local = deliver_localpart;
+
+if (!addr->transport)
+ return;
+
+router_name = addr->router ? addr->router->name : NULL;
+transport_name = addr->transport->name;
+deliver_domain = addr->domain;
+deliver_localpart = addr->local_part;
+
+(void) tpda_raise_event(addr->transport->tpda_event_action, event,
+ addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
+ ? addr->message : NULL);
+
+deliver_localpart = save_local;
+deliver_domain = save_domain;
+router_name = transport_name = NULL;
+}
+#endif /*EXPERIMENTAL_TPDA*/
+
+
/* If msg is NULL this is a delivery log and logchar is used. Otherwise
this is a nonstandard call; no two-character delivery flag is written
log_write(0, flags, "%s", s);
#ifdef EXPERIMENTAL_TPDA
- {
- uschar * save_domain = deliver_domain;
- uschar * save_local = deliver_localpart;
-
- router_name = addr->router ? addr->router->name : NULL;
- transport_name = addr->transport ? addr->transport->name : NULL;
- deliver_domain = addr->domain;
- deliver_localpart = addr->local_part;
-
- (void) tpda_raise_event(addr->transport->tpda_event_action, US"msg:delivery",
- addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
- ? addr->message : NULL);
-
- deliver_localpart = save_local;
- deliver_domain = save_domain;
- router_name = transport_name = NULL;
- }
+/*XXX cutthrough calls this also for non-delivery...*/
+tpda_msg_event(US"msg:delivery", addr);
#endif
+
store_reset(reset_point);
return;
}
deliver_msglog("%s %s\n", now, s);
log_write(0, LOG_MAIN, "** %s", s);
+
+#ifdef EXPERIMENTAL_TPDA
+ tpda_msg_event(US"msg:fail:delivery", addr);
+#endif
+
store_reset(reset_point);
}
addr_last = new;
break;
}
+
+#ifdef EXPERIMENTAL_TPDA
+ if (process_recipients != RECIP_ACCEPT)
+ {
+ uschar * save_local = deliver_localpart;
+ uschar * save_domain = deliver_domain;
+
+ deliver_localpart = expand_string(
+ string_sprintf("${local_part:%s}", new->address));
+ deliver_domain = expand_string(
+ string_sprintf("${domain:%s}", new->address));
+
+ (void) tpda_raise_event(delivery_event_action,
+ US"msg:fail:internal", new->message);
+
+ deliver_localpart = save_local;
+ deliver_domain = save_domain;
+ }
+#endif
}
}
}
/* 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);
+#endif
+}
/* If there are deferred addresses, we are keeping this message because it is
not yet completed. Lose any temporary files that were catching output from
#ifdef EXPERIMENTAL_TPDA
int tpda_defer_errno = 0;
-uschar *tpda_event = NULL;
-uschar *tpda_data = NULL;
+uschar *tpda_event = NULL; /* event name */
+uschar *tpda_data = NULL; /* auxilary data for event */
+uschar *delivery_event_action = NULL; /* expansion for delivery events */
#endif
transport_instance *transports = NULL;
#ifdef EXPERIMENTAL_TPDA
extern int tpda_defer_errno; /* error number set when a remote delivery is deferred with a host error */
extern uschar *tpda_event; /* event classification */
-extern uschar *tpda_data;; /* event data */
+extern uschar *tpda_data; /* event data */
+extern uschar *delivery_event_action; /* expansion for delivery events */
#endif
extern uschar *transport_name; /* Name of transport last started */
{ "deliver_drop_privilege", opt_bool, &deliver_drop_privilege },
{ "deliver_queue_load_max", opt_fixed, &deliver_queue_load_max },
{ "delivery_date_remove", opt_bool, &delivery_date_remove },
+#ifdef EXPERIMENTAL_TPDA
+ { "delivery_event_action", opt_stringptr, &delivery_event_action },
+#endif
#ifdef ENABLE_DISABLE_FSYNC
{ "disable_fsync", opt_bool, &disable_fsync },
#endif
acl_smtp_rcpt = accept
acl_smtp_data = accept
+delivery_event_action = ${acl {logger}}
+
# ----- ACL -----
[$host_address]:$host_port
logwrite = . banner <$tpda_data>
+ev_msg_fail:
+ accept condition = ${if eq {$tpda_event}{msg:fail:delivery}}
+ logwrite = . \
+ refused by fdqn <$host> \
+ local_part <$local_part> \
+ domain <$domain> \
+
+ accept logwrite = . \
+ local_part <$local_part> \
+ domain <$domain> \
+ reason <$tpda_data>
+
ev_msg:
- accept condition = ${if !eq {$acl_arg2}{domain1}}
+ accept condition = ${if eq {fail} {${listextract{2}{$tpda_event}}}}
+ acl = ev_msg_fail
+
+ accept condition = ${if eq {$tpda_event}{msg:complete}}
+ logwrite = . finished: $message_exim_id
+
+ accept condition = ${if !eq {$domain}{domain1}}
logwrite = $this_expansion_will_fail
- accept condition = ${if eq {$acl_arg1}{msg:delivery}}
+ accept condition = ${if eq {$tpda_event}{msg:delivery}}
logwrite = . \
delivery \
ip <$host_address> \
router <$router_name> \
transport <$transport_name>
- accept condition = ${if eq {$acl_arg1}{msg:host:defer}}
+ accept condition = ${if eq {$tpda_event}{msg:host:defer}}
logwrite = . \
deferral \
ip <$host_address> \
accept condition = ${if eq {smtp} {${listextract{1}{$tpda_event}}}}
acl = ev_smtp
accept condition = ${if eq {msg} {${listextract{1}{$tpda_event}}}}
- acl = ev_msg $tpda_event $acl_arg2
+ acl = ev_msg
# ----- Routers -----
port = PORT_S
command_timeout = 1s
final_timeout = 1s
- tpda_event_action = ${acl {logger} {$tpda_event} {$domain} }
+ tpda_event_action = ${acl {logger}}
# End
1999-03-02 09:44:33 10HmaY-0005vi-00 event msg:delivery
1999-03-02 09:44:33 10HmaY-0005vi-00 . delivery ip <127.0.0.1> port <1224> fqdn <127.0.0.1> local_part <userx> domain <domain1> confirmation <250 OK> router <others> transport <smtp>
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaY-0005vi-00 event msg:complete
+1999-03-02 09:44:33 10HmaY-0005vi-00 . finished: 10HmaY-0005vi-00
1999-03-02 09:44:33 End queue run: pid=pppp -qqf
1999-03-02 09:44:33 10HmaX-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 10HmaX-0005vi-00 failed to expand tpda_event_action msg:delivery in smtp: error from acl "logger"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaX-0005vi-00 event msg:complete
+1999-03-02 09:44:33 10HmaX-0005vi-00 . finished: 10HmaX-0005vi-00
1999-03-02 09:44:33 End queue run: pid=pppp -qqf
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmaZ-0005vi-00 event tcp:connect
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 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 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
+1999-03-02 09:44:33 10HmbB-0005vi-00 . [127.0.0.1]:-1
+1999-03-02 09:44:33 10HmbB-0005vi-00 event smtp:connect
+1999-03-02 09:44:33 10HmbB-0005vi-00 . [127.0.0.1] -> [127.0.0.1]:1224
+1999-03-02 09:44:33 10HmbB-0005vi-00 . banner <220 ESMTP>
+1999-03-02 09:44:33 10HmbB-0005vi-00 event tcp:close
+1999-03-02 09:44:33 10HmbB-0005vi-00 . [127.0.0.1] -> [127.0.0.1]:1224
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** userx@domain1 R=others T=smtp: SMTP error from remote mail server after RCPT TO:<userx@domain1>: host 127.0.0.1 [127.0.0.1]: 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 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 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
-# Arbtirary expansion after transport
+# Arbitrary expansion after transport
# (EXPERIMENTAL_TPDA)
#
need_ipv4
.
****
#
+#
+#
+#
+#
+exim -odq userx@domain1
+A message which will get refused
+****
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250 HELP
+MAIL
+250 OK
+RCPT
+550 GO AWAY
+QUIT
+220 OK
+****
+exim -qqf
+****
+#
+#
+#
+#
+exim -odq userx@domain1
+A message we will cancel from the queue
+****
+exim -odi -Mg $msg1
+****
EHLO the.local.host.name
*sleep 4
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:<CALLER@the.local.host.name>
+250 OK
+RCPT TO:<userx@domain1>
+550 GO AWAY
+QUIT
+220 OK
+End of script