Gitweb:
https://git.exim.org/exim.git/commitdiff/0762e1a4d6de4b7b0206314302297c9dd6d7ae73
Commit: 0762e1a4d6de4b7b0206314302297c9dd6d7ae73
Parent: 02f746c26c113c1bd97cc25cc75797327eca9434
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Fri Dec 23 18:02:25 2022 +0000
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Fri Dec 23 18:07:57 2022 +0000
Expand max_rcpt option on smtp transport. Bug 2946
---
doc/doc-docbook/spec.xfpt | 20 +++++++++++++++-----
doc/doc-txt/NewStuff | 3 ++-
src/src/deliver.c | 12 ++++++++----
src/src/functions.h | 10 +++++++++-
src/src/globals.c | 2 +-
src/src/macros.h | 4 ++++
src/src/structs.h | 2 +-
src/src/transports/smtp.c | 12 +++++++-----
test/confs/0285 | 15 +++++++++++----
test/log/0285 | 4 ++++
test/scripts/0000-Basic/0285 | 29 +++++++++++++++++++++++++++++
test/stdout/0285 | 41 +++++++++++++++++++++++++++++++++++++++++
12 files changed, 132 insertions(+), 22 deletions(-)
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index cdac2a266..946f55b11 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -22397,7 +22397,7 @@ its removal from incoming messages, so that delivered messages can safely be
resent to other recipients.
&*Note:*& If used on a transport handling multiple recipients
-(the smtp transport unless &%rcpt_max%& is 1, the appendfile, pipe or lmtp
+(the smtp transport unless &%max_rcpt%& is 1, the appendfile, pipe or lmtp
transport if &%batch_max%& is greater than 1)
then information about Bcc recipients will be leaked.
Doing so is generally not advised.
@@ -25778,12 +25778,22 @@ If this option is set true when the &%protocol%& option is set to &"lmtp"&, the
string &`IGNOREQUOTA`& is added to RCPT commands, provided that the LMTP server
has advertised support for IGNOREQUOTA in its response to the LHLO command.
-.option max_rcpt smtp integer 100
+.option max_rcpt smtp integer&!! 100
.cindex "RCPT" "maximum number of outgoing"
-This option limits the number of RCPT commands that are sent in a single
-SMTP message transaction. Each set of addresses is treated independently, and
+This option,
+.new
+after expansion,
+.wen
+limits the number of RCPT commands that are sent in a single
+SMTP message transaction.
+A value setting of zero disables the limit.
+
+.new
+If a constant is given,
+.wen
+each set of addresses is treated independently, and
so can cause parallel connections to the same host if &%remote_max_parallel%&
-permits this. A value setting of zero disables the limit.
+permits this.
.option message_linelength_limit smtp integer 998
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 0d4557a8b..b00399511 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -16,7 +16,8 @@ Version 4.97
3. Variable $sender_helo_verified with the result of an ACL "verify = helo".
4. Predefined macros for expansion items, operators, conditions and variables.
- 3. Variable $sender_helo_verified with the result of an ACL verify=helo.
+
+ 5. The smtp transport option "max_rcpt" is now expanded before use.
Version 4.96
------------
diff --git a/src/src/deliver.c b/src/src/deliver.c
index c5e00eaef..ca31df587 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -4290,10 +4290,14 @@ So look out for the place it gets used.
}
/* Get the maximum it can handle in one envelope, with zero meaning
- unlimited, which is forced for the MUA wrapper case. */
-
- address_count_max = tp->max_addresses;
- if (address_count_max == 0 || mua_wrapper) address_count_max = 999999;
+ unlimited, which is forced for the MUA wrapper case and if the
+ value could vary depending on the messages.
+ For those, we only split (below) by (tpt,dest,erraddr,hdrs) and rely on the
+ transport splitting further by max_rcp. So we potentially lose some
+ parallellism. */
+
+ address_count_max = mua_wrapper || Ustrchr(tp->max_addresses, '$')
+ ? UNLIMITED_ADDRS : expand_max_rcpt(tp->max_addresses);
/************************************************************************/
diff --git a/src/src/functions.h b/src/src/functions.h
index 3ca346c04..1817144ea 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -1307,6 +1307,14 @@ debug_printf("cmdlog: '%s'\n", client_cmd_log ? client_cmd_log->s : US"(unset)")
+static inline int
+expand_max_rcpt(const uschar * str_max_rcpt)
+{
+const uschar * s = expand_cstring(str_max_rcpt);
+int res;
+return !s || !*s || (res = Uatoi(s)) == 0 ? UNLIMITED_ADDRS : res;
+}
+
# endif /* !COMPILE_UTILITY */
/******************************************************************************/
@@ -1314,6 +1322,6 @@ debug_printf("cmdlog: '%s'\n", client_cmd_log ? client_cmd_log->s : US"(unset)")
#endif /* _FUNCTIONS_H_ */
-/* vi: aw
+/* vi: aw ai sw=2
*/
/* End of functions.h */
diff --git a/src/src/globals.c b/src/src/globals.c
index e5b72592f..efe34902a 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1592,7 +1592,7 @@ transport_instance transport_defaults = {
/* All non-mentioned elements zero/NULL/FALSE */
.batch_max = 1,
.multi_domain = TRUE,
- .max_addresses = 100,
+ .max_addresses = US"100",
.connection_max_messages = 500,
.uid = (uid_t)(-1),
.gid = (gid_t)(-1),
diff --git a/src/src/macros.h b/src/src/macros.h
index a631877a1..585067fc9 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -1136,4 +1136,8 @@ typedef unsigned mcs_flags;
#else
# define EXIM_NOFOLLOW 0
#endif
+
+/* A big number for (effectively) unlimited envelope addresses */
+#define UNLIMITED_ADDRS 999999
+
/* End of macros.h */
diff --git a/src/src/structs.h b/src/src/structs.h
index e1d93a943..eae66e88d 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -183,7 +183,7 @@ typedef struct transport_instance {
uschar *expand_multi_domain; /* ) */
BOOL multi_domain; /* ) */
BOOL overrides_hosts; /* ) Used only for remote transports */
- int max_addresses; /* ) */
+ uschar *max_addresses; /* ) */
int connection_max_messages;/* ) */
/**************************************/
BOOL deliver_as_creator; /* Used only by pipe at present */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index ed5f83b3e..c5951832b 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -114,7 +114,7 @@ optionlist smtp_transport_options[] = {
{ "interface", opt_stringptr, LOFF(interface) },
{ "keepalive", opt_bool, LOFF(keepalive) },
{ "lmtp_ignore_quota", opt_bool, LOFF(lmtp_ignore_quota) },
- { "max_rcpt", opt_int | opt_public,
+ { "max_rcpt", opt_stringptr | opt_public,
OPT_OFF(transport_instance, max_addresses) },
{ "message_linelength_limit", opt_int, LOFF(message_linelength_limit) },
{ "multi_domain", opt_expand_bool | opt_public,
@@ -2121,8 +2121,9 @@ sx->dane_required =
verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK;
#endif
-if ((sx->max_mail = sx->conn_args.tblock->connection_max_messages) == 0) sx->max_mail = 999999;
-if ((sx->max_rcpt = sx->conn_args.tblock->max_addresses) == 0) sx->max_rcpt = 999999;
+if ((sx->max_mail = sx->conn_args.tblock->connection_max_messages) == 0)
+ sx->max_mail = UNLIMITED_ADDRS;
+sx->max_rcpt = expand_max_rcpt(sx->conn_args.tblock->max_addresses);
sx->igquotstr = US"";
if (!sx->helo_data) sx->helo_data = ob->helo_data;
@@ -2819,8 +2820,9 @@ if (tls_out.active.sock >= 0)
#ifdef EXPERIMMENTAL_ESMTP_LIMITS
/* As we are about to send another EHLO, forget any LIMITS received so far. */
sx->peer_limit_mail = sx->peer_limit_rcpt = sx->peer_limit_rcptdom = 0;
- if ((sx->max_mail = sx->conn_args.tblock->connection_max_message) == 0) sx->max_mail = 999999;
- if ((sx->max_rcpt = sx->conn_args.tblock->max_addresses) == 0) sx->max_rcpt = 999999;
+ if ((sx->max_mail = sx->conn_args.tblock->connection_max_message) == 0)
+ sx->max_mail = UNLIMITED_ADDRS;
+ sx->max_rcpt = expand_max_rcpt(sx->conn_args.tblock->max_addresses);
sx->single_rcpt_domain = FALSE;
#endif
diff --git a/test/confs/0285 b/test/confs/0285
index 8b0ada1f1..20ec0263a 100644
--- a/test/confs/0285
+++ b/test/confs/0285
@@ -23,7 +23,7 @@ all:
driver = manualroute
route_list = * 127.0.0.1 byname
self = send
- transport = smtp
+ transport = ${if eq {$domain}{test.ex} {smtp}{magic_smtp}}
# ----- Transports -----
@@ -31,10 +31,17 @@ all:
begin transports
smtp:
- driver = smtp
- port = PORT_S
+ driver = smtp
+ port = PORT_S
hosts_try_fastopen = :
- max_rcpt = 2
+ max_rcpt = 2
+ connection_max_messages = 3
+
+magic_smtp:
+ driver = smtp
+ port = PORT_S
+ hosts_try_fastopen = :
+ max_rcpt = ${if match {$domain}{magic(\\d+)} {$1} {2}}
connection_max_messages = 3
diff --git a/test/log/0285 b/test/log/0285
index 7828219ce..4da1f42dc 100644
--- a/test/log/0285
+++ b/test/log/0285
@@ -26,3 +26,7 @@
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
1999-03-02 09:44:33 End queue run: pid=p1235
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbB-0005vi-00 => x@??? R=all T=magic_smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbB-0005vi-00 => y@??? R=all T=magic_smtp H=127.0.0.1 [127.0.0.1]* C="250 OK"
+1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
diff --git a/test/scripts/0000-Basic/0285 b/test/scripts/0000-Basic/0285
index 1ecc64202..976058fa4 100644
--- a/test/scripts/0000-Basic/0285
+++ b/test/scripts/0000-Basic/0285
@@ -100,3 +100,32 @@ QUIT
****
exim -odi -q
****
+#
+# Extended version of pulling a max_rcpt out of an expansion
+# Expect log with two => lines on one conn
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250 HELP
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -odf x@??? y@???
+****
diff --git a/test/stdout/0285 b/test/stdout/0285
index 256a65070..de6245c6d 100644
--- a/test/stdout/0285
+++ b/test/stdout/0285
@@ -133,3 +133,44 @@ Date: Tue, 2 Mar 1999 09:44:33 +0000
QUIT
250 OK
End of script
+Listening on port 1224 ...
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO myhost.test.ex
+250-OK
+250 HELP
+MAIL FROM:<CALLER@???>
+250 Sender OK
+RCPT TO:<x@???>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@???>)
+ id 10HmbB-0005vi-00;
+ Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbB-0005vi-00@???>
+From: CALLER_NAME <CALLER@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+.
+250 OK
+MAIL FROM:<CALLER@???>
+250 Sender OK
+RCPT TO:<y@???>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@???>)
+ id 10HmbB-0005vi-00;
+ Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbB-0005vi-00@???>
+From: CALLER_NAME <CALLER@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+.
+250 OK
+QUIT
+250 OK
+End of script