Support transport-added headers under cutthrough delivery. Bug 1431
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 16 Mar 2014 17:22:56 +0000 (17:22 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 16 Mar 2014 17:22:56 +0000 (17:22 +0000)
13 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/functions.h
src/src/transport.c
src/src/verify.c
test/confs/5400
test/log/5400
test/scripts/5400-cutthrough/5400
test/scripts/5410-cutthrough-OpenSSL/5410
test/stderr/5400
test/stderr/5401
test/stderr/5410
test/stdout/5400

index ae4d75ecb924398e4fe613df4f602af918fe83d7..2b055c3e9978603326c1dcce571bea511d3eab63 100644 (file)
@@ -27330,8 +27330,12 @@ from one SMTP connection to another.  If a recipient-verify callout connection i
 requested in the same ACL it is held open and used for the data, otherwise one is made
 after the ACL completes.
 
 requested in the same ACL it is held open and used for the data, otherwise one is made
 after the ACL completes.
 
-Note that routers are used in verify mode.  Note also that headers cannot be
+Note that routers are used in verify mode,
+and cannot depend on content of received headers.
+Note also that headers cannot be
 modified by any of the post-data ACLs (DATA, MIME and DKIM).
 modified by any of the post-data ACLs (DATA, MIME and DKIM).
+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.
 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.
index c29f21cbf5f95691c924b37b09f926db9b8fd21f..8a55ceea9d6eeea9e82f623f9fe409695e530e51 100644 (file)
@@ -56,7 +56,11 @@ JH/06 Log outbound-TLS and port details, subject to log selectors, for a
 
 JH/07 Add malware type "sock" for talking to simple daemon.
 
 
 JH/07 Add malware type "sock" for talking to simple daemon.
 
-JH/08 Bugzilla 1371: Add tls_{,try_}verify_hosts to smtp transport. OpenSSL only.
+JH/08 Bugzilla 1371: Add tls_{,try_}verify_hosts to smtp transport.
+      OpenSSL only.
+
+JH/09 Bugzilla 1431: Support (with limitations) headers_add/headers_remove in
+      routers/transports under cutthrough routing.
 
 
 Exim version 4.82
 
 
 Exim version 4.82
index e92c2455f342e5366af62e7d68a7f82aa0ba0d20..3959615305b62da045033cc34f781fb3b30b6252 100644 (file)
@@ -384,6 +384,8 @@ extern BOOL    transport_set_up_command(uschar ***, uschar *, BOOL, int,
 extern void    transport_update_waiting(host_item *, uschar *);
 extern BOOL    transport_write_block(int, uschar *, int);
 extern BOOL    transport_write_string(int, const char *, ...);
 extern void    transport_update_waiting(host_item *, uschar *);
 extern BOOL    transport_write_block(int, uschar *, int);
 extern BOOL    transport_write_string(int, const char *, ...);
+extern BOOL    transport_headers_send(address_item *, int, uschar *, uschar *,
+                 BOOL (*)(int, uschar *, int, BOOL), BOOL, rewrite_rule *, int);
 extern BOOL    transport_write_message(address_item *, int, int, int, uschar *,
                  uschar *, uschar *, uschar *, rewrite_rule *, int);
 extern void    tree_add_duplicate(uschar *, address_item *);
 extern BOOL    transport_write_message(address_item *, int, int, int, uschar *,
                  uschar *, uschar *, uschar *, rewrite_rule *, int);
 extern void    tree_add_duplicate(uschar *, address_item *);
index ec4d0da92eadc6f27801e13f8c909a50490401c6..549da469423d3c84fed4642c6677db18cfd4e113 100644 (file)
@@ -600,6 +600,175 @@ return write_chunk(fd, pp->address, Ustrlen(pp->address), use_crlf);
 
 
 
 
 
 
+/* Add/remove/rewwrite headers, and send them plus the empty-line sparator.
+
+Globals:
+  header_list
+
+Arguments:
+  addr                  (chain of) addresses (for extra headers), or NULL;
+                          only the first address is used
+  fd                    file descriptor to write the message to
+  sendfn               function for output
+  use_crlf             turn NL into CR LF
+  rewrite_rules         chain of header rewriting rules
+  rewrite_existflags    flags for the rewriting rules
+
+Returns:                TRUE on success; FALSE on failure.
+*/
+BOOL
+transport_headers_send(address_item *addr, int fd, uschar *add_headers, uschar *remove_headers,
+  BOOL (*sendfn)(int fd, uschar * s, int len, BOOL use_crlf),
+  BOOL use_crlf, rewrite_rule *rewrite_rules, int rewrite_existflags)
+{
+header_line *h;
+
+/* Then the message's headers. Don't write any that are flagged as "old";
+that means they were rewritten, or are a record of envelope rewriting, or
+were removed (e.g. Bcc). If remove_headers is not null, skip any headers that
+match any entries therein. Then check addr->p.remove_headers too, provided that
+addr is not NULL. */
+
+if (remove_headers)
+  {
+  uschar *s = expand_string(remove_headers);
+  if (!s && !expand_string_forcedfail)
+    {
+    errno = ERRNO_CHHEADER_FAIL;
+    return FALSE;
+    }
+  remove_headers = s;
+  }
+
+for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
+  {
+  int i;
+  uschar *list = remove_headers;
+
+  BOOL include_header = TRUE;
+
+  for (i = 0; i < 2; i++)    /* For remove_headers && addr->p.remove_headers */
+    {
+    if (list)
+      {
+      int sep = ':';         /* This is specified as a colon-separated list */
+      uschar *s, *ss;
+      uschar buffer[128];
+      while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+       {
+       int len = Ustrlen(s);
+       if (strncmpic(h->text, s, len) != 0) continue;
+       ss = h->text + len;
+       while (*ss == ' ' || *ss == '\t') ss++;
+       if (*ss == ':') break;
+       }
+      if (s != NULL) { include_header = FALSE; break; }
+      }
+    if (addr != NULL) list = addr->p.remove_headers;
+    }
+
+  /* If this header is to be output, try to rewrite it if there are rewriting
+  rules. */
+
+  if (include_header)
+    {
+    if (rewrite_rules)
+      {
+      void *reset_point = store_get(0);
+      header_line *hh;
+
+      if ((hh = rewrite_header(h, NULL, NULL, rewrite_rules, rewrite_existflags, FALSE)))
+       {
+       if (!sendfn(fd, hh->text, hh->slen, use_crlf)) return FALSE;
+       store_reset(reset_point);
+       continue;     /* With the next header line */
+       }
+      }
+
+    /* Either no rewriting rules, or it didn't get rewritten */
+
+    if (!sendfn(fd, h->text, h->slen, use_crlf)) return FALSE;
+    }
+
+  /* Header removed */
+
+  else
+    {
+    DEBUG(D_transport) debug_printf("removed header line:\n%s---\n", h->text);
+    }
+  }
+
+/* Add on any address-specific headers. If there are multiple addresses,
+they will all have the same headers in order to be batched. The headers
+are chained in reverse order of adding (so several addresses from the
+same alias might share some of them) but we want to output them in the
+opposite order. This is a bit tedious, but there shouldn't be very many
+of them. We just walk the list twice, reversing the pointers each time,
+but on the second time, write out the items.
+
+Headers added to an address by a router are guaranteed to end with a newline.
+*/
+
+if (addr)
+  {
+  int i;
+  header_line *hprev = addr->p.extra_headers;
+  header_line *hnext;
+  for (i = 0; i < 2; i++)
+    {
+    for (h = hprev, hprev = NULL; h != NULL; h = hnext)
+      {
+      hnext = h->next;
+      h->next = hprev;
+      hprev = h;
+      if (i == 1)
+       {
+       if (!sendfn(fd, h->text, h->slen, use_crlf)) return FALSE;
+       DEBUG(D_transport)
+         debug_printf("added header line(s):\n%s---\n", h->text);
+       }
+      }
+    }
+  }
+
+/* If a string containing additional headers exists, expand it and write
+out the result. This is done last so that if it (deliberately or accidentally)
+isn't in header format, it won't mess up any other headers. An empty string
+or a forced expansion failure are noops. An added header string from a
+transport may not end with a newline; add one if it does not. */
+
+if (add_headers)
+  {
+  uschar *s = expand_string(add_headers);
+  if (s == NULL)
+    {
+    if (!expand_string_forcedfail)
+      { errno = ERRNO_CHHEADER_FAIL; return FALSE; }
+    }
+  else
+    {
+    int len = Ustrlen(s);
+    if (len > 0)
+      {
+      if (!sendfn(fd, s, len, use_crlf)) return FALSE;
+      if (s[len-1] != '\n' && !sendfn(fd, US"\n", 1, use_crlf))
+       return FALSE;
+      DEBUG(D_transport)
+       {
+       debug_printf("added header line(s):\n%s", s);
+       if (s[len-1] != '\n') debug_printf("\n");
+       debug_printf("---\n");
+       }
+      }
+    }
+  }
+
+/* Separate headers from body with a blank line */
+
+return sendfn(fd, US"\n", 1, use_crlf);
+}
+
+
 /*************************************************
 *                Write the message               *
 *************************************************/
 /*************************************************
 *                Write the message               *
 *************************************************/
@@ -747,154 +916,9 @@ if ((options & topt_no_headers) == 0)
   were removed (e.g. Bcc). If remove_headers is not null, skip any headers that
   match any entries therein. Then check addr->p.remove_headers too, provided that
   addr is not NULL. */
   were removed (e.g. Bcc). If remove_headers is not null, skip any headers that
   match any entries therein. Then check addr->p.remove_headers too, provided that
   addr is not NULL. */
-
-  if (remove_headers != NULL)
-    {
-    uschar *s = expand_string(remove_headers);
-    if (s == NULL && !expand_string_forcedfail)
-      {
-      errno = ERRNO_CHHEADER_FAIL;
-      return FALSE;
-      }
-    remove_headers = s;
-    }
-
-  for (h = header_list; h != NULL; h = h->next)
-    {
-    int i;
-    uschar *list = NULL;
-    BOOL include_header;
-
-    if (h->type == htype_old) continue;
-
-    include_header = TRUE;
-    list = remove_headers;
-
-    for (i = 0; i < 2; i++)    /* For remove_headers && addr->p.remove_headers */
-      {
-      if (list != NULL)
-        {
-        int sep = ':';         /* This is specified as a colon-separated list */
-        uschar *s, *ss;
-        uschar buffer[128];
-        while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
-                != NULL)
-          {
-          int len = Ustrlen(s);
-          if (strncmpic(h->text, s, len) != 0) continue;
-          ss = h->text + len;
-          while (*ss == ' ' || *ss == '\t') ss++;
-          if (*ss == ':') break;
-          }
-        if (s != NULL) { include_header = FALSE; break; }
-        }
-      if (addr != NULL) list = addr->p.remove_headers;
-      }
-
-    /* If this header is to be output, try to rewrite it if there are rewriting
-    rules. */
-
-    if (include_header)
-      {
-      if (rewrite_rules != NULL)
-        {
-        void *reset_point = store_get(0);
-        header_line *hh =
-          rewrite_header(h, NULL, NULL, rewrite_rules, rewrite_existflags,
-            FALSE);
-        if (hh != NULL)
-          {
-          if (!write_chunk(fd, hh->text, hh->slen, use_crlf)) return FALSE;
-          store_reset(reset_point);
-          continue;     /* With the next header line */
-          }
-        }
-
-      /* Either no rewriting rules, or it didn't get rewritten */
-
-      if (!write_chunk(fd, h->text, h->slen, use_crlf)) return FALSE;
-      }
-
-    /* Header removed */
-
-    else
-      {
-      DEBUG(D_transport) debug_printf("removed header line:\n%s---\n",
-        h->text);
-      }
-    }
-
-  /* Add on any address-specific headers. If there are multiple addresses,
-  they will all have the same headers in order to be batched. The headers
-  are chained in reverse order of adding (so several addresses from the
-  same alias might share some of them) but we want to output them in the
-  opposite order. This is a bit tedious, but there shouldn't be very many
-  of them. We just walk the list twice, reversing the pointers each time,
-  but on the second time, write out the items.
-
-  Headers added to an address by a router are guaranteed to end with a newline.
-  */
-
-  if (addr != NULL)
-    {
-    int i;
-    header_line *hprev = addr->p.extra_headers;
-    header_line *hnext;
-    for (i = 0; i < 2; i++)
-      {
-      for (h = hprev, hprev = NULL; h != NULL; h = hnext)
-        {
-        hnext = h->next;
-        h->next = hprev;
-        hprev = h;
-        if (i == 1)
-          {
-          if (!write_chunk(fd, h->text, h->slen, use_crlf)) return FALSE;
-          DEBUG(D_transport)
-            debug_printf("added header line(s):\n%s---\n", h->text);
-          }
-        }
-      }
-    }
-
-  /* If a string containing additional headers exists, expand it and write
-  out the result. This is done last so that if it (deliberately or accidentally)
-  isn't in header format, it won't mess up any other headers. An empty string
-  or a forced expansion failure are noops. An added header string from a
-  transport may not end with a newline; add one if it does not. */
-
-  if (add_headers != NULL)
-    {
-    uschar *s = expand_string(add_headers);
-    if (s == NULL)
-      {
-      if (!expand_string_forcedfail)
-        {
-        errno = ERRNO_CHHEADER_FAIL;
-        return FALSE;
-        }
-      }
-    else
-      {
-      int len = Ustrlen(s);
-      if (len > 0)
-        {
-        if (!write_chunk(fd, s, len, use_crlf)) return FALSE;
-        if (s[len-1] != '\n' && !write_chunk(fd, US"\n", 1, use_crlf))
-          return FALSE;
-        DEBUG(D_transport)
-          {
-          debug_printf("added header line(s):\n%s", s);
-          if (s[len-1] != '\n') debug_printf("\n");
-          debug_printf("---\n");
-          }
-        }
-      }
-    }
-
-  /* Separate headers from body with a blank line */
-
-  if (!write_chunk(fd, US"\n", 1, use_crlf)) return FALSE;
+  if (!transport_headers_send(addr, fd, add_headers, remove_headers, &write_chunk,
+       use_crlf, rewrite_rules, rewrite_existflags))
+    return FALSE;
   }
 
 /* If the body is required, ensure that the data for check strings (formerly
   }
 
 /* If the body is required, ensure that the data for check strings (formerly
@@ -2157,4 +2181,6 @@ if (expand_arguments)
 return TRUE;
 }
 
 return TRUE;
 }
 
+/* vi: aw ai sw=2
+*/
 /* End of transport.c */
 /* End of transport.c */
index cd91b0560966474fb71c122dab31ce47926c2456..39f546ed6a7ab072020c410cf4ce9c25d86dc26c 100644 (file)
@@ -976,6 +976,7 @@ else
       {
       cutthrough_fd= outblock.sock;    /* We assume no buffer in use in the outblock */
       cutthrough_addr = *addr;         /* Save the address_item for later logging */
       {
       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->name =    host->name;
       cutthrough_addr.host_used->address = host->address;
       cutthrough_addr.host_used = store_get(sizeof(host_item));
       cutthrough_addr.host_used->name =    host->name;
       cutthrough_addr.host_used->address = host->address;
@@ -1244,27 +1245,43 @@ return cutthrough_response('3', NULL) == '3';
 }
 
 
 }
 
 
+/* fd and use_crlf args only to match write_chunk() */
+static BOOL
+cutthrough_write_chunk(int fd, uschar * s, int len, BOOL use_crlf)
+{
+uschar * s2;
+while(s && (s2 = Ustrchr(s, '\n')))
+ {
+ if(!cutthrough_puts(s, s2-s) || !cutthrough_put_nl())
+  return FALSE;
+ s = s2+1;
+ }
+return TRUE;
+}
+
+
 /* Buffered send of headers.  Return success boolean. */
 /* Expands newlines to wire format (CR,NL).           */
 /* Also sends header-terminating blank line.          */
 BOOL
 cutthrough_headers_send( void )
 {
 /* Buffered send of headers.  Return success boolean. */
 /* Expands newlines to wire format (CR,NL).           */
 /* Also sends header-terminating blank line.          */
 BOOL
 cutthrough_headers_send( void )
 {
-header_line * h;
-uschar * cp1, * cp2;
-
 if(cutthrough_fd < 0)
   return FALSE;
 
 if(cutthrough_fd < 0)
   return FALSE;
 
-for(h= header_list; h != NULL; h= h->next)
-  if(h->type != htype_old  &&  h->text != NULL)
-    for (cp1 = h->text; *cp1 && (cp2 = Ustrchr(cp1, '\n')); cp1 = cp2+1)
-      if(  !cutthrough_puts(cp1, cp2-cp1)
-        || !cutthrough_put_nl())
-        return FALSE;
+/* We share a routine with the mainline transport to handle header add/remove/rewrites,
+   but having a separate buffered-output function (for now)
+*/
+HDEBUG(D_acl) debug_printf("----------- start cutthrough headers send -----------\n");
 
 
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>>(nl)\n");
-return cutthrough_put_nl();
+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))
+  return FALSE;
+
+HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
+return TRUE;
 }
 
 
 }
 
 
@@ -3710,4 +3727,6 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
 return FAIL;
 }
 
 return FAIL;
 }
 
+/* vi: aw ai sw=2
+*/
 /* End of verify.c */
 /* End of verify.c */
index 8f2e8b585f1c0d5ae341c7e68e97cf4d7fc8c623..62466983c2884568e277583712200e6207e54eb9 100644 (file)
@@ -34,6 +34,8 @@ all:
   route_list = * 127.0.0.1
   self = send
   transport = smtp
   route_list = * 127.0.0.1
   self = send
   transport = smtp
+  headers_remove = X-hdr-rtr
+  headers_add =    X-hdr-rtr-new: $h_X-hdr-rtr:+++
   no_more
 
 
   no_more
 
 
@@ -45,6 +47,7 @@ smtp:
   driver = smtp
   interface = HOSTIPV4
   port = PORT_S
   driver = smtp
   interface = HOSTIPV4
   port = PORT_S
+  headers_add =  ${if def:h_X-hdr-rtr {X-hdr-tpt-new: new} {}}
 
 
 # End
 
 
 # End
index 59f948c5fdfeccb02628ab970e8b98b84547a7cb..6b51348c33bda4cea10b11d7d34f21e825bd3c58 100644 (file)
@@ -12,3 +12,7 @@
 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 Completed
 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 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 Completed
index 56d6fec7731323ded60616b8c58b49c68ef622bd..3e56b43b84e8e5413ec2c29be03d19dc4568dada 100644 (file)
@@ -26,8 +26,6 @@ DATA
 QUIT
 ****
 # cutthrough_delivery into HELO-only server
 QUIT
 ****
 # cutthrough_delivery into HELO-only server
-need_ipv4
-#
 server PORT_S
 220 SMTP only spoken here
 EHLO
 server PORT_S
 220 SMTP only spoken here
 EHLO
@@ -92,3 +90,36 @@ DATA
 QUIT
 ****
 sleep 1
 QUIT
 ****
 sleep 1
+#
+#
+#
+#
+#
+# cutthrough_delivery basic operation, again
+server PORT_S
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -d-all+acl+transport -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
+****
index 9f5ff7196aeb7c61bade5c1839dc7c5b75053835..5c9598c66bec99209deb493d4289d1036a683eef 100644 (file)
@@ -1,4 +1,4 @@
-# cutthrough_delivery to target oferring TLS
+# cutthrough_delivery to target offerring TLS
 exim -DSERVER=server -bd -oX PORT_D
 ****
 # this one should succeed
 exim -DSERVER=server -bd -oX PORT_D
 ****
 # this one should succeed
index 73934dd920a1a7aa95464d31fe10bca40344cd6c..29ff83b42626157428f84a2d845de67e8d45c6f1 100644 (file)
@@ -26,7 +26,11 @@ processing "accept"
 accept: condition test succeeded in inline ACL
   SMTP>> DATA
   SMTP<< 354 Send data
 accept: condition test succeeded in inline ACL
   SMTP>> DATA
   SMTP<< 354 Send data
-  SMTP>>(nl)
+----------- start cutthrough headers send -----------
+added header line(s):
+X-hdr-rtr-new: +++
+---
+----------- done cutthrough headers send ------------
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
@@ -69,7 +73,11 @@ processing "accept"
 accept: condition test succeeded in inline ACL
   SMTP>> DATA
   SMTP<< 354 Send data
 accept: condition test succeeded in inline ACL
   SMTP>> DATA
   SMTP<< 354 Send data
-  SMTP>>(nl)
+----------- start cutthrough headers send -----------
+added header line(s):
+X-hdr-rtr-new: +++
+---
+----------- done cutthrough headers send ------------
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
@@ -147,6 +155,9 @@ not using PIPELINING
   SMTP>> DATA
   SMTP<< 354 Send data
   SMTP>> writing message and terminating "."
   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
 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
@@ -162,3 +173,54 @@ LOG: MAIN
 LOG: MAIN
   Completed
 >>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
 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"
+----------- 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
+  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(s):
+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 >>>>>>>>>>>>>>>>
index 135c11ace3d2e79657302619d5912d655e5aa966..1bd14f8d52e1c8c26bfbbe3fd97ed3393f337110 100644 (file)
@@ -23,7 +23,8 @@ processing "accept"
 accept: condition test succeeded in inline ACL
   SMTP>> DATA
   SMTP<< 354 Send data
 accept: condition test succeeded in inline ACL
   SMTP>> DATA
   SMTP<< 354 Send data
-  SMTP>>(nl)
+----------- start cutthrough headers send -----------
+----------- done cutthrough headers send ------------
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
index 40ef77c4ae0957cf063f4424edb71e1e00e102cd..334301139792122ee7f4d28224e110f77cbbee7d 100644 (file)
@@ -137,7 +137,8 @@ expanding:
        for $received_for
    result: 
        for userx@domain.com
        for $received_for
    result: 
        for userx@domain.com
-PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+----------- start cutthrough headers send -----------
+----------- done cutthrough headers send ------------
 expanding: ${tod_full}
    result: Tue, 2 Mar 1999 09:44:33 +0000
   SMTP>> .
 expanding: ${tod_full}
    result: Tue, 2 Mar 1999 09:44:33 +0000
   SMTP>> .
@@ -270,7 +271,8 @@ expanding:
        for $received_for
    result: 
        for usery@domain.com
        for $received_for
    result: 
        for usery@domain.com
-PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+----------- start cutthrough headers send -----------
+----------- done cutthrough headers send ------------
 expanding: ${tod_full}
    result: Tue, 2 Mar 1999 09:44:33 +0000
   SMTP>> .
 expanding: ${tod_full}
    result: Tue, 2 Mar 1999 09:44:33 +0000
   SMTP>> .
@@ -403,7 +405,8 @@ expanding:
        for $received_for
    result: 
        for usery@domain.com
        for $received_for
    result: 
        for usery@domain.com
-PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+----------- start cutthrough headers send -----------
+----------- done cutthrough headers send ------------
 expanding: ${tod_full}
    result: Tue, 2 Mar 1999 09:44:33 +0000
   SMTP>> .
 expanding: ${tod_full}
    result: Tue, 2 Mar 1999 09:44:33 +0000
   SMTP>> .
index 74c2d235880815c38e94028bea36595666a30e22..4895072a3a0e24ea537bddface2e96ab12fe6523 100644 (file)
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmaZ-0005vi-00\r
 221 myhost.test.ex closing connection\r
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmaZ-0005vi-00\r
 221 myhost.test.ex closing connection\r
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at myhost.test.ex\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250 HELP\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmbA-0005vi-00\r
+221 myhost.test.ex closing connection\r
 
 ******** SERVER ********
 Listening on port 1224 ... 
 
 ******** SERVER ********
 Listening on port 1224 ... 
@@ -53,6 +64,7 @@ Received: from CALLER (helo=myhost.test.ex)
 Message-Id: <E10HmaX-0005vi-00@myhost.test.ex>
 From: CALLER_NAME <CALLER@myhost.test.ex>
 Date: Tue, 2 Mar 1999 09:44:33 +0000
 Message-Id: <E10HmaX-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
 
 .
 250 OK
@@ -80,6 +92,7 @@ Received: from CALLER (helo=myhost.test.ex)
 Message-Id: <E10HmaY-0005vi-00@myhost.test.ex>
 From: CALLER_NAME <CALLER@myhost.test.ex>
 Date: Tue, 2 Mar 1999 09:44:33 +0000
 Message-Id: <E10HmaY-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
 
 .
 250 OK
@@ -117,7 +130,37 @@ Received: from CALLER (helo=myhost.test.ex)
 Message-Id: <E10HmaZ-0005vi-00@myhost.test.ex>
 From: CALLER_NAME <CALLER@myhost.test.ex>
 Date: Tue, 2 Mar 1999 09:44:33 +0000
 Message-Id: <E10HmaZ-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 Recipient OK
+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 10HmbA-0005vi-00
+       for userx@domain.com; Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-tpt: zzz
+Message-Id: <E10HmbA-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: +++
+
 
 
+body
 .
 250 OK
 QUIT
 .
 250 OK
 QUIT