summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2015-01-13 11:19:32 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2015-01-20 13:39:22 +0000
commit5032d1cf500b102849d9a47867fbb7b34d871683 (patch)
treeff63b3bfaac155f1c502b01dbdf5c3065a440f1d
parent7f3555b3d8e1fccfe8f5d450bdde367018a5e764 (diff)
Multi-recipient cutthrough delivery. Bug 1542
Testing and fixes by: Heiko Schlittermann <hs@schlittermann.de>
-rw-r--r--doc/doc-docbook/spec.xfpt13
-rw-r--r--doc/doc-txt/ChangeLog3
-rw-r--r--src/src/acl.c36
-rw-r--r--src/src/globals.c7
-rw-r--r--src/src/globals.h12
-rw-r--r--src/src/receive.c74
-rw-r--r--src/src/smtp_in.c2
-rw-r--r--src/src/verify.c261
-rw-r--r--test/confs/540017
-rw-r--r--test/log/540048
-rw-r--r--test/scripts/5400-cutthrough/5400321
-rw-r--r--test/stderr/5400235
-rw-r--r--test/stdout/5400364
13 files changed, 999 insertions, 394 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index d78797fb7..d5a16cacc 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -28003,14 +28003,18 @@ is what is wanted for subsequent tests.
.cindex "cutthrough" "requesting"
This option requests delivery be attempted while the item is being received.
-The option usable in the RCPT ACL.
+The option is usable in the RCPT ACL.
If enabled for a message recieved via smtp and routed to an smtp transport,
-and the message has only one recipient,
+and only one transport, interface, destination host and port combination
+is used for all recipients of the message,
then the delivery connection is made while the receiving connection is open
and data is copied from one to the other.
+An attempt to set this option for any recipient but the first
+for a mail will be quietly ignored.
If a recipient-verify callout connection is subsequently
-requested in the same ACL it is held open and used for the data,
+requested in the same ACL it is held open and used for
+any subsequent receipients and the data,
otherwise one is made after the initial RCPT ACL completes.
Note that routers are used in verify mode,
@@ -28022,12 +28026,13 @@ Headers may be modified by routers (subject to the above) and transports.
Cutthrough delivery is not supported via transport-filters or when DKIM signing
of outgoing messages is done, because it sends data to the ultimate destination
before the entire message has been received from the source.
+It is not supported for messages recieved with the SMTP PRDR option in use.
Should the ultimate destination system positively accept or reject the mail,
a corresponding indication is given to the source system and nothing is queued.
If there is a temporary error the item is queued for later delivery in the
usual fashion. If the item is successfully delivered in cutthrough mode
-the log line is tagged with ">>" rather than "=>" and appears
+the delivery log lines are tagged with ">>" rather than "=>" and appear
before the acceptance "<=" line.
Delivery in this mode avoids the generation of a bounce mail to a
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index eeefef71c..57df78280 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -44,6 +44,9 @@ JH/10 The smtp_receive_timeout main option is now expanded before use.
JH/11 The incoming_interface log option now also enables logging of the
local interface on delivery outgoing connections.
+JH/12 The cutthrough-routing facility now supports multi-recipient mails,
+ if the interface and destination host and port all match.
+
Exim version 4.85
diff --git a/src/src/acl.c b/src/src/acl.c
index 8fdae0390..06c1c494c 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -3354,19 +3354,27 @@ for (; cb != NULL; cb = cb->next)
break;
case CONTROL_CUTTHROUGH_DELIVERY:
- if (deliver_freeze)
- *log_msgptr = US"frozen";
- else if (queue_only_policy)
- *log_msgptr = US"queue-only";
- else if (fake_response == FAIL)
- *log_msgptr = US"fakereject";
+ if (prdr_requested)
+ /* Too hard to think about for now. We might in future cutthrough
+ the case where both sides handle prdr and this-node prdr acl
+ is "accept" */
+ *log_msgptr = string_sprintf(US"PRDR on %s reception\n", arg);
else
{
- cutthrough_delivery = TRUE;
- break;
+ if (deliver_freeze)
+ *log_msgptr = US"frozen";
+ else if (queue_only_policy)
+ *log_msgptr = US"queue-only";
+ else if (fake_response == FAIL)
+ *log_msgptr = US"fakereject";
+ else
+ {
+ if (rcpt_count == 1) cutthrough.delivery = TRUE;
+ break;
+ }
+ *log_msgptr = string_sprintf("\"control=%s\" on %s item",
+ arg, *log_msgptr);
}
- *log_msgptr = string_sprintf("\"control=%s\" on %s item",
- arg, *log_msgptr);
return ERROR;
}
break;
@@ -4351,9 +4359,9 @@ ratelimiters_cmd = NULL;
log_reject_target = LOG_MAIN|LOG_REJECT;
#ifndef DISABLE_PRDR
-if (where == ACL_WHERE_RCPT || where == ACL_WHERE_PRDR )
+if (where == ACL_WHERE_RCPT || where == ACL_WHERE_PRDR)
#else
-if (where == ACL_WHERE_RCPT )
+if (where == ACL_WHERE_RCPT)
#endif
{
adb = address_defaults;
@@ -4397,9 +4405,7 @@ case ACL_WHERE_RCPT:
#ifndef DISABLE_PRDR
case ACL_WHERE_PRDR:
#endif
- if( rcpt_count > 1 )
- cancel_cutthrough_connection("more than one recipient");
- else if (rc == OK && cutthrough_delivery && cutthrough_fd < 0)
+ if (rc == OK && cutthrough.delivery && rcpt_count > cutthrough.nrcpt)
open_cutthrough_connection(addr);
break;
diff --git a/src/src/globals.c b/src/src/globals.c
index a8670e414..a066f3595 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -506,8 +506,11 @@ int continue_sequence = 1;
uschar *continue_transport = NULL;
uschar *csa_status = NULL;
-BOOL cutthrough_delivery = FALSE;
-int cutthrough_fd = -1;
+cut_t cutthrough = {
+ FALSE, /* delivery: when to attempt */
+ -1, /* fd: open connection */
+ 0, /* nrcpt: number of addresses */
+};
BOOL daemon_listen = FALSE;
uschar *daemon_smtp_port = US"smtp";
diff --git a/src/src/globals.h b/src/src/globals.h
index 5495f54db..b5ea8a49b 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -291,8 +291,16 @@ extern int continue_sequence; /* Sequence num for continued delivery */
extern uschar *continue_transport; /* Transport for continued delivery */
extern uschar *csa_status; /* Client SMTP Authorization result */
-extern BOOL cutthrough_delivery; /* Deliver in foreground */
-extern int cutthrough_fd; /* Connection for ditto */
+
+typedef struct {
+ BOOL delivery; /* When to attempt */
+ int fd; /* Open connection */
+ int nrcpt; /* Count of addresses */
+ uschar * interface; /* (address of) */
+ host_item host; /* Host used */
+ address_item addr; /* (Chain of) addresses */
+} cut_t;
+extern cut_t cutthrough; /* Deliver-concurrently */
extern BOOL daemon_listen; /* True if listening required */
extern uschar *daemon_smtp_port; /* Can be a list of ports */
diff --git a/src/src/receive.c b/src/src/receive.c
index 8ab3166d0..977150c1d 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -997,7 +997,7 @@ switch(where)
case ACL_WHERE_DKIM:
case ACL_WHERE_MIME:
case ACL_WHERE_DATA:
- if (cutthrough_fd >= 0 && (acl_removed_headers || acl_added_headers))
+ if (cutthrough.fd >= 0 && (acl_removed_headers || acl_added_headers))
{
log_write(0, LOG_MAIN|LOG_PANIC, "Header modification in data ACLs"
" will not take effect on cutthrough deliveries");
@@ -2807,12 +2807,11 @@ if (filter_test != FTEST_NONE)
}
/* Cutthrough delivery:
- We have to create the Received header now rather than at the end of reception,
- so the timestamp behaviour is a change to the normal case.
- XXX Ensure this gets documented XXX.
- Having created it, send the headers to the destination.
-*/
-if (cutthrough_fd >= 0)
+We have to create the Received header now rather than at the end of reception,
+so the timestamp behaviour is a change to the normal case.
+XXX Ensure this gets documented XXX.
+Having created it, send the headers to the destination. */
+if (cutthrough.fd >= 0)
{
if (received_count > received_headers_max)
{
@@ -3184,56 +3183,61 @@ else
rc = OK;
while ((item = string_nextinlist(&ptr, &sep,
itembuf,
- sizeof(itembuf))) != NULL)
+ sizeof(itembuf))))
{
/* Prevent running ACL for an empty item */
if (!item || (item[0] == '\0')) continue;
- /* Only run ACL once for each domain or identity, no matter how often it
- appears in the expanded list. */
- if (seen_items != NULL)
+
+ /* Only run ACL once for each domain or identity,
+ no matter how often it appears in the expanded list. */
+ if (seen_items)
{
uschar *seen_item = NULL;
uschar seen_item_buf[256];
uschar *seen_items_list = seen_items;
- int seen_this_item = 0;
+ BOOL seen_this_item = FALSE;
while ((seen_item = string_nextinlist(&seen_items_list, &sep,
seen_item_buf,
- sizeof(seen_item_buf))) != NULL)
- {
- if (Ustrcmp(seen_item,item) == 0)
- {
- seen_this_item = 1;
- break;
- }
- }
-
- if (seen_this_item > 0)
+ sizeof(seen_item_buf))))
+ if (Ustrcmp(seen_item,item) == 0)
+ {
+ seen_this_item = TRUE;
+ break;
+ }
+
+ if (seen_this_item)
{
DEBUG(D_receive)
- debug_printf("acl_smtp_dkim: skipping signer %s, already seen\n", item);
+ debug_printf("acl_smtp_dkim: skipping signer %s, "
+ "already seen\n", item);
continue;
}
- seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,":");
+ seen_items = string_append(seen_items, &seen_items_size,
+ &seen_items_offset, 1, ":");
}
- seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,item);
+ seen_items = string_append(seen_items, &seen_items_size,
+ &seen_items_offset, 1, item);
seen_items[seen_items_offset] = '\0';
DEBUG(D_receive)
- debug_printf("calling acl_smtp_dkim for dkim_cur_signer=%s\n", item);
+ debug_printf("calling acl_smtp_dkim for dkim_cur_signer=%s\n",
+ item);
dkim_exim_acl_setup(item);
- rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, &user_msg, &log_msg);
+ rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim,
+ &user_msg, &log_msg);
if (rc != OK)
- {
- DEBUG(D_receive)
- debug_printf("acl_smtp_dkim: acl_check returned %d on %s, skipping remaining items\n", rc, item);
- cancel_cutthrough_connection("dkim acl not ok");
- break;
- }
+ {
+ DEBUG(D_receive)
+ debug_printf("acl_smtp_dkim: acl_check returned %d on %s, "
+ "skipping remaining items\n", rc, item);
+ cancel_cutthrough_connection("dkim acl not ok");
+ break;
+ }
}
add_acl_headers(ACL_WHERE_DKIM, US"DKIM");
if (rc == DISCARD)
@@ -3957,7 +3961,7 @@ for this message. */
XXX We do not handle queue-only, freezing, or blackholes.
*/
-if(cutthrough_fd >= 0)
+if(cutthrough.fd >= 0)
{
uschar * msg= cutthrough_finaldot(); /* Ask the target system to accept the messsage */
/* Logging was done in finaldot() */
@@ -4103,7 +4107,7 @@ if (smtp_input)
case TMP_REJ: message_id[0] = 0; /* Prevent a delivery from starting */
default:break;
}
- cutthrough_delivery = FALSE;
+ cutthrough.delivery = FALSE;
}
/* For batched SMTP, generate an error message on failure, and do
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 4fc2cfd41..4e4cdb825 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -4448,7 +4448,7 @@ while (done <= 0)
ACL may have delayed. To handle cutthrough delivery enforce a dummy call
to get the DATA command sent. */
- if (acl_smtp_predata == NULL && cutthrough_fd < 0) rc = OK; else
+ if (acl_smtp_predata == NULL && cutthrough.fd < 0) rc = OK; else
{
uschar * acl= acl_smtp_predata ? acl_smtp_predata : US"accept";
enable_dollar_recipients = TRUE;
diff --git a/src/src/verify.c b/src/src/verify.c
index 96740f8f3..4474f2c5b 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -14,7 +14,6 @@ caching was contributed by Kevin Fleming (but I hacked it around a bit). */
#define CUTTHROUGH_CMD_TIMEOUT 30 /* timeout for cutthrough-routing calls */
#define CUTTHROUGH_DATA_TIMEOUT 60 /* timeout for cutthrough-routing calls */
-address_item cutthrough_addr;
static smtp_outblock ctblock;
uschar ctbuffer[8192];
@@ -39,6 +38,7 @@ static tree_node *dnsbl_cache = NULL;
#define MT_NOT 1
#define MT_ALL 2
+static uschar cutthrough_response(char, uschar **);
/*************************************************
@@ -189,12 +189,12 @@ from_address = US"";
if (is_recipient)
{
- if ((options & vopt_callout_recipsender) != 0)
+ if (options & vopt_callout_recipsender)
{
address_key = string_sprintf("%s/<%s>", addr->address, sender_address);
from_address = sender_address;
}
- else if ((options & vopt_callout_recippmaster) != 0)
+ else if (options & vopt_callout_recippmaster)
{
address_key = string_sprintf("%s/<postmaster@%s>", addr->address,
qualify_domain_sender);
@@ -410,6 +410,113 @@ else
if (smtp_out != NULL && !disable_callout_flush) mac_smtp_fflush();
+/* cutthrough-multi: if a nonfirst rcpt has the same routing as the first,
+and we are holding a cutthrough conn open, we can just append the rcpt to
+that conn for verification purposes (and later delivery also). Simplest
+coding means skipping this whole loop and doing the append separately.
+
+We will need to remember it has been appended so that rcpt-acl tail code
+can do it there for the non-rcpt-verify case. For this we keep an addresscount.
+*/
+
+ /* Can we re-use an open cutthrough connection? */
+ if ( cutthrough.fd >= 0
+ && (options & (vopt_callout_recipsender | vopt_callout_recippmaster))
+ == vopt_callout_recipsender
+ && !random_local_part
+ && !pm_mailfrom
+ )
+ {
+ if (addr->transport == cutthrough.addr.transport)
+ for (host = host_list; host; host = host->next)
+ if (Ustrcmp(host->address, cutthrough.host.address) == 0)
+ {
+ int host_af;
+ uschar *interface = NULL; /* Outgoing interface to use; NULL => any */
+ int port = 25;
+
+ deliver_host = host->name;
+ deliver_host_address = host->address;
+ deliver_host_port = host->port;
+ deliver_domain = addr->domain;
+ transport_name = addr->transport->name;
+
+ host_af = (Ustrchr(host->address, ':') == NULL)? AF_INET:AF_INET6;
+
+ if (!smtp_get_interface(tf->interface, host_af, addr, NULL, &interface,
+ US"callout") ||
+ !smtp_get_port(tf->port, addr, &port, US"callout"))
+ log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: %s", addr->address,
+ addr->message);
+
+ if ( ( interface == cutthrough.interface
+ || ( interface
+ && cutthrough.interface
+ && Ustrcmp(interface, cutthrough.interface) == 0
+ ) )
+ && port == cutthrough.host.port
+ )
+ {
+ uschar * resp;
+
+ /* Match! Send the RCPT TO, append the addr, set done */
+ done =
+ smtp_write_command(&ctblock, FALSE, "RCPT TO:<%.1000s>\r\n",
+ transport_rcpt_address(addr,
+ (addr->transport == NULL)? FALSE :
+ addr->transport->rcpt_include_affixes)) >= 0 &&
+ cutthrough_response('2', &resp) == '2';
+
+ /* This would go horribly wrong if a callout fail was ignored by ACL.
+ We punt by abandoning cutthrough on a reject, like the
+ first-rcpt does. */
+
+ if (done)
+ {
+ address_item * na = store_get(sizeof(address_item));
+ *na = cutthrough.addr;
+ cutthrough.addr = *addr;
+ cutthrough.addr.host_used = &cutthrough.host;
+ cutthrough.addr.next = na;
+
+ cutthrough.nrcpt++;
+ }
+ else
+ {
+ cancel_cutthrough_connection("recipient rejected");
+ if (errno == ETIMEDOUT)
+ {
+ HDEBUG(D_verify) debug_printf("SMTP timeout\n");
+ }
+ else if (errno == 0)
+ {
+ if (*resp == 0)
+ Ustrcpy(resp, US"connection dropped");
+
+ addr->message =
+ string_sprintf("response to \"%s\" from %s [%s] was: %s",
+ big_buffer, host->name, host->address,
+ string_printing(resp));
+
+ addr->user_message =
+ string_sprintf("Callout verification failed:\n%s", resp);
+
+ /* Hard rejection ends the process */
+
+ if (resp[0] == '5') /* Address rejected */
+ {
+ yield = FAIL;
+ done = TRUE;
+ }
+ }
+ }
+ }
+ break;
+ }
+ if (!done)
+ cancel_cutthrough_connection("incompatible connection");
+ }
+
/* Now make connections to the hosts and do real callouts. The list of hosts
is passed in as an argument. */
@@ -692,9 +799,9 @@ else
ob->command_timeout = callout;
rc = tls_client_start(inblock.sock, host, addr, addr->transport
-#ifdef EXPERIMENTAL_DANE
+# ifdef EXPERIMENTAL_DANE
, dane ? &tlsa_dnsa : NULL
-#endif
+# endif
);
ob->command_timeout = oldtimeout;
@@ -709,10 +816,10 @@ else
)
{
(void)close(inblock.sock);
-#ifdef EXPERIMENTAL_EVENT
+# ifdef EXPERIMENTAL_EVENT
(void) event_raise(addr->transport->event_action,
US"tcp:close", NULL);
-#endif
+# endif
log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
"to %s [%s] (not in hosts_require_tls)", host->name, host->address);
suppress_tls = TRUE;
@@ -741,9 +848,9 @@ else
/* If the host is required to use a secure channel, ensure that we have one. */
if (tls_out.active < 0)
if (
-#ifdef EXPERIMENTAL_DANE
+# ifdef EXPERIMENTAL_DANE
dane ||
-#endif
+# endif
verify_check_given_host(&ob->hosts_require_tls, host) == OK
)
{
@@ -757,7 +864,7 @@ else
goto TLS_FAILED;
}
- #endif /*SUPPORT_TLS*/
+#endif /*SUPPORT_TLS*/
done = TRUE; /* so far so good; have response to HELO */
@@ -765,17 +872,17 @@ else
/* For now, transport_filter by cutthrough-delivery is not supported */
/* Need proper integration with the proper transport mechanism. */
- if (cutthrough_delivery)
+ if (cutthrough.delivery)
{
if (addr->transport->filter_command)
{
- cutthrough_delivery= FALSE;
+ cutthrough.delivery = FALSE;
HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n");
}
#ifndef DISABLE_DKIM
if (ob->dkim_domain)
{
- cutthrough_delivery= FALSE;
+ cutthrough.delivery = FALSE;
HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n");
}
#endif
@@ -887,6 +994,8 @@ else
else if (errno == 0)
{
+ cancel_cutthrough_connection("random-recipient");
+
if (randombuffer[0] == '5')
new_domain_record.random_result = ccache_reject;
@@ -932,8 +1041,9 @@ else
if (done && pm_mailfrom != NULL)
{
- /*XXX not suitable for cutthrough - sequencing problems */
- cutthrough_delivery= FALSE;
+ /*XXX not suitable for cutthrough - we cannot afford to do an RSET
+ and lose the original mail-from */
+ cancel_cutthrough_connection("postmaster verify");
HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of postmaster verify\n");
done =
@@ -1028,30 +1138,34 @@ else
/* End the SMTP conversation and close the connection. */
- /* Cutthrough - on a successfull connect and recipient-verify with use-sender
- and we have no cutthrough conn so far
+ /* Cutthrough - on a successfull connect and recipient-verify with
+ use-sender and we are 1st rcpt and have no cutthrough conn so far
here is where we want to leave the conn open */
- if ( cutthrough_delivery
+ if ( cutthrough.delivery
+ && rcpt_count == 1
&& done
&& yield == OK
&& (options & (vopt_callout_recipsender|vopt_callout_recippmaster)) == vopt_callout_recipsender
&& !random_local_part
&& !pm_mailfrom
- && cutthrough_fd < 0
+ && cutthrough.fd < 0
)
{
- cutthrough_fd= outblock.sock; /* We assume no buffer in use in the outblock */
- cutthrough_addr = *addr; /* Save the address_item for later logging */
- cutthrough_addr.next = NULL;
- cutthrough_addr.host_used = store_get(sizeof(host_item));
- *(cutthrough_addr.host_used) = *host;
+ cutthrough.fd = outblock.sock; /* We assume no buffer in use in the outblock */
+ cutthrough.nrcpt = 1;
+ cutthrough.interface = interface;
+ cutthrough.host = *host;
+ cutthrough.addr = *addr; /* Save the address_item for later logging */
+ cutthrough.addr.next = NULL;
+ cutthrough.addr.host_used = &cutthrough.host;
if (addr->parent)
- *(cutthrough_addr.parent = store_get(sizeof(address_item)))= *addr->parent;
+ *(cutthrough.addr.parent = store_get(sizeof(address_item))) =
+ *addr->parent;
ctblock.buffer = ctbuffer;
ctblock.buffersize = sizeof(ctbuffer);
ctblock.ptr = ctbuffer;
/* ctblock.cmd_count = 0; ctblock.authenticating = FALSE; */
- ctblock.sock = cutthrough_fd;
+ ctblock.sock = cutthrough.fd;
}
else
{
@@ -1176,7 +1290,8 @@ address_item addr2;
get rewritten. */
addr2 = *addr;
-HDEBUG(D_acl) debug_printf("----------- start cutthrough setup ------------\n");
+HDEBUG(D_acl) debug_printf("----------- %s cutthrough setup ------------\n",
+ rcpt_count > 1 ? "more" : "start");
(void) verify_address(&addr2, NULL,
vopt_is_recipient | vopt_callout_recipsender | vopt_callout_no_cache,
CUTTHROUGH_CMD_TIMEOUT, -1, -1,
@@ -1191,14 +1306,14 @@ return;
static BOOL
cutthrough_send(int n)
{
-if(cutthrough_fd < 0)
+if(cutthrough.fd < 0)
return TRUE;
if(
#ifdef SUPPORT_TLS
- (tls_out.active == cutthrough_fd) ? tls_write(FALSE, ctblock.buffer, n) :
+ (tls_out.active == cutthrough.fd) ? tls_write(FALSE, ctblock.buffer, n) :
#endif
- send(cutthrough_fd, ctblock.buffer, n, 0) > 0
+ send(cutthrough.fd, ctblock.buffer, n, 0) > 0
)
{
transport_count += n;
@@ -1230,7 +1345,7 @@ return TRUE;
BOOL
cutthrough_puts(uschar * cp, int n)
{
-if (cutthrough_fd < 0) return TRUE;
+if (cutthrough.fd < 0) return TRUE;
if (_cutthrough_puts(cp, n)) return TRUE;
cancel_cutthrough_connection("transmit failed");
return FALSE;
@@ -1238,7 +1353,7 @@ return FALSE;
static BOOL
-_cutthrough_flush_send( void )
+_cutthrough_flush_send(void)
{
int n= ctblock.ptr-ctblock.buffer;
@@ -1251,7 +1366,7 @@ return TRUE;
/* Send out any bufferred output. Return boolean success. */
BOOL
-cutthrough_flush_send( void )
+cutthrough_flush_send(void)
{
if (_cutthrough_flush_send()) return TRUE;
cancel_cutthrough_connection("transmit failed");
@@ -1260,7 +1375,7 @@ return FALSE;
BOOL
-cutthrough_put_nl( void )
+cutthrough_put_nl(void)
{
return cutthrough_puts(US"\r\n", 2);
}
@@ -1278,7 +1393,7 @@ inblock.buffer = inbuffer;
inblock.buffersize = sizeof(inbuffer);
inblock.ptr = inbuffer;
inblock.ptrend = inbuffer;
-inblock.sock = cutthrough_fd;
+inblock.sock = cutthrough.fd;
/* this relies on (inblock.sock == tls_out.active) */
if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect, CUTTHROUGH_DATA_TIMEOUT))
cancel_cutthrough_connection("target timeout on read");
@@ -1286,7 +1401,7 @@ if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect,
if(copy != NULL)
{
uschar * cp;
- *copy= cp= string_copy(responsebuffer);
+ *copy = cp = string_copy(responsebuffer);
/* Trim the trailing end of line */
cp += Ustrlen(responsebuffer);
if(cp > *copy && cp[-1] == '\n') *--cp = '\0';
@@ -1299,9 +1414,9 @@ return responsebuffer[0];
/* Negotiate dataphase with the cutthrough target, returning success boolean */
BOOL
-cutthrough_predata( void )
+cutthrough_predata(void)
{
-if(cutthrough_fd < 0)
+if(cutthrough.fd < 0)
return FALSE;
HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP>> DATA\n");
@@ -1332,9 +1447,9 @@ return TRUE;
/* Expands newlines to wire format (CR,NL). */
/* Also sends header-terminating blank line. */
BOOL
-cutthrough_headers_send( void )
+cutthrough_headers_send(void)
{
-if(cutthrough_fd < 0)
+if(cutthrough.fd < 0)
return FALSE;
/* We share a routine with the mainline transport to handle header add/remove/rewrites,
@@ -1342,10 +1457,12 @@ if(cutthrough_fd < 0)
*/
HDEBUG(D_acl) debug_printf("----------- start cutthrough headers send -----------\n");
-if (!transport_headers_send(&cutthrough_addr, cutthrough_fd,
- cutthrough_addr.transport->add_headers, cutthrough_addr.transport->remove_headers,
+if (!transport_headers_send(&cutthrough.addr, cutthrough.fd,
+ cutthrough.addr.transport->add_headers,
+ cutthrough.addr.transport->remove_headers,
&cutthrough_write_chunk, TRUE,
- cutthrough_addr.transport->rewrite_rules, cutthrough_addr.transport->rewrite_existflags))
+ cutthrough.addr.transport->rewrite_rules,
+ cutthrough.addr.transport->rewrite_existflags))
return FALSE;
HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
@@ -1354,9 +1471,9 @@ return TRUE;
static void
-close_cutthrough_connection( const char * why )
+close_cutthrough_connection(const char * why)
{
-if(cutthrough_fd >= 0)
+if(cutthrough.fd >= 0)
{
/* We could be sending this after a bunch of data, but that is ok as
the only way to cancel the transfer in dataphase is to drop the tcp
@@ -1371,18 +1488,18 @@ if(cutthrough_fd >= 0)
#ifdef SUPPORT_TLS
tls_close(FALSE, TRUE);
#endif
- (void)close(cutthrough_fd);
- cutthrough_fd= -1;
+ (void)close(cutthrough.fd);
+ cutthrough.fd = -1;
HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown (%s) ------------\n", why);
}
ctblock.ptr = ctbuffer;
}
void
-cancel_cutthrough_connection( const char * why )
+cancel_cutthrough_connection(const char * why)
{
close_cutthrough_connection(why);
-cutthrough_delivery= FALSE;
+cutthrough.delivery = FALSE;
}
@@ -1394,33 +1511,45 @@ cutthrough_delivery= FALSE;
Return smtp response-class digit.
*/
uschar *
-cutthrough_finaldot( void )
+cutthrough_finaldot(void)
{
+uschar res;
+address_item * addr;
HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP>> .\n");
/* Assume data finshed with new-line */
-if(!cutthrough_puts(US".", 1) || !cutthrough_put_nl() || !cutthrough_flush_send())
- return cutthrough_addr.message;
+if( !cutthrough_puts(US".", 1)
+ || !cutthrough_put_nl()
+ || !cutthrough_flush_send()
+ )
+ return cutthrough.addr.message;
-switch(cutthrough_response('2', &cutthrough_addr.message))
+res = cutthrough_response('2', &cutthrough.addr.message);
+for (addr = &cutthrough.addr; addr; addr = addr->next)
{
- case '2':
- delivery_log(LOG_MAIN, &cutthrough_addr, (int)'>', NULL);
- close_cutthrough_connection("delivered");
- break;
+ addr->message = cutthrough.addr.message;
+ switch(res)
+ {
+ case '2':
+ delivery_log(LOG_MAIN, addr, (int)'>', NULL);
+ close_cutthrough_connection("delivered");
+ break;
- case '4':
- delivery_log(LOG_MAIN, &cutthrough_addr, 0, US"tmp-reject from cutthrough after DATA:");
- break;
+ case '4':
+ delivery_log(LOG_MAIN, addr, 0,
+ US"tmp-reject from cutthrough after DATA:");
+ break;
- case '5':
- delivery_log(LOG_MAIN|LOG_REJECT, &cutthrough_addr, 0, US"rejected after DATA:");
- break;
+ case '5':
+ delivery_log(LOG_MAIN|LOG_REJECT, addr, 0,
+ US"rejected after DATA:");
+ break;
- default:
- break;
+ default:
+ break;
+ }
}
- return cutthrough_addr.message;
+return cutthrough.addr.message;
}
diff --git a/test/confs/5400 b/test/confs/5400
index 09a0aafcf..5948ce8d2 100644
--- a/test/confs/5400
+++ b/test/confs/5400
@@ -8,6 +8,8 @@ log_file_path = DIR/spool/log/%slog
gecos_pattern = ""
gecos_name = CALLER_NAME
+log_selector = +received_recipients
+
# ----- Main settings -----
domainlist local_domains = test.ex : *.test.ex
@@ -27,12 +29,18 @@ ar:
begin routers
+dns:
+ driver = dnslookup
+ domains = localhost.test.ex : thishost.test.ex
+ self = send
+ transport = smtp
+
all:
driver = manualroute
domains = ! +local_domains
- route_list = * 127.0.0.1
+ route_list = special.com HOSTIPV4 ; * 127.0.0.1
self = send
- transport = smtp
+ transport = ${if eq {special_tpt}{$local_part} {smtp2}{smtp}}
headers_remove = X-hdr-rtr
headers_add = X-hdr-rtr-new: $h_X-hdr-rtr:+++
no_more
@@ -48,5 +56,10 @@ smtp:
port = PORT_S
headers_add = ${if def:h_X-hdr-rtr {X-hdr-tpt-new: new} {}}
+smtp2:
+ driver = smtp
+ interface = HOSTIPV4
+ port = PORT_S
+
# End
diff --git a/test/log/5400 b/test/log/5400
index 6b51348c3..c6f366272 100644
--- a/test/log/5400
+++ b/test/log/5400
@@ -1,18 +1,54 @@
1999-03-02 09:44:33 rcpt for userx@domain.com
1999-03-02 09:44:33 10HmaX-0005vi-00 >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain.com
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 rcpt for userz@domain.com
1999-03-02 09:44:33 10HmaY-0005vi-00 >> userz@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userz@domain.com
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
1999-03-02 09:44:33 rcpt for usery@domain.com
1999-03-02 09:44:33 rcpt for userx@domain.com
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => usery@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
-1999-03-02 09:44:33 10HmaZ-0005vi-00 -> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 >> usery@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for usery@domain.com userx@domain.com
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
1999-03-02 09:44:33 rcpt for userx@domain.com
1999-03-02 09:44:33 10HmbA-0005vi-00 >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain.com
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for no@domain.com
+1999-03-02 09:44:33 rcpt for userx@domain.com
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for no@domain.com userx@domain.com
+1999-03-02 09:44:33 10HmbB-0005vi-00 => no@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbB-0005vi-00 -> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for userx@domain.com
+1999-03-02 09:44:33 rcpt for no@domain.com
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain.com no@domain.com
+1999-03-02 09:44:33 10HmbC-0005vi-00 => userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbC-0005vi-00 -> no@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for userx@domain.com
+1999-03-02 09:44:33 rcpt for special_tpt@domain.com
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain.com special_tpt@domain.com
+1999-03-02 09:44:33 10HmbD-0005vi-00 => userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbD-0005vi-00 => special_tpt@domain.com R=all T=smtp2 H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for userx@domain1.com
+1999-03-02 09:44:33 rcpt for usery@domain2.com
+1999-03-02 09:44:33 10HmbE-0005vi-00 >> usery@domain2.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbE-0005vi-00 >> userx@domain1.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain1.com usery@domain2.com
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for userx@domain.com
+1999-03-02 09:44:33 rcpt for usery@special.com
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain.com usery@special.com
+1999-03-02 09:44:33 10HmbF-0005vi-00 => userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbF-0005vi-00 => usery@special.com R=all T=smtp H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK"
+1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for userx@localhost.test.ex
+1999-03-02 09:44:33 rcpt for usery@thishost.test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 >> usery@thishost.test.ex R=dns T=smtp H=localhost.test.ex [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbG-0005vi-00 >> userx@localhost.test.ex R=dns T=smtp H=localhost.test.ex [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@localhost.test.ex usery@thishost.test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
diff --git a/test/scripts/5400-cutthrough/5400 b/test/scripts/5400-cutthrough/5400
index 3e56b43b8..79072d749 100644
--- a/test/scripts/5400-cutthrough/5400
+++ b/test/scripts/5400-cutthrough/5400
@@ -16,7 +16,7 @@ DATA
QUIT
250 OK
****
-exim -d-all+acl+transport -bs
+exim -bs
EHLO myhost.test.ex
MAIL FROM:<CALLER@myhost.test.ex>
RCPT TO:<userx@domain.com>
@@ -43,7 +43,7 @@ DATA
QUIT
250 OK
****
-exim -d-all+acl+transport -bs
+exim -bs
EHLO myhost.test.ex
MAIL FROM:<CALLER@myhost.test.ex>
RCPT TO:<userz@domain.com>
@@ -52,8 +52,8 @@ DATA
.
QUIT
****
-# cutthrough cancelled by multiple recipients
-server PORT_S 2
+# cutthrough for 2 recipients in one domain
+server PORT_S
220 ESMTP
EHLO
250 OK
@@ -61,8 +61,32 @@ MAIL FROM:
250 Sender OK
RCPT TO:
250 Recipient OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
QUIT
-*eof
+250 OK
+****
+exim -bs
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<usery@domain.com>
+RCPT TO:<userx@domain.com>
+DATA
+
+.
+QUIT
+****
+#
+#
+#
+#
+#
+# cutthrough_delivery basic operation, again
+server PORT_S
220 ESMTP
EHLO
250 OK
@@ -70,8 +94,53 @@ MAIL FROM:
250 Sender OK
RCPT TO:
250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@domain.com>
+DATA
+X-hdr-rtr: qqq
+X-hdr-tpt: zzz
+
+body
+.
+QUIT
+****
+#
+#
+#
+#
+# cutthrough for 2 recipients in one domain
+# first one denied
+# so we get a 2nd conn with the traditional delivery
+# (for both because it's not a real verify=recipient)
+server PORT_S 2
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
RCPT TO:
-250 Recipient OK
+550 Not that one
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-1
+RCPT TO:
+250 ok rcpt-2
DATA
354 Send data
.
@@ -79,23 +148,138 @@ DATA
QUIT
250 OK
****
-exim -d-all+acl+transport -bs
+exim -bs
EHLO myhost.test.ex
MAIL FROM:<CALLER@myhost.test.ex>
-RCPT TO:<usery@domain.com>
+RCPT TO:<no@domain.com>
RCPT TO:<userx@domain.com>
DATA
.
QUIT
****
-sleep 1
#
#
#
#
#
-# cutthrough_delivery basic operation, again
+# cutthrough for 2 recipients in one domain
+# second one denied
+# so we get a 2nd conn with the traditional delivery
+# (for both because it's not a real verify=recipient)
+server PORT_S 2
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 first recipient ok
+RCPT TO:
+550 Not that one
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-1
+RCPT TO:
+250 ok rcpt-2
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@domain.com>
+RCPT TO:<no@domain.com>
+DATA
+
+.
+QUIT
+****
+#
+#
+#
+#
+#
+# cutthrough for 2 recipients in one domain
+# second one uses a different transport
+# so we get a 2nd conn with 2nd rcpt, doing the fake verify
+# then 3rd & 4th conns with the traditional deliveries on the different transports
+server PORT_S 4
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 first recipient ok
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 second recipient ok
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-1
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-2
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@domain.com>
+RCPT TO:<special_tpt@domain.com>
+DATA
+
+.
+QUIT
+****
+#
+#
+#
+#
+#
+# cutthrough for 2 recipients in different domains, handled by the same tpt & host
server PORT_S
220 ESMTP
EHLO
@@ -103,7 +287,9 @@ EHLO
MAIL FROM:
250 Sender OK
RCPT TO:
-250 Recipient OK
+250 ok rcpt-1
+RCPT TO:
+250 ok rcpt-2
DATA
354 Send data
.
@@ -111,15 +297,120 @@ DATA
QUIT
250 OK
****
-exim -d-all+acl+transport -bs
+exim -bs
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@domain1.com>
+RCPT TO:<usery@domain2.com>
+DATA
+
+.
+QUIT
+****
+#
+#
+#
+#
+#
+# cutthrough for 2 recipients in different domains, handled by the same tpt but different hosts
+# so we get a 2nd conn with 2nd rcpt, doing the fake verify
+# then 3rd & 4th conns with the traditional deliveries on the different transports
+server PORT_S 4
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 first recipient ok
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 second recipient ok
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-1
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+*eof
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-2
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs
EHLO myhost.test.ex
MAIL FROM:<CALLER@myhost.test.ex>
RCPT TO:<userx@domain.com>
+RCPT TO:<usery@special.com>
+DATA
+
+.
+QUIT
+****
+#
+#
+#
+#
+#
+# cutthrough for 2 recipients in different domains, handled by the same tpt & host
+# but via a dnslookup router (all previous were manualroute)
+server PORT_S
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 ok rcpt-1
+RCPT TO:
+250 ok rcpt-2
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@localhost.test.ex>
+RCPT TO:<usery@thishost.test.ex>
DATA
-X-hdr-rtr: qqq
-X-hdr-tpt: zzz
-body
.
QUIT
****
+#
+#
+#
+#
+#
+sleep 1
diff --git a/test/stderr/5400 b/test/stderr/5400
deleted file mode 100644
index 9fa77d5f2..000000000
--- a/test/stderr/5400
+++ /dev/null
@@ -1,235 +0,0 @@
-Exim version x.yz ....
-configuration file is TESTSUITE/test-config
-admin user
-LOG: smtp_connection MAIN
- SMTP connection from CALLER
-using ACL "ar"
-processing "accept"
-check control = cutthrough_delivery
-check logwrite = rcpt for $local_part@$domain
- = rcpt for userx@domain.com
-LOG: MAIN
- rcpt for userx@domain.com
-created log directory TESTSUITE/spool/log
-accept: condition test succeeded in ACL "ar"
-end of ACL "ar": ACCEPT
------------ start cutthrough setup ------------
-Connecting to 127.0.0.1 [127.0.0.1]:1224 from ip4.ip4.ip4.ip4 ... connected
- SMTP<< 220 ESMTP
- SMTP>> EHLO myhost.test.ex
- SMTP<< 250 OK
- SMTP>> MAIL FROM:<CALLER@myhost.test.ex>
- SMTP<< 250 Sender OK
- SMTP>> RCPT TO:<userx@domain.com>
- SMTP<< 250 Recipient OK
------------ end cutthrough setup ------------
-processing "accept"
-accept: condition test succeeded in inline ACL
-end of inline ACL: ACCEPT
- SMTP>> DATA
- SMTP<< 354 Send data
------------ start cutthrough headers send -----------
-added header line(s):
-X-hdr-rtr-new: +++
----
------------ done cutthrough headers send ------------
- SMTP>> .
- SMTP<< 250 OK
-LOG: MAIN
- >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
- SMTP>> QUIT
------------ cutthrough shutdown (delivered) ------------
-LOG: MAIN
- <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-LOG: MAIN
- Completed
-LOG: smtp_connection MAIN
- SMTP connection from CALLER closed by QUIT
->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
-Exim version x.yz ....
-configuration file is TESTSUITE/test-config
-admin user
-LOG: smtp_connection MAIN
- SMTP connection from CALLER
-using ACL "ar"
-processing "accept"
-check control = cutthrough_delivery
-check logwrite = rcpt for $local_part@$domain
- = rcpt for userz@domain.com
-LOG: MAIN
- rcpt for userz@domain.com
-accept: condition test succeeded in ACL "ar"
-end of ACL "ar": ACCEPT
------------ start cutthrough setup ------------
-Connecting to 127.0.0.1 [127.0.0.1]:1224 from ip4.ip4.ip4.ip4 ... connected
- SMTP<< 220 SMTP only spoken here
- SMTP>> EHLO myhost.test.ex
- SMTP<< 550 Not here, mate
- SMTP>> HELO myhost.test.ex
- SMTP<< 250 OK
- SMTP>> MAIL FROM:<CALLER@myhost.test.ex>
- SMTP<< 250 Sender OK
- SMTP>> RCPT TO:<userz@domain.com>
- SMTP<< 250 Recipient OK
------------ end cutthrough setup ------------
-processing "accept"
-accept: condition test succeeded in inline ACL
-end of inline ACL: ACCEPT
- SMTP>> DATA
- SMTP<< 354 Send data
------------ start cutthrough headers send -----------
-added header line(s):
-X-hdr-rtr-new: +++
----
------------ done cutthrough headers send ------------
- SMTP>> .
- SMTP<< 250 OK
-LOG: MAIN
- >> userz@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
- SMTP>> QUIT
------------ cutthrough shutdown (delivered) ------------
-LOG: MAIN
- <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-LOG: MAIN
- Completed
-LOG: smtp_connection MAIN
- SMTP connection from CALLER closed by QUIT
->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
-Exim version x.yz ....
-configuration file is TESTSUITE/test-config
-admin user
-LOG: smtp_connection MAIN
- SMTP connection from CALLER
-using ACL "ar"
-processing "accept"
-check control = cutthrough_delivery
-check logwrite = rcpt for $local_part@$domain
- = rcpt for usery@domain.com
-LOG: MAIN
- rcpt for usery@domain.com
-accept: condition test succeeded in ACL "ar"
-end of ACL "ar": ACCEPT
------------ start cutthrough setup ------------
-Connecting to 127.0.0.1 [127.0.0.1]:1224 from ip4.ip4.ip4.ip4 ... connected
- SMTP<< 220 ESMTP
- SMTP>> EHLO myhost.test.ex
- SMTP<< 250 OK
- SMTP>> MAIL FROM:<CALLER@myhost.test.ex>
- SMTP<< 250 Sender OK
- SMTP>> RCPT TO:<usery@domain.com>
- SMTP<< 250 Recipient OK
------------ end cutthrough setup ------------
-using ACL "ar"
-processing "accept"
-check control = cutthrough_delivery
-check logwrite = rcpt for $local_part@$domain
- = rcpt for userx@domain.com
-LOG: MAIN
- rcpt for userx@domain.com
-accept: condition test succeeded in ACL "ar"
-end of ACL "ar": ACCEPT
- SMTP>> QUIT
------------ cutthrough shutdown (more than one recipient) ------------
-LOG: MAIN
- <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-LOG: smtp_connection MAIN
- SMTP connection from CALLER closed by QUIT
->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
-Exim version x.yz ....
-configuration file is TESTSUITE/test-config
-trusted user
-admin user
->>>>>>>>>>>>>>>> Remote deliveries >>>>>>>>>>>>>>>>
---------> usery@domain.com <--------
-smtp transport entered
- usery@domain.com
- userx@domain.com
-checking status of 127.0.0.1
-127.0.0.1 [127.0.0.1]:1111 status = usable
-delivering 10HmaZ-0005vi-00 to 127.0.0.1 [127.0.0.1] (usery@domain.com, ...)
-Connecting to 127.0.0.1 [127.0.0.1]:1224 from ip4.ip4.ip4.ip4 ... connected
- SMTP<< 220 ESMTP
- SMTP>> EHLO myhost.test.ex
- SMTP<< 250 OK
-not using PIPELINING
-use_dsn=0
- SMTP>> MAIL FROM:<CALLER@myhost.test.ex>
- SMTP<< 250 Sender OK
- SMTP>> RCPT TO:<usery@domain.com>
- SMTP<< 250 Recipient OK
- SMTP>> RCPT TO:<userx@domain.com>
- SMTP<< 250 Recipient OK
- SMTP>> DATA
- SMTP<< 354 Send data
- SMTP>> writing message and terminating "."
-added header line(s):
-X-hdr-rtr-new: +++
----
-writing data block fd=dddd size=sss timeout=300
- SMTP<< 250 OK
-ok=1 send_quit=1 send_rset=0 continue_more=0 yield=0 first_address is NULL
-transport_check_waiting entered
- sequence=1 local_max=500 global_max=-1
-no messages waiting for 127.0.0.1
- SMTP>> QUIT
-Leaving smtp transport
-LOG: MAIN
- => usery@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
-LOG: MAIN
- -> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
-LOG: MAIN
- Completed
->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
-Exim version x.yz ....
-configuration file is TESTSUITE/test-config
-admin user
-LOG: smtp_connection MAIN
- SMTP connection from CALLER
-using ACL "ar"
-processing "accept"
-check control = cutthrough_delivery
-check logwrite = rcpt for $local_part@$domain
- = rcpt for userx@domain.com
-LOG: MAIN
- rcpt for userx@domain.com
-accept: condition test succeeded in ACL "ar"
-end of ACL "ar": ACCEPT
------------ start cutthrough setup ------------
-Connecting to 127.0.0.1 [127.0.0.1]:1224 from ip4.ip4.ip4.ip4 ... connected
- SMTP<< 220 ESMTP
- SMTP>> EHLO myhost.test.ex
- SMTP<< 250 OK
- SMTP>> MAIL FROM:<CALLER@myhost.test.ex>
- SMTP<< 250 Sender OK
- SMTP>> RCPT TO:<userx@domain.com>
- SMTP<< 250 Recipient OK
------------ end cutthrough setup ------------
-processing "accept"
-accept: condition test succeeded in inline ACL
-end of inline ACL: ACCEPT
- SMTP>> DATA
- SMTP<< 354 Send data
------------ start cutthrough headers send -----------
-removed header line:
-X-hdr-rtr: qqq
----
-added header line(s):
-X-hdr-rtr-new: +++
----
-added header line:
-X-hdr-tpt-new: new
----
------------ done cutthrough headers send ------------
- SMTP>> .
- SMTP<< 250 OK
-LOG: MAIN
- >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
- SMTP>> QUIT
------------ cutthrough shutdown (delivered) ------------
-LOG: MAIN
- <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-LOG: MAIN
- Completed
-LOG: smtp_connection MAIN
- SMTP connection from CALLER closed by QUIT
->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
diff --git a/test/stdout/5400 b/test/stdout/5400
index 4895072a3..3452a9cc1 100644
--- a/test/stdout/5400
+++ b/test/stdout/5400
@@ -43,6 +43,78 @@
354 Enter message, ending with "." on a line by itself
250 OK id=10HmbA-0005vi-00
221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at myhost.test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbB-0005vi-00
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at myhost.test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbC-0005vi-00
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at myhost.test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbD-0005vi-00
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at myhost.test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbE-0005vi-00
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at myhost.test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbF-0005vi-00
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at myhost.test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbG-0005vi-00
+221 myhost.test.ex closing connection
******** SERVER ********
Listening on port 1224 ...
@@ -108,17 +180,6 @@ MAIL FROM:<CALLER@myhost.test.ex>
250 Sender OK
RCPT TO:<usery@domain.com>
250 Recipient OK
-QUIT
-Expected EOF read from client
-Listening on port 1224 ...
-Connection request from [ip4.ip4.ip4.ip4]
-220 ESMTP
-EHLO myhost.test.ex
-250 OK
-MAIL FROM:<CALLER@myhost.test.ex>
-250 Sender OK
-RCPT TO:<usery@domain.com>
-250 Recipient OK
RCPT TO:<userx@domain.com>
250 Recipient OK
DATA
@@ -166,3 +227,284 @@ body
QUIT
250 OK
End of script
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<no@domain.com>
+550 Not that one
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<no@domain.com>
+250 ok rcpt-1
+RCPT TO:<userx@domain.com>
+250 ok rcpt-2
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.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@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+End of script
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 first recipient ok
+RCPT TO:<no@domain.com>
+550 Not that one
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 ok rcpt-1
+RCPT TO:<no@domain.com>
+250 ok rcpt-2
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbC-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbC-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+End of script
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 first recipient ok
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<special_tpt@domain.com>
+250 second recipient ok
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 ok rcpt-1
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbD-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbD-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<special_tpt@domain.com>
+250 ok rcpt-2
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbD-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbD-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+End of script
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain1.com>
+250 ok rcpt-1
+RCPT TO:<usery@domain2.com>
+250 ok rcpt-2
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbE-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbE-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+End of script
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 first recipient ok
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<usery@special.com>
+250 second recipient ok
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 ok rcpt-1
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbF-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbF-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+Expected EOF read from client
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<usery@special.com>
+250 ok rcpt-2
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbF-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbF-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+.
+250 OK
+QUIT
+250 OK
+End of script
+Listening on port 1224 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@localhost.test.ex>
+250 ok rcpt-1
+RCPT TO:<usery@thishost.test.ex>
+250 ok rcpt-2
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+ by myhost.test.ex with local-esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbG-0005vi-00; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbG-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+.
+250 OK
+QUIT
+250 OK
+End of script