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
&$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"
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
-----------------
}
/* 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. */
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;
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
NULL, /* batch_id */
NULL, /* home_dir */
NULL, /* current_dir */
+ NULL, /* expand-multi-domain */
TRUE, /* multi-domain */
FALSE, /* overrides_hosts */
100, /* max_addresses */
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; /* ) */
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)) },
(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) },
--- /dev/null
+# 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
--- /dev/null
+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=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: 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=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: 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=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: 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=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: 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=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: 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=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: 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=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: 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=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: 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=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domA.ex>: 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=<CALLER@test.ex> rejected RCPT <userz@domC.ex>: 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
--- /dev/null
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domB.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userx@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <usery@domA.ex>: discarded by RCPT ACL
+1999-03-02 09:44:33 H=localhost (primary.test.ex) [127.0.0.1] F=<CALLER@test.ex> rejected RCPT <userz@domC.ex>: discarded by RCPT ACL
--- /dev/null
+# 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
+#
+#
+##