From 506900aff65e12440fdd36a71e9172fc7af5830a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 16 Nov 2014 17:47:50 +0000 Subject: [PATCH] Make the multi_domain smtp transport option expanded --- doc/doc-docbook/spec.xfpt | 5 ++- doc/doc-txt/ChangeLog | 2 + src/src/deliver.c | 61 +++++++++++++++++--------- src/src/globals.c | 1 + src/src/structs.h | 1 + src/src/transports/smtp.c | 4 +- test/confs/0570 | 45 +++++++++++++++++++ test/log/0570 | 83 ++++++++++++++++++++++++++++++++++++ test/rejectlog/0570 | 13 ++++++ test/scripts/0000-Basic/0570 | 66 ++++++++++++++++++++++++++++ 10 files changed, 259 insertions(+), 22 deletions(-) create mode 100644 test/confs/0570 create mode 100644 test/log/0570 create mode 100644 test/rejectlog/0570 create mode 100644 test/scripts/0000-Basic/0570 diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index c6aeea145..0047f6bde 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -23224,7 +23224,7 @@ so can cause parallel connections to the same host if &%remote_max_parallel%& permits this. -.option multi_domain smtp boolean true +.option multi_domain smtp boolean&!! true .vindex "&$domain$&" When this option is set, the &(smtp)& transport can handle a number of addresses containing a mixture of different domains provided they all resolve @@ -23233,6 +23233,9 @@ handling only one domain at a time. This is useful if you want to use &$domain$& in an expansion for the transport, because it is set only when there is a single domain involved in a remote delivery. +It is expanded per-address and can depend on any of +&$address_data$&, &$domain_data$&, &$local_part_data$&, +&$host$&, &$host_address$& and &$host_port$&. .option port smtp string&!! "see below" .cindex "port" "sending TCP/IP" diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index ae2b84dd0..768d872e1 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -7,6 +7,8 @@ Exim version 4.86 JH/01 Bug 1545: The smtp transport option "retry_include_ip_address" is now expanded. +JH/02 The smtp transport option "multi_domain" is now expanded. + Exim version 4.85 ----------------- diff --git a/src/src/deliver.c b/src/src/deliver.c index d33cf799a..5000f1cbc 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -3844,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. */ @@ -3915,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; @@ -3944,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 diff --git a/src/src/globals.c b/src/src/globals.c index fb705d9d8..f7c67d76f 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1356,6 +1356,7 @@ transport_instance transport_defaults = { NULL, /* batch_id */ NULL, /* home_dir */ NULL, /* current_dir */ + NULL, /* expand-multi-domain */ TRUE, /* multi-domain */ FALSE, /* overrides_hosts */ 100, /* max_addresses */ diff --git a/src/src/structs.h b/src/src/structs.h index 259d9af71..2250bbbde 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -148,6 +148,7 @@ typedef struct transport_instance { uschar *home_dir; /* ) Used only for local transports */ uschar *current_dir; /* ) */ /**************************************/ + uschar *expand_multi_domain; /* ) */ BOOL multi_domain; /* ) */ BOOL overrides_hosts; /* ) Used only for remote transports */ int max_addresses; /* ) */ diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 33d357f7a..69bbc4d0c 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -19,6 +19,8 @@ before the lower case letters). Some live in the transport_instance block so as to be publicly visible; these are flagged with opt_public. */ optionlist smtp_transport_options[] = { + { "*expand_multi_domain", opt_stringptr | opt_hidden | opt_public, + (void *)offsetof(transport_instance, expand_multi_domain) }, { "*expand_retry_include_ip_address", opt_stringptr | opt_hidden, (void *)(offsetof(smtp_transport_options_block, expand_retry_include_ip_address)) }, @@ -145,7 +147,7 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, lmtp_ignore_quota) }, { "max_rcpt", opt_int | opt_public, (void *)offsetof(transport_instance, max_addresses) }, - { "multi_domain", opt_bool | opt_public, + { "multi_domain", opt_expand_bool | opt_public, (void *)offsetof(transport_instance, multi_domain) }, { "port", opt_stringptr, (void *)offsetof(smtp_transport_options_block, port) }, diff --git a/test/confs/0570 b/test/confs/0570 new file mode 100644 index 000000000..4c5e5dc06 --- /dev/null +++ b/test/confs/0570 @@ -0,0 +1,45 @@ +# Exim test configuration 0570 +# multi_domain option on smtp transport + +OPTION = + +exim_path = EXIM_PATH +host_lookup_order = bydns +rfc1413_query_timeout = 0s +spool_directory = DIR/spool +log_file_path = DIR/spool/log/%slog +gecos_pattern = "" +gecos_name = CALLER_NAME + +# ----- Main settings ----- + +primary_hostname = primary.test.ex +qualify_domain = test.ex +queue_only +queue_run_in_order + + +# for server +acl_smtp_rcpt= discard + +# ----- Routers ----- + +begin routers + +all: + driver = manualroute +address_data = $domain + route_list = * 127.0.0.1 byname + self = send + transport = smtp + +# ----- Transports ----- + +begin transports + +smtp: + driver = smtp + port = PORT_D + OPTION + +# End diff --git a/test/log/0570 b/test/log/0570 new file mode 100644 index 000000000..53ba80a61 --- /dev/null +++ b/test/log/0570 @@ -0,0 +1,83 @@ +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmaY-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmaY-0005vi-00 Completed +1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaY-0005vi-00" +1999-03-02 09:44:33 10HmaX-0005vi-00 -> usery@domb.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaY-0005vi-00" +1999-03-02 09:44:33 10HmaX-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaZ-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbA-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbA-0005vi-00 Completed +1999-03-02 09:44:33 10HmaZ-0005vi-00 => userx@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbA-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 -> usery@domb.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbA-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbB-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbC-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbC-0005vi-00 Completed +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbB-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbD-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbD-0005vi-00 Completed +1999-03-02 09:44:33 10HmbB-0005vi-00 => userx@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmbB-0005vi-00 => usery@domb.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbD-0005vi-00" +1999-03-02 09:44:33 10HmbB-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbE-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbF-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbF-0005vi-00 Completed +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbE-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbG-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbG-0005vi-00 Completed +1999-03-02 09:44:33 10HmbE-0005vi-00 => userx@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbF-0005vi-00" +1999-03-02 09:44:33 10HmbE-0005vi-00 => usery@domb.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbG-0005vi-00" +1999-03-02 09:44:33 10HmbE-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbH-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbI-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbI-0005vi-00 Completed +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbH-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbJ-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbJ-0005vi-00 Completed +1999-03-02 09:44:33 10HmbH-0005vi-00 => userx@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbI-0005vi-00" +1999-03-02 09:44:33 10HmbH-0005vi-00 => usery@domb.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbJ-0005vi-00" +1999-03-02 09:44:33 10HmbH-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbK-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbL-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbL-0005vi-00 Completed +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@test.ex H=localhost (primary.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmbK-0005vi-00@primary.test.ex +1999-03-02 09:44:33 10HmbM-0005vi-00 => blackhole (RCPT ACL discarded recipients) +1999-03-02 09:44:33 10HmbM-0005vi-00 Completed +1999-03-02 09:44:33 10HmbK-0005vi-00 => userx@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-0005vi-00" +1999-03-02 09:44:33 10HmbK-0005vi-00 -> usery@doma.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-0005vi-00" +1999-03-02 09:44:33 10HmbK-0005vi-00 => userz@domc.ex R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbM-0005vi-00" +1999-03-02 09:44:33 10HmbK-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp diff --git a/test/rejectlog/0570 b/test/rejectlog/0570 new file mode 100644 index 000000000..d179df73b --- /dev/null +++ b/test/rejectlog/0570 @@ -0,0 +1,13 @@ +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL +1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F= rejected RCPT : discarded by RCPT ACL diff --git a/test/scripts/0000-Basic/0570 b/test/scripts/0000-Basic/0570 new file mode 100644 index 000000000..ed54afc1d --- /dev/null +++ b/test/scripts/0000-Basic/0570 @@ -0,0 +1,66 @@ +# multi_domain option on smtp transport +# +# +exim -DSERVER=server -bd -oX PORT_D +**** +# +exim userx@domA.ex usery@domB.ex +Test message +**** +# Default case: can multi-domain +exim -q +**** +# +# +exim userx@domA.ex usery@domB.ex +Test message +**** +# Equivalent explicit case: can multi-domain +exim -DOPTION=multi_domain=yes -q +**** +# +# +exim userx@domA.ex usery@domB.ex +Test message +**** +# no multi-domain +exim -DOPTION=multi_domain=no -q +# +# +exim userx@domA.ex usery@domB.ex +Test message +**** +# Expanded case: can multi-domain +exim -DOPTION='multi_domain=${if bool{1} {true}{false}}' -q +**** +# +# +exim userx@domA.ex usery@domB.ex +Test message +**** +# Expanded case: no multi-domain (1) +exim -DOPTION='multi_domain=${if eqi {$address_data}{domA.ex} {no}{yes}}' -q +**** +# +# +exim userx@domA.ex usery@domB.ex +Test message +**** +# Expanded case: no multi-domain (2) +exim -DOPTION='multi_domain=${if match_domain {$address_data}{domZ.ex : domY.ex : domB.ex} {no}{yes}}' -q +**** +# +# +exim userx@domA.ex usery@domA.ex userz@domC.ex +Test message +**** +# Expanded case: both yes and no +exim -DOPTION='multi_domain=${if eqi {$address_data}{domA.ex} {no}{yes}}' -q +**** +# +# +killdaemon +no_msglog_check +# +# +## -- 2.30.2