Gitweb:
https://git.exim.org/exim.git/commitdiff/cd19f9a79c20f9c0c9d650a8aa21d9cc54a66620
Commit: cd19f9a79c20f9c0c9d650a8aa21d9cc54a66620
Parent: a173a4376d168edbf3fe2494dff998c4060bf425
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Sun Feb 11 23:32:34 2024 +0000
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Tue Feb 13 18:32:04 2024 +0000
Expand recipients_max
---
doc/doc-docbook/spec.xfpt | 14 ++++++++++++--
doc/doc-txt/NewStuff | 2 ++
doc/doc-txt/OptionLists.txt | 2 +-
src/src/exim.c | 30 ++++++++++++++++++++++--------
src/src/globals.c | 3 ++-
src/src/globals.h | 3 ++-
src/src/moan.c | 2 +-
src/src/readconf.c | 2 +-
src/src/receive.c | 8 +++++---
src/src/smtp_in.c | 16 +++++++++++-----
test/confs/0289 | 4 ++++
test/log/0289 | 7 +++++++
test/log/4710 | 2 ++
test/mail/0289.CALLER | 21 +++++++++++++++++++++
test/mail/0289.userx | 10 ++++++++++
test/mail/0289.usery | 10 ++++++++++
test/scripts/0000-Basic/0289 | 11 +++++++++++
test/scripts/4710-esmtp-limits/4710 | 23 +++++++++++++++++++++++
test/stdout/4710 | 26 ++++++++++++++++++++++++++
19 files changed, 173 insertions(+), 23 deletions(-)
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 902f8e72f..316860aae 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -17472,16 +17472,26 @@ or if the message was submitted locally (not using TCP/IP), and the &%-bnq%&
option was not set.
-.option recipients_max main integer 50000
+.option recipients_max main integer&!! 50000
.cindex "limit" "number of recipients"
.cindex "recipient" "maximum number"
-If this option is set greater than zero, it specifies the maximum number of
+If the value resulting from expanding this option
+is set greater than zero, it specifies the maximum number of
original recipients for any message. Additional recipients that are generated
by aliasing or forwarding do not count. SMTP messages get a 452 response for
all recipients over the limit; earlier recipients are delivered as normal.
Non-SMTP messages with too many recipients are failed, and no deliveries are
done.
+.new
+For SMTP message the expansion is done after the connection is
+accepted (but before any SMTP conversation) and may depend on
+the IP addresses and port numbers of the connection.
+&*Note*&: If an expansion is used for the option,
+care should be taken that a resonable value results for
+non-SMTP messages.
+.wen
+
.cindex "RCPT" "maximum number of incoming"
&*Note*&: The RFCs specify that an SMTP server should accept at least 100
RCPT commands in a single message.
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index ad385b9ec..2439b3137 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -16,6 +16,8 @@ Version 4.98
timestamp but no extiry timestamp. Code by Simon Arlott; testsuite
additions by jgh.
+ 4. The recipients_max main option is now expanded.
+
Version 4.97
------------
diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt
index 4d7117697..987f096ba 100644
--- a/doc/doc-txt/OptionLists.txt
+++ b/doc/doc-txt/OptionLists.txt
@@ -475,7 +475,7 @@ receive_timeout time 0s main
received_header_text string* + main
received_headers_max integer 30 main
recipient_unqualified_hosts host list unset main 4.00 replacing receiver_unqualified_hosts
-recipients_max integer 50000 main 1.60 default changed in 4.95 (was 0)
+recipients_max integer* 50000 main 1.60 default changed in 4.95 (was 0)
recipients_max_reject boolean false main 1.70
redirect_router string unset routers 4.00
remote_max_parallel integer 1 main
diff --git a/src/src/exim.c b/src/src/exim.c
index 1f76f8f14..10fc98963 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -5339,6 +5339,7 @@ if (expansion_test)
else if (expansion_test_message)
{
+ uschar * rme = expand_string(recipients_max);
int save_stdin = dup(0);
int fd = Uopen(expansion_test_message, O_RDONLY, 0);
if (fd < 0)
@@ -5347,6 +5348,7 @@ if (expansion_test)
(void) dup2(fd, 0);
filter_test = FTEST_USER; /* Fudge to make it look like filter test */
message_ended = END_NOTENDED;
+ recipients_max_expanded = atoi(CCS rme);
read_message_body(receive_msg(extract_recipients));
message_linecount += body_linecount;
(void)dup2(save_stdin, 0);
@@ -5753,8 +5755,8 @@ for (BOOL more = TRUE; more; )
int rc;
if ((rc = smtp_setup_msg()) > 0)
{
- if (real_sender_address != NULL &&
- !receive_check_set_sender(sender_address))
+ if ( real_sender_address
+ && !receive_check_set_sender(sender_address))
{
sender_address = raw_sender = real_sender_address;
sender_address_unrewritten = NULL;
@@ -5801,10 +5803,12 @@ for (BOOL more = TRUE; more; )
else
{
- int rcount = 0;
- int count = argc - recipients_arg;
+ uschar * rme = expand_string(recipients_max);
+ int rcount = 0, count = argc - recipients_arg;
const uschar ** list = argv + recipients_arg;
+ recipients_max_expanded = atoi(CCS rme);
+
/* These options cannot be changed dynamically for non-SMTP messages */
f.active_local_sender_retain = local_sender_retain;
@@ -5831,15 +5835,19 @@ for (BOOL more = TRUE; more; )
while (*s)
{
BOOL finished = FALSE;
- uschar *recipient;
- uschar *ss = parse_find_address_end(s, FALSE);
+ uschar * recipient;
+ uschar * ss = parse_find_address_end(s, FALSE);
if (*ss == ',') *ss = 0; else finished = TRUE;
/* Check max recipients - if -t was used, these aren't recipients */
- if (recipients_max > 0 && ++rcount > recipients_max &&
- !extract_recipients)
+ if ( recipients_max_expanded > 0 && ++rcount > recipients_max_expanded
+ && !extract_recipients)
+ {
+ DEBUG(D_all) debug_printf("excess reipients (max %d)\n",
+ recipients_max_expanded);
+
if (error_handling == ERRORS_STDERR)
{
fprintf(stderr, "exim: too many recipients\n");
@@ -5849,6 +5857,7 @@ for (BOOL more = TRUE; more; )
return
moan_to_sender(ERRMESS_TOOMANYRECIP, NULL, NULL, stdin, TRUE)?
errors_sender_rc : EXIT_FAILURE;
+ }
#ifdef SUPPORT_I18N
{
@@ -5873,6 +5882,10 @@ for (BOOL more = TRUE; more; )
}
if (!recipient)
+ {
+ DEBUG(D_all) debug_printf("bad recipient address \"%s\": %s\n",
+ string_printing(list[i]), errmess);
+
if (error_handling == ERRORS_STDERR)
{
fprintf(stderr, "exim: bad recipient address \"%s\": %s\n",
@@ -5889,6 +5902,7 @@ for (BOOL more = TRUE; more; )
moan_to_sender(ERRMESS_BADARGADDRESS, &eblock, NULL, stdin, TRUE)?
errors_sender_rc : EXIT_FAILURE;
}
+ }
receive_add_recipient(string_copy_taint(recipient, GET_TAINTED), -1);
s = ss;
diff --git a/src/src/globals.c b/src/src/globals.c
index c483ab182..4af8668f0 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1322,7 +1322,8 @@ uschar *recipient_verify_failure = NULL;
int recipients_count = 0;
recipient_item *recipients_list = NULL;
int recipients_list_max = 0;
-int recipients_max = 50000;
+uschar *recipients_max = US"50000";
+int recipients_max_expanded= 0;
const pcre2_code *regex_AUTH = NULL;
const pcre2_code *regex_check_dns_names = NULL;
const pcre2_code *regex_From = NULL;
diff --git a/src/src/globals.h b/src/src/globals.h
index b5c3a520e..427590050 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -895,7 +895,8 @@ extern uschar *recipient_data; /* lookup data for recipients */
extern uschar *recipient_unqualified_hosts; /* Permitted unqualified recipients */
extern uschar *recipient_verify_failure; /* What went wrong */
extern int recipients_list_max; /* Maximum number fitting in list */
-extern int recipients_max; /* Max permitted */
+extern uschar *recipients_max; /* Max permitted */
+extern int recipients_max_expanded;
extern BOOL recipients_max_reject; /* If TRUE, reject whole message */
extern const pcre2_code *regex_AUTH; /* For recognizing AUTH settings */
extern const pcre2_code *regex_check_dns_names; /* For DNS name checking */
diff --git a/src/src/moan.c b/src/src/moan.c
index c2e38d4f7..a3c8e0aba 100644
--- a/src/src/moan.c
+++ b/src/src/moan.c
@@ -561,7 +561,7 @@ switch(ident)
case ERRMESS_TOOMANYRECIP:
log_write(0, LOG_MAIN, "%s: too many recipients (max set to %d)", msg,
- recipients_max);
+ recipients_max_expanded);
break;
case ERRMESS_LOCAL_SCAN:
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 8ee6e9fe0..5b486d0b6 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -293,7 +293,7 @@ static optionlist optionlist_config[] = {
{ "received_header_text", opt_stringptr, {&received_header_text} },
{ "received_headers_max", opt_int, {&received_headers_max} },
{ "recipient_unqualified_hosts", opt_stringptr, {&recipient_unqualified_hosts} },
- { "recipients_max", opt_int, {&recipients_max} },
+ { "recipients_max", opt_stringptr, {&recipients_max} },
{ "recipients_max_reject", opt_bool, {&recipients_max_reject} },
#ifdef LOOKUP_REDIS
{ "redis_servers", opt_stringptr, {&redis_servers} },
diff --git a/src/src/receive.c b/src/src/receive.c
index ae4203e7f..990b9c22e 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -1204,6 +1204,8 @@ static void
give_local_error(int errcode, uschar *text1, uschar *text2, int error_rc,
FILE *f, header_line *hptr)
{
+DEBUG(D_all) debug_printf("%s%s\n", text2, text1);
+
if (error_handling == ERRORS_SENDER)
{
error_block eblock;
@@ -2622,12 +2624,12 @@ if (extract_recip)
if ((h->type == htype_to || h->type == htype_cc || h->type == htype_bcc) &&
(!contains_resent_headers || strncmpic(h->text, US"resent-", 7) == 0))
{
- uschar *s = Ustrchr(h->text, ':') + 1;
+ uschar * s = Ustrchr(h->text, ':') + 1;
while (isspace(*s)) s++;
f.parse_allow_group = TRUE; /* Allow address group syntax */
- while (*s != 0)
+ while (*s)
{
uschar *ss = parse_find_address_end(s, FALSE);
uschar *recipient, *errmess, *pp;
@@ -2635,7 +2637,7 @@ if (extract_recip)
/* Check on maximum */
- if (recipients_max > 0 && ++rcount > recipients_max)
+ if (recipients_max_expanded > 0 && ++rcount > recipients_max_expanded)
give_local_error(ERRMESS_TOOMANYRECIP, US"too many recipients",
US"message rejected: ", error_rc, stdin, NULL);
/* Does not return */
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index a57c9821e..1d4c232a5 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -1879,7 +1879,7 @@ while (done <= 0)
if (recipients_max > 0 && recipients_count + 1 > recipients_max)
/* The function moan_smtp_batch() does not return. */
moan_smtp_batch(smtp_cmd_buffer, "%s too many recipients",
- recipients_max_reject? "552": "452");
+ recipients_max_reject ? "552": "452");
/* Apply SMTP rewrite, then extract address. Don't allow "<>" as a
recipient address */
@@ -2540,6 +2540,11 @@ if (!f.sender_host_unknown)
fl.helo_accept_junk = verify_check_host(&helo_accept_junk_hosts) == OK;
}
+/* Expand recipients_max, if needed */
+ {
+ uschar * rme = expand_string(recipients_max);
+ recipients_max_expanded = atoi(CCS rme);
+ }
/* For batch SMTP input we are now done. */
if (smtp_batched_input) return TRUE;
@@ -4055,14 +4060,14 @@ while (done <= 0)
}
#ifndef DISABLE_ESMTP_LIMITS
- if ( (smtp_mailcmd_max > 0 || recipients_max)
+ if ( (smtp_mailcmd_max > 0 || recipients_max_expanded > 0)
&& verify_check_host(&limits_advertise_hosts) == OK)
{
g = string_fmt_append(g, "%.3s-LIMITS", smtp_code);
if (smtp_mailcmd_max > 0)
g = string_fmt_append(g, " MAILMAX=%d", smtp_mailcmd_max);
- if (recipients_max)
- g = string_fmt_append(g, " RCPTMAX=%d", recipients_max);
+ if (recipients_max > 9)
+ g = string_fmt_append(g, " RCPTMAX=%d", recipients_max_expanded);
g = string_catn(g, US"\r\n", 2);
}
#endif
@@ -4900,7 +4905,8 @@ while (done <= 0)
/* Check maximum allowed */
- if (rcpt_count+1 < 0 || rcpt_count > recipients_max && recipients_max > 0)
+ if ( rcpt_count+1 < 0
+ || rcpt_count > recipients_max_expanded && recipients_max_expanded > 0)
{
if (recipients_max_reject)
{
diff --git a/test/confs/0289 b/test/confs/0289
index 44e40a528..a96799690 100644
--- a/test/confs/0289
+++ b/test/confs/0289
@@ -8,7 +8,11 @@ primary_hostname = myhost.test.ex
# ----- Main settings -----
acl_smtp_rcpt = accept
+.ifdef DYNAMIC_OPTION
+recipients_max = ${if def:sender_host_address {1}{2}}
+.else
recipients_max = 1
+.endif
# ------ Routers ------
diff --git a/test/log/0289 b/test/log/0289
index 15064bcdb..e79c3e25e 100644
--- a/test/log/0289
+++ b/test/log/0289
@@ -1,3 +1,10 @@
1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= <> U=EXIMUSER P=local S=sss
1999-03-02 09:44:33 10HmaX-000000005vi-0000 => CALLER <CALLER@???> R=r1 T=local_delivery
1999-03-02 09:44:33 10HmaX-000000005vi-0000 Completed
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 <= CALLER@??? U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 => userx <userx@???> R=r1 T=local_delivery
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 => usery <usery@???> R=r1 T=local_delivery
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 Completed
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 <= <> U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 => CALLER <CALLER@???> R=r1 T=local_delivery
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 Completed
diff --git a/test/log/4710 b/test/log/4710
index 3937611b8..99934ebf5 100644
--- a/test/log/4710
+++ b/test/log/4710
@@ -4,3 +4,5 @@
1999-03-02 09:44:33 exim x.yz daemon started: pid=p1237, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 exim x.yz daemon started: pid=p1238, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 exim x.yz daemon started: pid=p1239, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 exim x.yz daemon started: pid=p1240, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 exim x.yz daemon started: pid=p1241, no queue runs, listening for SMTP on port PORT_D
diff --git a/test/mail/0289.CALLER b/test/mail/0289.CALLER
index 2ba67d12b..3dc4f79ba 100644
--- a/test/mail/0289.CALLER
+++ b/test/mail/0289.CALLER
@@ -21,3 +21,24 @@ From: me
Body
.
+From MAILER-DAEMON Tue Mar 02 09:44:33 1999
+Received: from EXIMUSER by myhost.test.ex with local (Exim x.yz)
+ id 10HmaZ-000000005vi-0000
+ for CALLER@???;
+ Tue, 2 Mar 1999 09:44:33 +0000
+Auto-Submitted: auto-replied
+From: Mail Delivery System <Mailer-Daemon@???>
+To: CALLER@???
+Subject: Mail failure - too many recipients
+Message-Id: <E10HmaZ-000000005vi-0000@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+A message that you sent contained more recipients than allowed on this
+system. It was not delivered to any recipients.
+
+------ This is a copy of your message, including all the headers. ------
+
+
+From: me
+.
+
diff --git a/test/mail/0289.userx b/test/mail/0289.userx
new file mode 100644
index 000000000..a789fc76e
--- /dev/null
+++ b/test/mail/0289.userx
@@ -0,0 +1,10 @@
+From CALLER@??? Tue Mar 02 09:44:33 1999
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@???>)
+ id 10HmaY-000000005vi-0000;
+ Tue, 2 Mar 1999 09:44:33 +0000
+From: me@???
+Message-Id: <E10HmaY-000000005vi-0000@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+
diff --git a/test/mail/0289.usery b/test/mail/0289.usery
new file mode 100644
index 000000000..a789fc76e
--- /dev/null
+++ b/test/mail/0289.usery
@@ -0,0 +1,10 @@
+From CALLER@??? Tue Mar 02 09:44:33 1999
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@???>)
+ id 10HmaY-000000005vi-0000;
+ Tue, 2 Mar 1999 09:44:33 +0000
+From: me@???
+Message-Id: <E10HmaY-000000005vi-0000@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+
diff --git a/test/scripts/0000-Basic/0289 b/test/scripts/0000-Basic/0289
index 2483b3706..f768b80d0 100644
--- a/test/scripts/0000-Basic/0289
+++ b/test/scripts/0000-Basic/0289
@@ -13,3 +13,14 @@ From: me
Body
.
****
+#
+# recipients_max should be expanded (here, for non-SMTP)
+exim -DDYNAMIC_OPTION -odi userx usery
+From: me
+.
+****
+1
+exim -odi -DDYNAMIC_OPTION userx usery userz
+From: me
+.
+****
diff --git a/test/scripts/4710-esmtp-limits/4710 b/test/scripts/4710-esmtp-limits/4710
index 875613cab..a5b9a6a6c 100644
--- a/test/scripts/4710-esmtp-limits/4710
+++ b/test/scripts/4710-esmtp-limits/4710
@@ -84,3 +84,26 @@ EHLO tester
??? 250
****
killdaemon
+# recipients_max is expanded (at least for smtp)
+exim -DSERVER=server -DRCPT_MSG='${if eq {$sender_host_address}{HOSTIPV4}{4}{100}}' -bd -oX PORT_D
+****
+client HOSTIPV4 PORT_D
+??? 220
+EHLO tester
+??? 250-
+??? 250-SIZE
+??? 250-LIMITS MAILMAX=1000 RCPTMAX=4
+??? 250
+****
+killdaemon
+exim -DSERVER=server -DRCPT_MSG='${if eq {$sender_host_address}{HOSTIPV4}{4}{100}}' -bd -oX PORT_D
+****
+client 127.0.0.1 PORT_D
+??? 220
+EHLO tester
+??? 250-
+??? 250-SIZE
+??? 250-LIMITS MAILMAX=1000 RCPTMAX=100
+??? 250
+****
+killdaemon
diff --git a/test/stdout/4710 b/test/stdout/4710
index 701b4376c..7e031e244 100644
--- a/test/stdout/4710
+++ b/test/stdout/4710
@@ -85,3 +85,29 @@ Connecting to 127.0.0.1 port 1225 ... connected
??? 250
<<< 250-8BITMIME
End of script
+Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO tester
+??? 250-
+<<< 250-myhost.test.ex Hello tester [ip4.ip4.ip4.ip4]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-LIMITS MAILMAX=1000 RCPTMAX=4
+<<< 250-LIMITS MAILMAX=1000 RCPTMAX=4
+??? 250
+<<< 250-8BITMIME
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO tester
+??? 250-
+<<< 250-myhost.test.ex Hello tester [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-LIMITS MAILMAX=1000 RCPTMAX=100
+<<< 250-LIMITS MAILMAX=1000 RCPTMAX=100
+??? 250
+<<< 250-8BITMIME
+End of script
--
## subscription configuration (requires account):
##
https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at
http://www.exim.org/
## Please use the Wiki with this list -
http://wiki.exim.org/