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.
 
-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).
+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.
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/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
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 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 *);
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               *
 *************************************************/
@@ -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. */
-
-  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
@@ -2157,4 +2181,6 @@ if (expand_arguments)
 return TRUE;
 }
 
+/* vi: aw ai sw=2
+*/
 /* 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_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;
@@ -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 )
 {
-header_line * h;
-uschar * cp1, * cp2;
-
 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;
 }
 
+/* vi: aw ai sw=2
+*/
 /* End of verify.c */
index 8f2e8b585f1c0d5ae341c7e68e97cf4d7fc8c623..62466983c2884568e277583712200e6207e54eb9 100644 (file)
@@ -34,6 +34,8 @@ all:
   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
 
 
@@ -45,6 +47,7 @@ smtp:
   driver = smtp
   interface = HOSTIPV4
   port = PORT_S
+  headers_add =  ${if def:h_X-hdr-rtr {X-hdr-tpt-new: new} {}}
 
 
 # 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 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
-need_ipv4
-#
 server PORT_S
 220 SMTP only spoken here
 EHLO
@@ -92,3 +90,36 @@ DATA
 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
index 73934dd920a1a7aa95464d31fe10bca40344cd6c..29ff83b42626157428f84a2d845de67e8d45c6f1 100644 (file)
@@ -26,7 +26,11 @@ processing "accept"
 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
@@ -69,7 +73,11 @@ processing "accept"
 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
@@ -147,6 +155,9 @@ not using PIPELINING
   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
@@ -162,3 +173,54 @@ LOG: MAIN
 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
-  SMTP>>(nl)
+----------- start cutthrough headers send -----------
+----------- done cutthrough headers send ------------
   SMTP>> .
   SMTP<< 250 OK
 LOG: MAIN
index 40ef77c4ae0957cf063f4424edb71e1e00e102cd..334301139792122ee7f4d28224e110f77cbbee7d 100644 (file)
@@ -137,7 +137,8 @@ expanding:
        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>> .
@@ -270,7 +271,8 @@ expanding:
        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>> .
@@ -403,7 +405,8 @@ expanding:
        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>> .
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
+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 ... 
@@ -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
+X-hdr-rtr-new: +++
 
 .
 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
+X-hdr-rtr-new: +++
 
 .
 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
+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