Expand max_rcpt option on smtp transport. Bug 2946
authorJeremy Harris <jgh146exb@wizmail.org>
Fri, 23 Dec 2022 18:02:25 +0000 (18:02 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Fri, 23 Dec 2022 18:07:57 +0000 (18:07 +0000)
12 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/deliver.c
src/src/functions.h
src/src/globals.c
src/src/macros.h
src/src/structs.h
src/src/transports/smtp.c
test/confs/0285
test/log/0285
test/scripts/0000-Basic/0285
test/stdout/0285

index cdac2a266e287e9094689bccb5d689e7740167e9..946f55b1130e4bf2b31df791c40c2a53aca7b993 100644 (file)
@@ -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
index 0d4557a8b89ac1a368f8f50413f5c05663af8226..b00399511557da1a415a13d3175762032c82b39f 100644 (file)
@@ -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
 ------------
index c5e00eaef480a5087fd413dc41374502c6a2974f..ca31df5872329c50fca7f94d0c2d8e5d4a857b2d 100644 (file)
@@ -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);
 
 
   /************************************************************************/
index 3ca346c04df4aa6b881e7159b8e48677fa055413..1817144ead49f724ad819d68cb2e0311bf999c8b 100644 (file)
@@ -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 */
index e5b72592febf9aa774da11b5a6b9b8b74a97f752..efe34902a2586bb137913a2549e0faee26c3ef44 100644 (file)
@@ -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),
index a631877a151a38986799aa5e34c96e6b9adea5df..585067fc9ea59c4ed69cd6b714145435571ea9b5 100644 (file)
@@ -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 */
index e1d93a9431e397fb4792f00c158fa298c8bcaacf..eae66e88de5922d55ab56fbde466deed88857b61 100644 (file)
@@ -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 */
index ed5f83b3ee939c294209909abe354fdb007e10c8..c5951832bd851d3404a68c22144e2d1795090087 100644 (file)
@@ -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
 
index 8b0ada1f1ae5d7a338758a15ab65cfec161b040e..20ec0263aeb345fad8bef5ac8ae96e3944382621 100644 (file)
@@ -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
 
 
index 7828219ce2ba7db333f18429ce7c95873f62f247..4da1f42dccdd3c418a4c9bca16f6843a2337dfbc 100644 (file)
@@ -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@test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbB-0005vi-00 => x@magic1.test.ex 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@magic1.test.ex 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
index 1ecc64202c127cde5dea66275a1b978515ab088c..976058fa4f04d96fee30ccde41455ea267345302 100644 (file)
@@ -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@magic1.test.ex y@magic1.test.ex
+****
index 256a650707cac191a8380491ca4bb3011f5a5543..de6245c6dc9616eb911c1047b100ce5ef3117c86 100644 (file)
@@ -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@test.ex>
+250 Sender OK
+RCPT TO:<x@magic1.test.ex>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <CALLER@test.ex>)
+       id 10HmbB-0005vi-00;
+       Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbB-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+.
+250 OK
+MAIL FROM:<CALLER@test.ex>
+250 Sender OK
+RCPT TO:<y@magic1.test.ex>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <CALLER@test.ex>)
+       id 10HmbB-0005vi-00;
+       Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbB-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+.
+250 OK
+QUIT
+250 OK
+End of script