From: Jeremy Harris Date: Sun, 26 Jan 2020 14:02:31 +0000 (+0000) Subject: ACL: control = queue/first_pass_route X-Git-Url: https://git.exim.org/users/jgh/exim.git/commitdiff_plain/9438970c97adda0afb9b825b5beff5276a1d613d?hp=e851856fc72bf126f7b649a007fb7040140d5d3c ACL: control = queue/first_pass_route --- diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 3bea313c1..68ad1691e 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -4185,6 +4185,7 @@ forces queueing. .vitem &%-odqs%& .oindex "&%-odqs%&" .cindex "SMTP" "delaying delivery" +.cindex "first pass routing" This option is a hybrid between &%-odb%&/&%-odi%& and &%-odq%&. However, like &%-odb%& and &%-odi%&, this option has no effect if &%queue_only_override%& is false and one of the queueing options in the @@ -4503,6 +4504,7 @@ appear in the correct order. Each flag is described in a separate item below. .cindex "queue" "double scanning" .cindex "queue" "routing" .cindex "routing" "whole queue before delivery" +.cindex "first pass routing" An option starting with &%-qq%& requests a two-stage queue run. In the first stage, the queue is scanned as if the &%queue_smtp_domains%& option matched every domain. Addresses are routed, local deliveries happen, but no remote @@ -16766,6 +16768,7 @@ an expansion depending on the &$queue_name$& variable. .option queue_smtp_domains main "domain list&!!" unset .cindex "queueing incoming messages" .cindex "message" "queueing remote deliveries" +.cindex "first pass routing" When this option is set, a delivery process is started whenever a message is received, routing is performed, and local deliveries take place. However, if any SMTP deliveries are required for domains that match @@ -30717,16 +30720,32 @@ response to an EHLO command. Therefore, it should normally appear in an ACL controlled by &%acl_smtp_connect%& or &%acl_smtp_helo%&. See also &%pipelining_advertise_hosts%&. +.new +.vitem &*control&~=&~queue/*&<&'options'&>* .vitem &*control&~=&~queue_only*& +.oindex "&%queue%&" .oindex "&%queue_only%&" .cindex "queueing incoming messages" +.cindex queueing "forcing in ACL" +.cindex "first pass routing" This control is permitted only for the MAIL, RCPT, DATA, and non-SMTP ACLs, in other words, only when a message is being received. If the message is accepted, it is placed on Exim's queue and left there for delivery by a subsequent queue -runner. No immediate delivery process is started. In other words, it has the -effect as the &%queue_only%& global option. However, the control applies only -to the current message, not to any subsequent ones that may be received in the -same SMTP connection. +runner. +If used with no options set, +no immediate delivery process is started. In other words, it has the +effect as the &%queue_only%& global option or &'-odq'& command-line option. + +If the &'first_pass_route'& option is given then +the behaviour is like the command-line &'-oqds'& option; +a delivery process is started which stops short of making +any SMTP delivery. The benefit is that the hints database will be updated for +the message being waiting for a specific host, and a later queue run will be +able to send all such messages on a single connection. + +The control only applies to the current message, not to any subsequent ones that + may be received in the same SMTP connection. +.wen .vitem &*control&~=&~submission/*&<&'options'&> .cindex "message" "submission" @@ -36859,6 +36878,7 @@ delivered immediately. .cindex "SMTP" "passed connection" .cindex "SMTP" "multiple deliveries" .cindex "multiple SMTP deliveries" +.cindex "first pass routing" Mail waiting to be sent from an intermittently connected host will probably not have been routed, because without a connection DNS lookups are not possible. This means that if a normal queue run is done at connection time, diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 8ae95a7fb..3542c82cb 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -33,6 +33,9 @@ Version 4.94 8. As an exerimental feature, the dovecot authenticatino driver supports inet sockets. Previously it was unix-domain sockets only. + 9. The ACL control "queue_only" can also be spelled "queue", and now takes an + option "first_pass_route" to do the same as a "-odqs" on the command line. + Version 4.93 ------------ diff --git a/src/src/acl.c b/src/src/acl.c index 938bea7d9..952195d4a 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -366,6 +366,7 @@ enum { CONTROL_NO_MULTILINE, CONTROL_NO_PIPELINING, + CONTROL_QUEUE, CONTROL_QUEUE_ONLY, CONTROL_SUBMISSION, CONTROL_SUPPRESS_LOCAL_FIXUPS, @@ -502,8 +503,16 @@ static control_def controls_list[] = { ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START }, +[CONTROL_QUEUE] = + { US"queue", TRUE, + (unsigned) + ~(ACL_BIT_MAIL | ACL_BIT_RCPT | + ACL_BIT_PREDATA | ACL_BIT_DATA | + // ACL_BIT_PRDR| /* Not allow one user to freeze for all */ + ACL_BIT_NOTSMTP | ACL_BIT_MIME) + }, [CONTROL_QUEUE_ONLY] = - { US"queue_only", FALSE, + { US"queue_only", TRUE, (unsigned) ~(ACL_BIT_MAIL | ACL_BIT_RCPT | ACL_BIT_PREDATA | ACL_BIT_DATA | @@ -3158,9 +3167,16 @@ for (; cb; cb = cb->next) cancel_cutthrough_connection(TRUE, US"item frozen"); break; + case CONTROL_QUEUE: case CONTROL_QUEUE_ONLY: f.queue_only_policy = TRUE; cancel_cutthrough_connection(TRUE, US"queueing forced"); + while (*p == '/') + if (Ustrncmp(p, "/first_pass_route", 17) == 0) + { + p += 17; + f.queue_smtp = TRUE; + } break; case CONTROL_SUBMISSION: diff --git a/src/src/daemon.c b/src/src/daemon.c index 61371f592..42e291cf8 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -640,7 +640,8 @@ if (pid == 0) If we are not root, we have to re-exec exim unless deliveries are being done unprivileged. */ - else if (!f.queue_only_policy && !f.deliver_freeze) + else if ( (!f.queue_only_policy || f.queue_smtp) + && !f.deliver_freeze) { pid_t dpid; diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 6559d4170..b748b7657 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -4873,10 +4873,12 @@ retry_non_continued: &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK) ) { + DEBUG(D_transport) debug_printf("first-pass routing only\n"); expired = FALSE; for (address_item * addr = addrlist; addr; addr = addr->next) if (addr->transport_return == DEFER) - addr->message = US"domain matches queue_smtp_domains, or -odqs set"; + addr->message = US"first-pass only routing due to -odqs, " + "queue_smtp_domains or control=queue"; continue; /* With next host */ } diff --git a/test/confs/0599 b/test/confs/0599 new file mode 100644 index 000000000..54667124d --- /dev/null +++ b/test/confs/0599 @@ -0,0 +1,54 @@ +# Exim test configuration 0599 +# control = queue/first_pass_route + +.include DIR/aux-var/std_conf_prefix + + +# ----- Main settings ----- + +domainlist local_domains = @ + +acl_smtp_rcpt = check_rcpt + +trusted_users = CALLER +queue_run_in_order + + +# ----- ACL ----- + +begin acl + +check_rcpt: + accept senders = HOSTIPV4 + + accept local_parts = ^queue_only.* + control = queue_only + + accept local_parts = ^first_pass_route.* + control = queue/first_pass_route + +# ----- Routers ----- + +begin routers + +discard_remote_source: + driver = redirect + condition = ${if !eq {$sender_host_address}{127.0.0.1}} + data = :blackhole: + +outbound: + driver = accept + transport = smtp + + +# ----- Transports ----- + +begin transports + +smtp: + driver = smtp + hosts = HOSTIPV4 + port = PORT_D + allow_localhost + +# End diff --git a/test/log/0055 b/test/log/0055 index a3f151d45..51d31aa3d 100644 --- a/test/log/0055 +++ b/test/log/0055 @@ -19,7 +19,7 @@ 1999-03-02 09:44:33 10HmbB-0005vi-00 *> xxx@ten-1.test.ex R=lookuphost T=smtp H=ten-1.test.ex [V4NET.0.0.1] C="delivery bypassed by -N option" 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed 1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.ex U=CALLER P=local S=sss -1999-03-02 09:44:33 10HmbC-0005vi-00 == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set +1999-03-02 09:44:33 10HmbC-0005vi-00 == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue 1999-03-02 09:44:33 Start queue run: pid=pppp 1999-03-02 09:44:33 10HmbC-0005vi-00 *> xxx@ten-2.test.ex R=lookuphost T=smtp H=ten-2.test.ex [V4NET.0.0.2] C="delivery bypassed by -N option" 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed @@ -33,7 +33,7 @@ 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp -qq 1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.ex U=CALLER P=local S=sss -1999-03-02 09:44:33 10HmbF-0005vi-00 == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set +1999-03-02 09:44:33 10HmbF-0005vi-00 == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue 1999-03-02 09:44:33 10HmbF-0005vi-00 *> xxx@ten-2.test.ex R=lookuphost T=smtp H=ten-2.test.ex [V4NET.0.0.2] C="delivery bypassed by -N option" 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed 1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.ex U=CALLER P=local S=sss diff --git a/test/log/0544 b/test/log/0544 index 9d519bb84..a8361a13a 100644 --- a/test/log/0544 +++ b/test/log/0544 @@ -1,3 +1,3 @@ 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss -1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@domain1.ex R=smarthost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set -1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@domain2.ex R=smarthost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set +1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@domain1.ex R=smarthost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue +1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@domain2.ex R=smarthost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue diff --git a/test/log/0599 b/test/log/0599 new file mode 100644 index 000000000..cef4d7471 --- /dev/null +++ b/test/log/0599 @@ -0,0 +1,45 @@ +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 10HmaX-0005vi-00 => queue_only_1@test.ex R=outbound T=smtp H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmaY-0005vi-00" +1999-03-02 09:44:33 10HmaX-0005vi-00 Completed +1999-03-02 09:44:33 10HmaZ-0005vi-00 => queue_only_2@test.ex R=outbound T=smtp H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] 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 Start queue run: pid=pppp +1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: R=discard_remote_source +1999-03-02 09:44:33 10HmaY-0005vi-00 Completed +1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: R=discard_remote_source +1999-03-02 09:44:33 10HmbA-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 10HmbB-0005vi-00 => first_pass_route_1@test.ex R=outbound T=smtp H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmbB-0005vi-00 Completed +1999-03-02 09:44:33 10HmbD-0005vi-00 => first_pass_route_2@test.ex R=outbound T=smtp H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]* C="250 OK id=10HmbE-0005vi-00" +1999-03-02 09:44:33 10HmbD-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 + +******** SERVER ******** +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex H=(me) [127.0.0.1] P=smtp S=sss +1999-03-02 09:44:33 10HmaX-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex H=(me) [127.0.0.1] P=smtp S=sss +1999-03-02 09:44:33 10HmaZ-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@test.ex H=the.local.host.name [ip4.ip4.ip4.ip4] P=esmtp S=sss +1999-03-02 09:44:33 10HmaY-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@test.ex H=the.local.host.name [ip4.ip4.ip4.ip4] P=esmtp S=sss +1999-03-02 09:44:33 10HmbA-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@test.ex H=(me) [127.0.0.1] P=smtp S=sss +1999-03-02 09:44:33 10HmbB-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@test.ex H=(me) [127.0.0.1] P=smtp S=sss +1999-03-02 09:44:33 10HmbD-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmbB-0005vi-00 == first_pass_route_1@test.ex R=outbound T=smtp defer (0): SMTP delivery explicitly queued +1999-03-02 09:44:33 10HmbD-0005vi-00 == first_pass_route_2@test.ex R=outbound T=smtp defer (0): SMTP delivery explicitly queued +1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@test.ex H=the.local.host.name [ip4.ip4.ip4.ip4] P=esmtp S=sss +1999-03-02 09:44:33 10HmbC-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: R=discard_remote_source +1999-03-02 09:44:33 10HmbC-0005vi-00 Completed +1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@test.ex H=the.local.host.name [ip4.ip4.ip4.ip4] P=esmtp S=sss +1999-03-02 09:44:33 10HmbE-0005vi-00 no immediate delivery: queued by ACL +1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: R=discard_remote_source +1999-03-02 09:44:33 10HmbE-0005vi-00 Completed diff --git a/test/scripts/0000-Basic/0599 b/test/scripts/0000-Basic/0599 new file mode 100644 index 000000000..aa712de2f --- /dev/null +++ b/test/scripts/0000-Basic/0599 @@ -0,0 +1,76 @@ +# control = queue/first_pass_route +# +exim -bd -DSERVER=server -oX PORT_D +**** +# +# First, control=queue_only - we expact the queue run to make separate connections +client 127.0.0.1 PORT_D +??? 220 +HELO me +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +Subject: 1 +. +??? 250 +RSET +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +Subject: 2 +. +??? 250 +QUIT +**** +exim -q +**** +exim -q +**** +# +# Second, control=queue/first_pass_route - we expect the queue run to make only one +# connection, and put both messages over it +client 127.0.0.1 PORT_D +??? 220 +HELO me +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +Subject: 1 +. +??? 250 +RSET +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +Subject: 2 +. +??? 250 +QUIT +**** +# give time for the background routing in the exim daemon to complete +sleep 1 +# then run the queue +exim -q +**** +exim -q +**** +# +# +killdaemon +no_msglog_check diff --git a/test/stderr/0055 b/test/stderr/0055 index c9729ad2e..e3789a44c 100644 --- a/test/stderr/0055 +++ b/test/stderr/0055 @@ -28,7 +28,7 @@ LOG: MAIN <= CALLER@myhost.ex U=CALLER P=local S=sss delivering 10HmbC-0005vi-00 LOG: MAIN - == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set + == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue LOG: queue_run MAIN Start queue run: pid=pppp delivering 10HmbC-0005vi-00 (queue run pid ppppp) @@ -58,7 +58,7 @@ LOG: MAIN <= CALLER@myhost.ex U=CALLER P=local S=sss delivering 10HmbF-0005vi-00 LOG: MAIN - == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set + == xxx@ten-2.test.ex R=lookuphost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue delivering 10HmbF-0005vi-00 LOG: MAIN *> xxx@ten-2.test.ex R=lookuphost T=smtp H=ten-2.test.ex [V4NET.0.0.2] C="delivery bypassed by -N option" diff --git a/test/stderr/0544 b/test/stderr/0544 index 4f4e07b02..026c28623 100644 --- a/test/stderr/0544 +++ b/test/stderr/0544 @@ -130,9 +130,9 @@ dropping to exim gid; retaining priv uid ╰─────result: domain1.ex ╰──(tainted) LOG: MAIN - == userx@domain1.ex R=smarthost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set + == userx@domain1.ex R=smarthost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue LOG: MAIN - == userx@domain2.ex R=smarthost T=smtp defer (-1): domain matches queue_smtp_domains, or -odqs set + == userx@domain2.ex R=smarthost T=smtp defer (-1): first-pass only routing due to -odqs, queue_smtp_domains or control=queue ╭considering: ${if or {{ !eq{$h_list-id:$h_list-post:$h_list-subscribe:}{} }{ match{$h_precedence:}{(?i)bulk|list|junk} }{ match{$h_auto-submitted:}{(?i)auto-generated|auto-replied} }} {no}{yes}} ╭considering: $h_list-id:$h_list-post:$h_list-subscribe:}{} }{ match{$h_precedence:}{(?i)bulk|list|junk} }{ match{$h_auto-submitted:}{(?i)auto-generated|auto-replied} }} {no}{yes}} ├──expanding: $h_list-id:$h_list-post:$h_list-subscribe: diff --git a/test/stdout/0599 b/test/stdout/0599 new file mode 100644 index 000000000..ee9dd950a --- /dev/null +++ b/test/stdout/0599 @@ -0,0 +1,74 @@ +Connecting to 127.0.0.1 port 1225 ... connected +??? 220 +<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +>>> HELO me +??? 250 +<<< 250 the.local.host.name Hello me [127.0.0.1] +>>> MAIL FROM: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 250 +<<< 250 Accepted +>>> DATA +??? 354 +<<< 354 Enter message, ending with "." on a line by itself +>>> Subject: 1 +>>> . +??? 250 +<<< 250 OK id=10HmaX-0005vi-00 +>>> RSET +??? 250 +<<< 250 Reset OK +>>> MAIL FROM: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 250 +<<< 250 Accepted +>>> DATA +??? 354 +<<< 354 Enter message, ending with "." on a line by itself +>>> Subject: 2 +>>> . +??? 250 +<<< 250 OK id=10HmaZ-0005vi-00 +>>> QUIT +End of script +Connecting to 127.0.0.1 port 1225 ... connected +??? 220 +<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +>>> HELO me +??? 250 +<<< 250 the.local.host.name Hello me [127.0.0.1] +>>> MAIL FROM: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 250 +<<< 250 Accepted +>>> DATA +??? 354 +<<< 354 Enter message, ending with "." on a line by itself +>>> Subject: 1 +>>> . +??? 250 +<<< 250 OK id=10HmbB-0005vi-00 +>>> RSET +??? 250 +<<< 250 Reset OK +>>> MAIL FROM: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 250 +<<< 250 Accepted +>>> DATA +??? 354 +<<< 354 Enter message, ending with "." on a line by itself +>>> Subject: 2 +>>> . +??? 250 +<<< 250 OK id=10HmbD-0005vi-00 +>>> QUIT +End of script