Merge branch 'CHUNKING'
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 6 Aug 2016 13:04:45 +0000 (14:04 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 6 Aug 2016 13:04:45 +0000 (14:04 +0100)
99 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/deliver.c
src/src/dkim.c
src/src/exim.c
src/src/functions.h
src/src/globals.c
src/src/globals.h
src/src/macros.h
src/src/readconf.c
src/src/receive.c
src/src/smtp_in.c
src/src/smtp_out.c
src/src/structs.h
src/src/tls-gnu.c
src/src/tls-openssl.c
src/src/transport.c
src/src/transports/autoreply.c
src/src/transports/lmtp.c
src/src/transports/pipe.c
src/src/transports/smtp.c
src/src/transports/smtp.h
src/src/verify.c
test/aux-var-src/tls_conf_prefix
test/confs/0564
test/confs/0611
test/confs/0900 [new file with mode: 0644]
test/confs/0901 [new symlink]
test/confs/0902 [new symlink]
test/confs/2090 [new symlink]
test/confs/2091 [new symlink]
test/confs/2190 [new symlink]
test/confs/2191 [new symlink]
test/confs/3414
test/confs/4509 [new symlink]
test/confs/5590 [new symlink]
test/confs/5591 [new symlink]
test/confs/5601
test/confs/5740
test/log/0900 [new file with mode: 0644]
test/log/0901 [new file with mode: 0644]
test/log/0902 [new file with mode: 0644]
test/log/2026
test/log/2090 [new file with mode: 0644]
test/log/2091 [new file with mode: 0644]
test/log/2190 [new file with mode: 0644]
test/log/2191 [new file with mode: 0644]
test/log/4509 [new file with mode: 0644]
test/log/5590 [new file with mode: 0644]
test/log/5591 [new file with mode: 0644]
test/scripts/0000-Basic/0900 [new file with mode: 0644]
test/scripts/0000-Basic/0901 [new file with mode: 0644]
test/scripts/0000-Basic/0902 [new file with mode: 0644]
test/scripts/2000-GnuTLS/2090 [new file with mode: 0644]
test/scripts/2000-GnuTLS/2091 [new file with mode: 0644]
test/scripts/2100-OpenSSL/2190 [new file with mode: 0644]
test/scripts/2100-OpenSSL/2191 [new symlink]
test/scripts/4500-Domain-Keys-Identified-Mail/4509 [new file with mode: 0644]
test/scripts/5500-PRDR/5590 [new file with mode: 0644]
test/scripts/5500-PRDR/5591 [new file with mode: 0644]
test/scripts/5500-PRDR/REQUIRES
test/src/server.c
test/stderr/0038
test/stderr/0043
test/stderr/0044
test/stderr/0070
test/stderr/0079
test/stderr/0080
test/stderr/0121
test/stderr/0138
test/stderr/0180
test/stderr/0243
test/stderr/0303
test/stderr/0371
test/stderr/0384
test/stderr/0487
test/stderr/0513
test/stderr/0524
test/stderr/0537
test/stderr/3000
test/stderr/3208
test/stderr/3400
test/stderr/3408
test/stderr/3410
test/stderr/3500
test/stderr/5204
test/stderr/5403
test/stderr/5410
test/stderr/5420
test/stdout/0547
test/stdout/0572
test/stdout/0900 [new file with mode: 0644]
test/stdout/0901 [new file with mode: 0644]
test/stdout/0902 [new file with mode: 0644]
test/stdout/2022
test/stdout/2090 [new file with mode: 0644]
test/stdout/2122
test/stdout/2190 [new file with mode: 0644]
test/stdout/5591 [new file with mode: 0644]

index 5ff976e..d18dd0c 100644 (file)
@@ -13816,6 +13816,7 @@ See also the &'Policy controls'& section above.
 .table2
 .row &%accept_8bitmime%&             "advertise 8BITMIME"
 .row &%auth_advertise_hosts%&        "advertise AUTH to these hosts"
+.row &%chunking_advertise_hosts%&    "advertise CHUNKING to these hosts"
 .row &%dsn_advertise_hosts%&         "advertise DSN extensions to these hosts"
 .row &%ignore_fromline_hosts%&       "allow &""From ""& from these hosts"
 .row &%ignore_fromline_local%&       "allow &""From ""& from local SMTP"
@@ -14373,6 +14374,15 @@ For non-SMTP input and for batched SMTP input, the test is done at start-up; on
 failure a message is written to stderr and Exim exits with a non-zero code, as
 it obviously cannot send an error message of any kind.
 
+.new
+.option chunking_advertise_hosts main "host list&!!" *
+.cindex CHUNKING advertisement
+.cindex "RFC 3030" "CHUNKING"
+The CHUNKING extension (RFC3030) will be advertised in the EHLO message to
+these hosts.
+Hosts may use the BDAT command as an alternate to DATA.
+.wen
+
 .option daemon_smtp_ports main string &`smtp`&
 .cindex "port" "for daemon"
 .cindex "TCP/IP" "setting listening ports"
@@ -23891,6 +23901,16 @@ connects. If authentication fails, Exim will try to transfer the message
 unauthenticated. See also &%hosts_require_auth%&, and chapter
 &<<CHAPSMTPAUTH>>& for details of authentication.
 
+.new
+.option hosts_try_chunking smtp "host list&!!" *
+.cindex CHUNKING "enabling, in client"
+.cindex BDAT "SMTP command"
+.cindex "RFC 3030" "CHUNKING"
+This option provides a list of server to which, provided they announce
+CHUNKING support, Exim will attempt to use BDAT commands rather than DATA.
+BDAT will not be used in conjuction with a transport filter.
+.wen
+
 .option hosts_try_prdr smtp "host list&!!" *
 .cindex "PRDR" "enabling, optional in client"
 This option provides a list of servers to which, provided they announce
@@ -27761,6 +27781,17 @@ received, before the final response to the DATA command is sent. This is
 the ACL specified by &%acl_smtp_data%&, which is the second ACL that is
 associated with the DATA command.
 
+.new
+.cindex CHUNKING "BDAT command"
+.cindex BDAT "SMTP command"
+.cindex "RFC 3030" CHUNKING
+If CHUNKING was advertised and a BDAT command sequence is received,
+the &%acl_smtp_predata%& ACL is not run.
+. XXX why not?  It should be possible, for the first BDAT.
+The &%acl_smtp_data%& is run after the last BDAT command and all of
+the data specified is received.
+.wen
+
 For both of these ACLs, it is not possible to reject individual recipients. An
 error response rejects the entire message. Unfortunately, it is known that some
 MTAs do not treat hard (5&'xx'&) responses to the DATA command (either
@@ -35646,10 +35677,12 @@ the following table:
 &`F   `&        sender address (on delivery lines)
 &`H   `&        host name and IP address
 &`I   `&        local interface used
+&`K   `&        CHUNKING extension used
 &`id  `&        message id for incoming message
 &`P   `&        on &`<=`& lines: protocol used
 &`    `&        on &`=>`& and &`**`& lines: return path
-&`PRX `&        on &'<='& and&`=>`& lines: proxy address
+&`PRDR`&        PRDR extension used
+&`PRX `&        on &'<='& and &`=>`& lines: proxy address
 &`Q   `&        alternate queue name
 &`QT  `&        on &`=>`& lines: time spent on queue so far
 &`    `&        on &"Completed"& lines: time spent on queue
index 587dc65..719bedf 100644 (file)
@@ -28,6 +28,11 @@ Version 4.88
 
  6. New expansion operators base32/base32d.
 
+ 7. The CHUNKING ESMTP extension from RFC 3030.  May give some slight
+    performance increase and network load decrease.  Main config option
+    chunking_advertise_hosts, and smtp transport option hosts_try_chunking
+    for control.
+
 
 Version 4.87
 ------------
index 956a332..eae6757 100644 (file)
@@ -715,7 +715,7 @@ host_item * h = addr->host_used;
 s = string_append(s, sp, pp, 2, US" H=", h->name);
 
 if (LOGGING(dnssec) && h->dnssec == DS_YES)
-  s = string_cat(s, sp, pp, US" DS");
+  s = string_catn(s, sp, pp, US" DS", 3);
 
 s = string_append(s, sp, pp, 3, US" [", h->address, US"]");
 
@@ -1139,8 +1139,11 @@ else
 
 #ifndef DISABLE_PRDR
   if (addr->flags & af_prdr_used)
-    s = string_append(s, &size, &ptr, 1, US" PRDR");
+    s = string_catn(s, &size, &ptr, US" PRDR", 5);
 #endif
+
+  if (addr->flags & af_chunking_used)
+    s = string_catn(s, &size, &ptr, US" K", 2);
   }
 
 /* confirmation message (SMTP (host_used) and LMTP (driver_name)) */
@@ -3482,6 +3485,10 @@ while (!done)
     break;
 #endif
 
+    case 'K':
+    addr->flags |= af_chunking_used;
+    break;
+
     case 'D':
     if (!addr) goto ADDR_MISMATCH;
     memcpy(&(addr->dsn_aware), ptr, sizeof(addr->dsn_aware));
@@ -4720,6 +4727,9 @@ for (delivery_count = 0; addr_remote; delivery_count++)
        rmt_dlv_checked_write(fd, 'P', '0', NULL, 0);
 #endif
 
+      if (addr->flags & af_chunking_used)
+       rmt_dlv_checked_write(fd, 'K', '0', NULL, 0);
+
       memcpy(big_buffer, &addr->dsn_aware, sizeof(addr->dsn_aware));
       rmt_dlv_checked_write(fd, 'D', '0', big_buffer, sizeof(addr->dsn_aware));
       DEBUG(D_deliver) debug_printf("DSN write: addr->dsn_aware = %d\n", addr->dsn_aware);
@@ -7100,7 +7110,7 @@ if (addr_senddsn)
     FILE *f = fdopen(fd, "wb");
     /* header only as required by RFC. only failure DSN needs to honor RET=FULL */
     uschar * bound;
-    transport_ctx tctx;
+    transport_ctx tctx = {0};
 
     DEBUG(D_deliver)
       debug_printf("sending error message to: %s\n", sender_address);
@@ -7180,7 +7190,6 @@ if (addr_senddsn)
 
     /* Write the original email out */
 
-    bzero(&tctx, sizeof(tctx));
     tctx.options = topt_add_return_path | topt_no_body;
     transport_write_message(fileno(f), &tctx, 0);
     fflush(f);
@@ -7638,16 +7647,14 @@ wording. */
       transport_filter_argv = NULL;   /* Just in case */
       return_path = sender_address;   /* In case not previously set */
        {                             /* Dummy transport for headers add */
-       transport_ctx * tctx =
-         store_get(sizeof(*tctx) + sizeof(transport_instance));
-       transport_instance * tb = (transport_instance *)(tctx+1);
+       transport_ctx tctx = {0};
+       transport_instance tb = {0};
 
-       bzero(tctx, sizeof(*tctx)+sizeof(*tb));
-       tctx->tblock = tb;
-       tctx->options = topt;
-       tb->add_headers = dsnnotifyhdr;
+       tctx.tblock = &tb;
+       tctx.options = topt;
+       tb.add_headers = dsnnotifyhdr;
 
-       transport_write_message(fileno(f), tctx, 0);
+       transport_write_message(fileno(f), &tctx, 0);
        }
       fflush(f);
 
@@ -7964,9 +7971,7 @@ else if (addr_defer != (address_item *)(+1))
         FILE *wmf = NULL;
         FILE *f = fdopen(fd, "wb");
        uschar * bound;
-       transport_ctx tctx;
-
-       bzero(&tctx, sizeof(tctx));
+       transport_ctx tctx = {0};
 
         if (warn_message_file)
           if (!(wmf = Ufopen(warn_message_file, "rb")))
@@ -8282,6 +8287,9 @@ if (!regex_STARTTLS) regex_STARTTLS =
   regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
 #endif
 
+if (!regex_CHUNKING) regex_CHUNKING =
+  regex_must_compile(US"\\n250[\\s\\-]CHUNKING(\\s|\\n|$)", FALSE, TRUE);
+
 #ifndef DISABLE_PRDR
 if (!regex_PRDR) regex_PRDR =
   regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
index e027a23..f09d438 100644 (file)
@@ -88,6 +88,9 @@ if (dkim_verify_ctx)
 dkim_verify_ctx = pdkim_init_verify(&dkim_exim_query_dns_txt);
 dkim_collect_input = !!dkim_verify_ctx;
 
+/* Start feed up with any cached data */
+receive_get_cache();
+
 store_pool = dkim_verify_oldpool;
 }
 
index 01770df..14e0b9d 100644 (file)
@@ -2717,76 +2717,63 @@ for (i = 1; i < argc; i++)
       break;
       }
 
+    else if (*argrest == 'C' && argrest[1] && !argrest[2])
+      {
+       switch(argrest[1])
+       {
     /* -MCA: set the smtp_authenticated flag; this is useful only when it
     precedes -MC (see above). The flag indicates that the host to which
     Exim is connected has accepted an AUTH sequence. */
 
-    else if (Ustrcmp(argrest, "CA") == 0)
-      {
-      smtp_authenticated = TRUE;
-      break;
-      }
+       case 'A': smtp_authenticated = TRUE; break;
 
     /* -MCD: set the smtp_use_dsn flag; this indicates that the host
        that exim is connected to supports the esmtp extension DSN */
 
-    else if (Ustrcmp(argrest, "CD") == 0)
-      {
-      smtp_use_dsn = TRUE;
-      break;
-      }
+       case 'D': smtp_peer_options |= PEER_OFFERED_DSN; break;
 
     /* -MCG: set the queue name, to a non-default value */
 
-    else if (Ustrcmp(argrest, "CG") == 0)
-      {
-      if (++i < argc) queue_name = string_copy(argv[i]);
-      else badarg = TRUE;
-      break;
-      }
+       case 'G': if (++i < argc) queue_name = string_copy(argv[i]);
+                 else badarg = TRUE;
+                 break;
+
+    /* -MCK: the peer offered CHUNKING.  Must precede -MC */
+
+       case 'K': smtp_peer_options |= PEER_OFFERED_CHUNKING; break;
 
     /* -MCP: set the smtp_use_pipelining flag; this is useful only when
     it preceded -MC (see above) */
 
-    else if (Ustrcmp(argrest, "CP") == 0)
-      {
-      smtp_use_pipelining = TRUE;
-      break;
-      }
+       case 'P': smtp_peer_options |= PEER_OFFERED_PIPE; break;
 
     /* -MCQ: pass on the pid of the queue-running process that started
     this chain of deliveries and the fd of its synchronizing pipe; this
     is useful only when it precedes -MC (see above) */
 
-    else if (Ustrcmp(argrest, "CQ") == 0)
-      {
-      if (++i < argc) passed_qr_pid = (pid_t)(Uatol(argv[i]));
-        else badarg = TRUE;
-      if (++i < argc) passed_qr_pipe = (int)(Uatol(argv[i]));
-        else badarg = TRUE;
-      break;
-      }
+       case 'Q': if (++i < argc) passed_qr_pid = (pid_t)(Uatol(argv[i]));
+                 else badarg = TRUE;
+                 if (++i < argc) passed_qr_pipe = (int)(Uatol(argv[i]));
+                 else badarg = TRUE;
+                 break;
 
     /* -MCS: set the smtp_use_size flag; this is useful only when it
     precedes -MC (see above) */
 
-    else if (Ustrcmp(argrest, "CS") == 0)
-      {
-      smtp_use_size = TRUE;
-      break;
-      }
+       case 'S': smtp_peer_options |= PEER_OFFERED_SIZE; break;
 
+#ifdef SUPPORT_TLS
     /* -MCT: set the tls_offered flag; this is useful only when it
     precedes -MC (see above). The flag indicates that the host to which
     Exim is connected has offered TLS support. */
 
-    #ifdef SUPPORT_TLS
-    else if (Ustrcmp(argrest, "CT") == 0)
-      {
-      tls_offered = TRUE;
-      break;
+       case 'T': smtp_peer_options |= PEER_OFFERED_TLS; break;
+#endif
+
+       default:  badarg = TRUE; break;
+       }
+       break;
       }
-    #endif
 
     /* -M[x]: various operations on the following list of message ids:
        -M    deliver the messages, ignoring next retry times and thawing
index 2c14163..8745a39 100644 (file)
@@ -56,6 +56,7 @@ extern int     tls_feof(void);
 extern int     tls_ferror(void);
 extern void    tls_free_cert(void **);
 extern int     tls_getc(void);
+extern void    tls_get_cache(void);
 extern int     tls_import_cert(const uschar *, void **);
 extern int     tls_read(BOOL, uschar *, size_t);
 extern int     tls_server_start(const uschar *);
@@ -100,6 +101,7 @@ extern int     auth_xtextdecode(uschar *, uschar **);
 
 extern uschar *b64encode(uschar *, int);
 extern int     b64decode(uschar *, uschar **);
+extern int     bdat_getc(void);
 extern void    bits_clear(unsigned int *, size_t, int *);
 extern void    bits_set(unsigned int *, size_t, int *);
 
@@ -389,6 +391,7 @@ extern BOOL    smtp_get_interface(uschar *, int, address_item *,
                  uschar **, uschar *);
 extern BOOL    smtp_get_port(uschar *, address_item *, int *, uschar *);
 extern int     smtp_getc(void);
+extern void    smtp_get_cache(void);
 extern int     smtp_handle_acl_fail(int, int, uschar *, uschar *);
 extern void    smtp_log_no_mail(void);
 extern void    smtp_message_code(uschar **, int *, uschar **, uschar **, BOOL);
@@ -466,9 +469,8 @@ extern BOOL    transport_set_up_command(const uschar ***, uschar *,
 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, transport_instance *,
-                 BOOL (*)(int, uschar *, int, BOOL),
-                BOOL);
+extern BOOL    transport_headers_send(int, transport_ctx *,
+                 BOOL (*)(int, transport_ctx *, uschar *, int));
 extern BOOL    transport_write_message(int, transport_ctx *, int);
 extern void    tree_add_duplicate(uschar *, address_item *);
 extern void    tree_add_nonrecipient(uschar *);
index 4f5a922..9e6f9d3 100644 (file)
@@ -138,7 +138,6 @@ tls_support tls_out = {
 uschar *dsn_envid              = NULL;
 int     dsn_ret                = 0;
 const pcre  *regex_DSN         = NULL;
-BOOL    smtp_use_dsn           = FALSE;
 uschar *dsn_advertise_hosts    = NULL;
 
 #ifdef SUPPORT_TLS
@@ -158,7 +157,6 @@ uschar *tls_eccurve            = US"prime256v1";
 # ifndef DISABLE_OCSP
 uschar *tls_ocsp_file          = NULL;
 # endif
-BOOL    tls_offered            = FALSE;
 uschar *tls_privatekey         = NULL;
 BOOL    tls_remember_esmtp     = FALSE;
 uschar *tls_require_ciphers    = NULL;
@@ -185,7 +183,10 @@ incoming TCP/IP. The defaults use stdin. We never need these for any
 stand-alone tests. */
 
 #ifndef STAND_ALONE
+int (*lwr_receive_getc)(void)  = stdin_getc;
+int (*lwr_receive_ungetc)(int) = stdin_ungetc;
 int (*receive_getc)(void)      = stdin_getc;
+void (*receive_get_cache)(void)= NULL;
 int (*receive_ungetc)(int)     = stdin_ungetc;
 int (*receive_feof)(void)      = stdin_feof;
 int (*receive_ferror)(void)    = stdin_ferror;
@@ -492,9 +493,17 @@ int     check_log_space        = 0;
 BOOL    check_rfc2047_length   = TRUE;
 int     check_spool_inodes     = 0;
 int     check_spool_space      = 0;
-uschar *client_authenticator  = NULL;
-uschar *client_authenticated_id = NULL;
-uschar *client_authenticated_sender = NULL;
+
+uschar *chunking_advertise_hosts = US"*";
+unsigned chunking_datasize     = 0;
+unsigned chunking_data_left    = 0;
+BOOL    chunking_offered       = FALSE;
+chunking_state_t chunking_state= CHUNKING_NOT_OFFERED;
+const pcre *regex_CHUNKING     = NULL;
+
+uschar *client_authenticator   = NULL;
+uschar *client_authenticated_id = NULL;
+uschar *client_authenticated_sender = NULL;
 int     clmacro_count          = 0;
 uschar *clmacros[MAX_CLMACROS];
 BOOL    config_changed         = FALSE;
@@ -1311,8 +1320,8 @@ int     smtp_rlr_base          = 0;
 double  smtp_rlr_factor        = 0.0;
 int     smtp_rlr_limit         = 0;
 int     smtp_rlr_threshold     = INT_MAX;
-BOOL    smtp_use_pipelining    = FALSE;
-BOOL    smtp_use_size          = FALSE;
+unsigned smtp_peer_options     = 0;
+unsigned smtp_peer_options_wrap= 0;
 #ifdef SUPPORT_I18N
 uschar *smtputf8_advertise_hosts = US"*";      /* overridden under test-harness */
 #endif
index 6e42bc3..b2bfca6 100644 (file)
@@ -119,7 +119,6 @@ extern uschar *tls_eccurve;            /* EC curve */
 # ifndef DISABLE_OCSP
 extern uschar *tls_ocsp_file;          /* OCSP stapling proof file */
 # endif
-extern BOOL    tls_offered;            /* Server offered TLS */
 extern uschar *tls_privatekey;         /* Private key file */
 extern BOOL    tls_remember_esmtp;     /* For YAEB */
 extern uschar *tls_require_ciphers;    /* So some can be avoided */
@@ -132,13 +131,15 @@ extern uschar *tls_advertise_hosts;    /* host for which TLS is advertised */
 extern uschar  *dsn_envid;             /* DSN envid string */
 extern int      dsn_ret;               /* DSN ret type*/
 extern const pcre  *regex_DSN;         /* For recognizing DSN settings */
-extern BOOL     smtp_use_dsn;          /* Global for passed connections */
 extern uschar  *dsn_advertise_hosts;   /* host for which TLS is advertised */
 
 /* Input-reading functions for messages, so we can use special ones for
 incoming TCP/IP. */
 
+extern int (*lwr_receive_getc)(void);
+extern int (*lwr_receive_ungetc)(int);
 extern int (*receive_getc)(void);
+extern void (*receive_get_cache)(void);
 extern int (*receive_ungetc)(int);
 extern int (*receive_feof)(void);
 extern int (*receive_ferror)(void);
@@ -267,6 +268,11 @@ extern int     check_log_space;        /* Minimum for message acceptance */
 extern BOOL    check_rfc2047_length;   /* Check RFC 2047 encoded string length */
 extern int     check_spool_inodes;     /* Minimum for message acceptance */
 extern int     check_spool_space;      /* Minimum for message acceptance */
+extern uschar *chunking_advertise_hosts;    /* RFC 3030 CHUNKING */
+extern unsigned chunking_datasize;
+extern unsigned chunking_data_left;
+extern BOOL    chunking_offered;
+extern chunking_state_t chunking_state;
 extern uschar *client_authenticator;        /* Authenticator name used for smtp delivery */
 extern uschar *client_authenticated_id;     /* "login" name used for SMTP AUTH */
 extern uschar *client_authenticated_sender; /* AUTH option to SMTP MAIL FROM (not yet used) */
@@ -711,6 +717,7 @@ extern int     recipients_max_reject;  /* If TRUE, reject whole message */
 extern const pcre *regex_AUTH;         /* For recognizing AUTH settings */
 extern const pcre  *regex_check_dns_names; /* For DNS name checking */
 extern const pcre  *regex_From;        /* For recognizing "From_" lines */
+extern const pcre  *regex_CHUNKING;    /* For recognizing CHUNKING (RFC 3030) */
 extern const pcre  *regex_IGNOREQUOTA; /* For recognizing IGNOREQUOTA (LMTP) */
 extern const pcre  *regex_PIPELINING;  /* For recognizing PIPELINING */
 extern const pcre  *regex_SIZE;        /* For recognizing SIZE settings */
@@ -829,8 +836,8 @@ extern int     smtp_rlr_base;          /* Base interval for RCPT rate limit */
 extern double  smtp_rlr_factor;        /* Factor for RCPT rate limit */
 extern int     smtp_rlr_limit;         /* Max delay */
 extern int     smtp_rlr_threshold;     /* Threshold for RCPT rate limit */
-extern BOOL    smtp_use_pipelining;    /* Global for passed connections */
-extern BOOL    smtp_use_size;          /* Global for passed connections */
+extern unsigned smtp_peer_options;     /* Global flags for passed connections */
+extern unsigned smtp_peer_options_wrap; /* stacked version hidden by TLS */
 #ifdef SUPPORT_I18N
 extern uschar *smtputf8_advertise_hosts; /* ingress control */
 #endif
index 53abeb5..c62f16e 100644 (file)
@@ -320,6 +320,13 @@ for having to swallow the rest of an SMTP message is whether the value is
 #define END_NOTENDED   3    /* Message reading not yet ended */
 #define END_SIZE       4    /* Reading ended because message too big */
 #define END_WERROR     5    /* Write error while reading the message */
+#define END_PROTOCOL   6    /* Protocol error in CHUNKING sequence */
+
+/* result codes for bdat_getc() (which can also return EOF) */
+
+#define EOD (-2)
+#define ERR (-3)
+
 
 /* Bit masks for debug and log selectors */
 
@@ -787,7 +794,8 @@ most recent SMTP commands. Must be kept in step with the list of names in
 smtp_in.c that is used for creating the smtp_no_mail logging action. SCH_NONE
 is "empty". */
 
-enum { SCH_NONE, SCH_AUTH, SCH_DATA, SCH_EHLO, SCH_ETRN, SCH_EXPN, SCH_HELO,
+enum { SCH_NONE, SCH_AUTH, SCH_DATA, SCH_BDAT,
+       SCH_EHLO, SCH_ETRN, SCH_EXPN, SCH_HELO,
        SCH_HELP, SCH_MAIL, SCH_NOOP, SCH_QUIT, SCH_RCPT, SCH_RSET, SCH_STARTTLS,
        SCH_VRFY };
 
@@ -837,6 +845,7 @@ enum {
 #define topt_no_headers         0x020  /* Omit headers */
 #define topt_no_body            0x040  /* Omit body */
 #define topt_escape_headers     0x080  /* Apply escape check to headers */
+#define topt_use_bdat          0x100  /* prepend chunks with RFC3030 BDAT header */
 
 /* Flags for recipient_block, used in DSN support */
 
@@ -952,6 +961,7 @@ enum { FILTER_UNSET, FILTER_FORWARD, FILTER_EXIM, FILTER_SIEVE };
 #define PEER_OFFERED_DSN       BIT(4)
 #define PEER_OFFERED_PIPE      BIT(5)
 #define PEER_OFFERED_SIZE      BIT(6)
+#define PEER_OFFERED_CHUNKING  BIT(7)
 
 
 /* End of macros.h */
index 25ff58e..a1591e2 100644 (file)
@@ -212,6 +212,7 @@ static optionlist optionlist_config[] = {
   { "check_rfc2047_length",     opt_bool,        &check_rfc2047_length },
   { "check_spool_inodes",       opt_int,         &check_spool_inodes },
   { "check_spool_space",        opt_Kint,        &check_spool_space },
+  { "chunking_advertise_hosts", opt_stringptr,  &chunking_advertise_hosts },
   { "daemon_smtp_port",         opt_stringptr|opt_hidden, &daemon_smtp_port },
   { "daemon_smtp_ports",        opt_stringptr,   &daemon_smtp_port },
   { "daemon_startup_retries",   opt_int,         &daemon_startup_retries },
index 3215479..6a8ce88 100644 (file)
@@ -777,7 +777,7 @@ read_message_data_smtp(FILE *fout)
 {
 int ch_state = 0;
 int ch;
-register int linelength = 0;
+int linelength = 0;
 
 while ((ch = (receive_getc)()) != EOF)
   {
@@ -867,7 +867,7 @@ while ((ch = (receive_getc)()) != EOF)
 
   message_size++;
   linelength++;
-  if (fout != NULL)
+  if (fout)
     {
     if (fputc(ch, fout) == EOF) return END_WERROR;
     if (message_size > thismessage_size_limit) return END_SIZE;
@@ -876,7 +876,7 @@ while ((ch = (receive_getc)()) != EOF)
     (void) cutthrough_put_nl();
   else
     {
-    uschar c= ch;
+    uschar c = ch;
     (void) cutthrough_puts(&c, 1);
     }
   }
@@ -890,6 +890,63 @@ return END_EOF;
 
 
 
+/* Variant of the above read_message_data_smtp() specialised for RFC 3030
+CHUNKING.  We assume that the incoming has proper CRLF, so only have to scan
+for and strip CR.  On the downside there are more protocol reasons to stop.
+
+Arguments:
+  fout      a FILE to which to write the message; NULL if skipping
+
+Returns:    One of the END_xxx values indicating why it stopped reading
+*/
+
+static int
+read_message_bdat_smtp(FILE *fout)
+{
+int ch;
+int linelength = 0;
+
+for (;;) switch (ch = bdat_getc())
+  {
+  case EOF: return END_EOF;
+  case EOD: return END_DOT;
+  case ERR: return END_PROTOCOL;
+
+  case '\r':
+    body_linecount++;
+    if (linelength > max_received_linelength)
+      max_received_linelength = linelength;
+    linelength = -1;
+    break;
+
+  case 0:
+    body_zerocount++;
+    /*FALLTHROUGH*/
+  default:
+    message_size++;
+    linelength++;
+    if (fout)
+      {
+      if (fputc(ch, fout) == EOF) return END_WERROR;
+      if (message_size > thismessage_size_limit) return END_SIZE;
+      }
+#ifdef notyet
+    if(ch == '\n')
+      (void) cutthrough_put_nl();
+    else
+      {
+      uschar c = ch;
+      (void) cutthrough_puts(&c, 1);
+      }
+#endif
+    break;
+  }
+/*NOTREACHED*/
+}
+
+
+
+
 /*************************************************
 *             Swallow SMTP message               *
 *************************************************/
@@ -906,6 +963,7 @@ Returns:     nothing
 void
 receive_swallow_smtp(void)
 {
+/*XXX CHUNKING: not enough.  read chunks until RSET? */
 if (message_ended >= END_NOTENDED)
   message_ended = read_message_data_smtp(NULL);
 }
@@ -2832,6 +2890,14 @@ if (filter_test != FTEST_NONE)
   return message_ended == END_DOT;
   }
 
+/*XXX CHUNKING: need to cancel cutthrough under BDAT, for now.  In future,
+think more if it could be handled.  Cannot do onward CHUNKING unless
+inbound is, but inbound chunking ought to be ok with outbound plain.
+Could we do onward CHUNKING given inbound CHUNKING?
+*/
+if (chunking_state > CHUNKING_OFFERED)
+  cancel_cutthrough_connection("chunking active");
+
 /* 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.
@@ -2929,7 +2995,9 @@ if (!ferror(data_file) && !(receive_feof)() && message_ended != END_DOT)
   {
   if (smtp_input)
     {
-    message_ended = read_message_data_smtp(data_file);
+    message_ended = chunking_state > CHUNKING_OFFERED
+      ? read_message_bdat_smtp(data_file)
+      : read_message_data_smtp(data_file);
     receive_linecount++;                /* The terminating "." line */
     }
   else message_ended = read_message_data(data_file);
@@ -2937,51 +3005,64 @@ if (!ferror(data_file) && !(receive_feof)() && message_ended != END_DOT)
   receive_linecount += body_linecount;  /* For BSMTP errors mainly */
   message_linecount += body_linecount;
 
-  /* Handle premature termination of SMTP */
-
-  if (smtp_input && message_ended == END_EOF)
+  switch (message_ended)
     {
-    Uunlink(spool_name);                     /* Lose data file when closed */
-    cancel_cutthrough_connection("sender closed connection");
-    message_id[0] = 0;                       /* Indicate no message accepted */
-    smtp_reply = handle_lost_connection(US"");
-    smtp_yield = FALSE;
-    goto TIDYUP;                             /* Skip to end of function */
-    }
+    /* Handle premature termination of SMTP */
 
-  /* Handle message that is too big. Don't use host_or_ident() in the log
-  message; we want to see the ident value even for non-remote messages. */
+    case END_EOF:
+      if (smtp_input)
+       {
+       Uunlink(spool_name);                 /* Lose data file when closed */
+       cancel_cutthrough_connection("sender closed connection");
+       message_id[0] = 0;                   /* Indicate no message accepted */
+       smtp_reply = handle_lost_connection(US"");
+       smtp_yield = FALSE;
+       goto TIDYUP;                         /* Skip to end of function */
+       }
+      break;
 
-  if (message_ended == END_SIZE)
-    {
-    Uunlink(spool_name);                /* Lose the data file when closed */
-    cancel_cutthrough_connection("mail too big");
-    if (smtp_input) receive_swallow_smtp();  /* Swallow incoming SMTP */
+    /* Handle message that is too big. Don't use host_or_ident() in the log
+    message; we want to see the ident value even for non-remote messages. */
 
-    log_write(L_size_reject, LOG_MAIN|LOG_REJECT, "rejected from <%s>%s%s%s%s: "
-      "message too big: read=%d max=%d",
-      sender_address,
-      (sender_fullhost == NULL)? "" : " H=",
-      (sender_fullhost == NULL)? US"" : sender_fullhost,
-      (sender_ident == NULL)? "" : " U=",
-      (sender_ident == NULL)? US"" : sender_ident,
-      message_size,
-      thismessage_size_limit);
+    case END_SIZE:
+      Uunlink(spool_name);                /* Lose the data file when closed */
+      cancel_cutthrough_connection("mail too big");
+      if (smtp_input) receive_swallow_smtp();  /* Swallow incoming SMTP */
 
-    if (smtp_input)
-      {
-      smtp_reply = US"552 Message size exceeds maximum permitted";
-      message_id[0] = 0;               /* Indicate no message accepted */
-      goto TIDYUP;                     /* Skip to end of function */
-      }
-    else
-      {
-      fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
-      give_local_error(ERRMESS_TOOBIG,
-        string_sprintf("message too big (max=%d)", thismessage_size_limit),
-        US"message rejected: ", error_rc, data_file, header_list);
-      /* Does not return */
-      }
+      log_write(L_size_reject, LOG_MAIN|LOG_REJECT, "rejected from <%s>%s%s%s%s: "
+       "message too big: read=%d max=%d",
+       sender_address,
+       (sender_fullhost == NULL)? "" : " H=",
+       (sender_fullhost == NULL)? US"" : sender_fullhost,
+       (sender_ident == NULL)? "" : " U=",
+       (sender_ident == NULL)? US"" : sender_ident,
+       message_size,
+       thismessage_size_limit);
+
+      if (smtp_input)
+       {
+       smtp_reply = US"552 Message size exceeds maximum permitted";
+       message_id[0] = 0;               /* Indicate no message accepted */
+       goto TIDYUP;                     /* Skip to end of function */
+       }
+      else
+       {
+       fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
+       give_local_error(ERRMESS_TOOBIG,
+         string_sprintf("message too big (max=%d)", thismessage_size_limit),
+         US"message rejected: ", error_rc, data_file, header_list);
+       /* Does not return */
+       }
+      break;
+
+    /* Handle bad BDAT protocol sequence */
+
+    case END_PROTOCOL:
+      Uunlink(spool_name);             /* Lose the data file when closed */
+      cancel_cutthrough_connection("sender protocol error");
+      smtp_reply = US"";               /* Response already sent */
+      message_id[0] = 0;               /* Indicate no message accepted */
+      goto TIDYUP;                     /* Skip to end of function */
     }
   }
 
@@ -3164,9 +3245,8 @@ user_msg = NULL;
 enable_dollar_recipients = TRUE;
 
 if (recipients_count == 0)
-  {
-  blackholed_by = recipients_discarded? US"MAIL ACL" : US"RCPT ACL";
-  }
+  blackholed_by = recipients_discarded ? US"MAIL ACL" : US"RCPT ACL";
+
 else
   {
   /* Handle interactive SMTP messages */
@@ -3182,18 +3262,15 @@ else
       dkim_exim_verify_finish();
 
       /* Check if we must run the DKIM ACL */
-      if ((acl_smtp_dkim != NULL) &&
-          (dkim_verify_signers != NULL) &&
-          (dkim_verify_signers[0] != '\0'))
+      if (acl_smtp_dkim && dkim_verify_signers && *dkim_verify_signers)
         {
         uschar *dkim_verify_signers_expanded =
           expand_string(dkim_verify_signers);
-        if (dkim_verify_signers_expanded == NULL)
-          {
+        if (!dkim_verify_signers_expanded)
           log_write(0, LOG_MAIN|LOG_PANIC,
             "expansion of dkim_verify_signers option failed: %s",
             expand_string_message);
-          }
+
         else
           {
           int sep = 0;
@@ -3202,28 +3279,23 @@ else
           uschar *seen_items = NULL;
           int     seen_items_size = 0;
           int     seen_items_offset = 0;
-          uschar itembuf[256];
           /* Default to OK when no items are present */
           rc = OK;
-          while ((item = string_nextinlist(&ptr, &sep,
-                                           itembuf,
-                                           sizeof(itembuf))))
+          while ((item = string_nextinlist(&ptr, &sep, NULL, 0)))
             {
             /* Prevent running ACL for an empty item */
-            if (!item || (item[0] == '\0')) continue;
+            if (!item || !*item) continue;
 
             /* 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];
               const uschar *seen_items_list = seen_items;
               BOOL seen_this_item = FALSE;
 
               while ((seen_item = string_nextinlist(&seen_items_list, &sep,
-                                                    seen_item_buf,
-                                                    sizeof(seen_item_buf))))
+                                                    NULL, 0)))
                if (Ustrcmp(seen_item,item) == 0)
                  {
                  seen_this_item = TRUE;
@@ -3783,7 +3855,7 @@ if (sender_host_authenticated)
 
 #ifndef DISABLE_PRDR
 if (prdr_requested)
-  s = string_append(s, &size, &sptr, 1, US" PRDR");
+  s = string_catn(s, &size, &sptr, US" PRDR", 5);
 #endif
 
 #ifdef SUPPORT_PROXY
@@ -3791,6 +3863,9 @@ if (proxy_session && LOGGING(proxy))
   s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_local_address);
 #endif
 
+if (chunking_state > CHUNKING_OFFERED)
+  s = string_catn(s, &size, &sptr, US" K", 2);
+
 sprintf(CS big_buffer, "%d", msg_size);
 s = string_append(s, &size, &sptr, 2, US" S=", big_buffer);
 
@@ -4093,8 +4168,15 @@ if (smtp_input)
 
       /* Default OK response */
 
+      else if (chunking_state > CHUNKING_OFFERED)
+       {
+        smtp_printf("250- %u byte chunk, total %d\r\n250 OK id=%s\r\n",
+           chunking_datasize, message_size+message_linecount, message_id);
+       chunking_state = CHUNKING_OFFERED;
+       }
       else
         smtp_printf("250 OK id=%s\r\n", message_id);
+
       if (host_checking)
         fprintf(stdout,
           "\n**** SMTP testing: that is not a real message id!\n\n");
index 5338701..8994c6e 100644 (file)
@@ -82,6 +82,15 @@ enum {
 
   MAIL_CMD, RCPT_CMD, RSET_CMD,
 
+  /* RFC3030 section 2: "After all MAIL and RCPT responses are collected and
+  processed the message is sent using a series of BDAT commands"
+  implies that BDAT should be synchronized.  However, we see Google, at least,
+  sending MAIL,RCPT,BDAT-LAST in a single packet, clearly not waiting for
+  processing of the RPCT response(s).  We shall do the same, and not require
+  synch for BDAT. */
+
+  BDAT_CMD,
+
   /* This is a dummy to identify the non-sync commands when not pipelining */
 
   NON_SYNC_CMD_NON_PIPELINING,
@@ -182,6 +191,7 @@ static smtp_cmd_list cmd_list[] = {
   { "mail from:", sizeof("mail from:")-1, MAIL_CMD, TRUE,  TRUE  },
   { "rcpt to:",   sizeof("rcpt to:")-1,   RCPT_CMD, TRUE,  TRUE  },
   { "data",       sizeof("data")-1,       DATA_CMD, FALSE, TRUE  },
+  { "bdat",       sizeof("bdat")-1,       BDAT_CMD, TRUE,  TRUE  },
   { "quit",       sizeof("quit")-1,       QUIT_CMD, FALSE, TRUE  },
   { "noop",       sizeof("noop")-1,       NOOP_CMD, TRUE,  FALSE },
   { "etrn",       sizeof("etrn")-1,       ETRN_CMD, TRUE,  FALSE },
@@ -205,9 +215,9 @@ It must be kept in step with the SCH_xxx enumerations. */
 
 static uschar *smtp_names[] =
   {
-  US"NONE", US"AUTH", US"DATA", US"EHLO", US"ETRN", US"EXPN", US"HELO",
-  US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET", US"STARTTLS",
-  US"VRFY" };
+  US"NONE", US"AUTH", US"DATA", US"BDAT", US"EHLO", US"ETRN", US"EXPN",
+  US"HELO", US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET",
+  US"STARTTLS", US"VRFY" };
 
 static uschar *protocols_local[] = {
   US"local-smtp",        /* HELO */
@@ -289,6 +299,13 @@ static int     smtp_had_eof;
 static int     smtp_had_error;
 
 
+/* forward declarations */
+int bdat_ungetc(int ch);
+static int smtp_read_command(BOOL check_sync);
+static int synprot_error(int type, int code, uschar *data, uschar *errmess);
+static void smtp_quit_handler(uschar **, uschar **);
+static void smtp_rset_handler(void);
+
 /*************************************************
 *          SMTP version of getc()                *
 *************************************************/
@@ -335,6 +352,131 @@ if (smtp_inptr >= smtp_inend)
 return *smtp_inptr++;
 }
 
+#ifndef DISABLE_DKIM
+void
+smtp_get_cache(void)
+{
+int n = smtp_inend - smtp_inptr;
+if (n > 0)
+  dkim_exim_verify_feed(smtp_inptr, n);
+}
+#endif
+
+
+/* Get a byte from the smtp input, in CHUNKING mode.  Handle ack of the
+previous BDAT chunk and getting new ones when we run out.  Uses the
+underlying smtp_getc or tls_getc both for that and for getting the
+(buffered) data byte.  EOD signals (an expected) no further data.
+ERR signals a protocol error, and EOF a closed input stream.
+
+Called from read_bdat_smtp() in receive.c for the message body, but also
+by the headers read loop in receive_msg(); manipulates chunking_state
+to handle the BDAT command/response.
+Placed here due to the correlation with the above smtp_getc(), which it wraps,
+and also by the need to do smtp command/response handling.
+
+Arguments:  none
+Returns:    the next character or ERR, EOD or EOF
+*/
+
+int
+bdat_getc(void)
+{
+uschar * user_msg = NULL;
+uschar * log_msg;
+
+for(;;)
+  {
+  if (chunking_data_left-- > 0)
+    return lwr_receive_getc();
+
+  receive_getc = lwr_receive_getc;
+  receive_ungetc = lwr_receive_ungetc;
+
+  /* If not the last, ack the received chunk.  The last response is delayed
+  until after the data ACL decides on it */
+
+  if (chunking_state == CHUNKING_LAST)
+    {
+#ifndef DISABLE_DKIM
+    dkim_exim_verify_feed(".\r\n", 3); /* for consistency with .-term MAIL */
+#endif
+    return EOD;
+    }
+
+  chunking_state = CHUNKING_OFFERED;
+  smtp_printf("250 %u byte chunk received\r\n", chunking_datasize);
+
+  /* Expect another BDAT cmd from input. RFC 3030 says nothing about
+  QUIT, RSET or NOOP but handling them seems obvious */
+
+next_cmd:
+  switch(smtp_read_command(TRUE))
+    {
+    default:
+      (void) synprot_error(L_smtp_protocol_error, 503, NULL,
+       US"only BDAT permissible after non-LAST BDAT");
+
+  repeat_until_rset:
+      switch(smtp_read_command(TRUE))
+       {
+       case QUIT_CMD:  smtp_quit_handler(&user_msg, &log_msg); /*FALLTHROUGH */
+       case EOF_CMD:   return EOF;
+       case RSET_CMD:  smtp_rset_handler(); return ERR;
+       default:        if (synprot_error(L_smtp_protocol_error, 503, NULL,
+                                         US"only RSET accepted now") > 0)
+                         return EOF;
+                       goto repeat_until_rset;
+       }
+
+    case QUIT_CMD:
+      smtp_quit_handler(&user_msg, &log_msg);
+      /*FALLTHROUGH*/
+    case EOF_CMD:
+      return EOF;
+
+    case RSET_CMD:
+      smtp_rset_handler();
+      return ERR;
+
+    case NOOP_CMD:
+      HAD(SCH_NOOP);
+      smtp_printf("250 OK\r\n");
+      goto next_cmd;
+
+    case BDAT_CMD:
+      {
+      int n;
+
+      if (sscanf(CS smtp_cmd_data, "%u %n", &chunking_datasize, &n) < 1)
+       {
+       (void) synprot_error(L_smtp_protocol_error, 501, NULL,
+         US"missing size for BDAT command");
+       return ERR;
+       }
+      chunking_state = strcmpic(smtp_cmd_data+n, US"LAST") == 0
+       ? CHUNKING_LAST : CHUNKING_ACTIVE;
+      chunking_data_left = chunking_datasize;
+
+      if (chunking_datasize == 0)
+       if (chunking_state == CHUNKING_LAST)
+         return EOD;
+       else
+         {
+         (void) synprot_error(L_smtp_protocol_error, 504, NULL,
+           US"zero size for BDAT command");
+         goto repeat_until_rset;
+         }
+
+      receive_getc = bdat_getc;
+      receive_ungetc = bdat_ungetc;
+      break;   /* to top of main loop */
+      }
+    }
+  }
+}
+
+
 
 
 /*************************************************
@@ -353,11 +495,18 @@ Returns:       the character
 int
 smtp_ungetc(int ch)
 {
-*(--smtp_inptr) = ch;
+*--smtp_inptr = ch;
 return ch;
 }
 
 
+int
+bdat_ungetc(int ch)
+{
+chunking_data_left++;
+return lwr_receive_ungetc(ch);
+}
+
 
 
 /*************************************************
@@ -1520,14 +1669,6 @@ sender_verified_list = NULL;        /* No senders verified */
 memset(sender_address_cache, 0, sizeof(sender_address_cache));
 memset(sender_domain_cache, 0, sizeof(sender_domain_cache));
 
-#ifndef DISABLE_PRDR
-prdr_requested = FALSE;
-#endif
-
-/* Reset the DSN flags */
-dsn_ret = 0;
-dsn_envid = NULL;
-
 authenticated_sender = NULL;
 #ifdef EXPERIMENTAL_BRIGHTMAIL
 bmi_run = 0;
@@ -1538,6 +1679,11 @@ dkim_signers = NULL;
 dkim_disable_verify = FALSE;
 dkim_collect_input = FALSE;
 #endif
+dsn_ret = 0;
+dsn_envid = NULL;
+#ifndef DISABLE_PRDR
+prdr_requested = FALSE;
+#endif
 #ifdef EXPERIMENTAL_SPF
 spf_header_comment = NULL;
 spf_received = NULL;
@@ -1918,6 +2064,7 @@ smtp_inbuffer = (uschar *)malloc(in_buffer_size);
 if (smtp_inbuffer == NULL)
   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "malloc() failed for SMTP input buffer");
 receive_getc = smtp_getc;
+receive_get_cache = smtp_get_cache;
 receive_ungetc = smtp_ungetc;
 receive_feof = smtp_feof;
 receive_ferror = smtp_ferror;
@@ -3239,6 +3386,43 @@ return 0;
 
 
 
+static void
+smtp_quit_handler(uschar ** user_msgp, uschar ** log_msgp)
+{
+HAD(SCH_QUIT);
+incomplete_transaction_log(US"QUIT");
+if (acl_smtp_quit != NULL)
+  {
+  int rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, user_msgp, log_msgp);
+  if (rc == ERROR)
+    log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s",
+      *log_msgp);
+  }
+if (*user_msgp)
+  smtp_respond(US"221", 3, TRUE, *user_msgp);
+else
+  smtp_printf("221 %s closing connection\r\n", smtp_active_hostname);
+
+#ifdef SUPPORT_TLS
+tls_close(TRUE, TRUE);
+#endif
+
+log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT",
+  smtp_get_connection_info());
+}
+
+
+static void
+smtp_rset_handler(void)
+{
+HAD(SCH_RSET);
+incomplete_transaction_log(US"RSET");
+smtp_printf("250 Reset OK\r\n");
+cmd_list[CMD_LIST_RSET].is_mail_cmd = FALSE;
+}
+
+
+
 /*************************************************
 *       Initialize for SMTP incoming message     *
 *************************************************/
@@ -3285,6 +3469,8 @@ for the host). Note: we do NOT reset AUTH at this point. */
 smtp_reset(reset_point);
 message_ended = END_NOTSTARTED;
 
+chunking_state = chunking_offered ? CHUNKING_OFFERED : CHUNKING_NOT_OFFERED;
+
 cmd_list[CMD_LIST_RSET].is_mail_cmd = TRUE;
 cmd_list[CMD_LIST_HELO].is_mail_cmd = TRUE;
 cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
@@ -3769,6 +3955,16 @@ while (done <= 0)
        if (!first) s = string_catn(s, &size, &ptr, US"\r\n", 2);
        }
 
+      /* RFC 3030 CHUNKING */
+
+      if (verify_check_host(&chunking_advertise_hosts) != FAIL)
+        {
+        s = string_catn(s, &size, &ptr, smtp_code, 3);
+        s = string_catn(s, &size, &ptr, US"-CHUNKING\r\n", 11);
+       chunking_offered = TRUE;
+       chunking_state = CHUNKING_OFFERED;
+        }
+
       /* Advertise TLS (Transport Level Security) aka SSL (Secure Socket Layer)
       if it has been included in the binary, and the host matches
       tls_advertise_hosts. We must *not* advertise if we are already in a
@@ -4521,8 +4717,44 @@ while (done <= 0)
     (often indicating some kind of system error), it is helpful to include it
     with the DATA rejection (an idea suggested by Tony Finch). */
 
+    case BDAT_CMD:
+    HAD(SCH_BDAT);
+      {
+      int n;
+
+      if (chunking_state != CHUNKING_OFFERED)
+       {
+       done = synprot_error(L_smtp_protocol_error, 503, NULL,
+         US"BDAT command used when CHUNKING not advertised");
+       break;
+       }
+
+      /* grab size, endmarker */
+
+      if (sscanf(CS smtp_cmd_data, "%u %n", &chunking_datasize, &n) < 1)
+       {
+       done = synprot_error(L_smtp_protocol_error, 501, NULL,
+         US"missing size for BDAT command");
+       break;
+       }
+      chunking_state = strcmpic(smtp_cmd_data+n, US"LAST") == 0
+       ? CHUNKING_LAST : CHUNKING_ACTIVE;
+      chunking_data_left = chunking_datasize;
+
+      lwr_receive_getc = receive_getc;
+      lwr_receive_ungetc = receive_ungetc;
+      receive_getc = bdat_getc;
+      receive_ungetc = bdat_ungetc;
+
+      DEBUG(D_any)
+        debug_printf("chunking state %d\n", (int)chunking_state);
+      goto DATA_BDAT;
+      }
+
     case DATA_CMD:
     HAD(SCH_DATA);
+
+    DATA_BDAT:         /* Common code for DATA and BDAT */
     if (!discarded && recipients_count <= 0)
       {
       if (rcpt_smtp_response_same && rcpt_smtp_response != NULL)
@@ -4537,10 +4769,13 @@ while (done <= 0)
         smtp_respond(code, 3, FALSE, rcpt_smtp_response);
         }
       if (pipelining_advertised && last_was_rcpt)
-        smtp_printf("503 Valid RCPT command must precede DATA\r\n");
+        smtp_printf("503 Valid RCPT command must precede %s\r\n",
+         smtp_names[smtp_connection_had[smtp_ch_index-1]]);
       else
         done = synprot_error(L_smtp_protocol_error, 503, NULL,
-          US"valid RCPT command must precede DATA");
+         smtp_connection_had[smtp_ch_index-1] == SCH_DATA
+         ? US"valid RCPT command must precede DATA"
+         : US"valid RCPT command must precede BDAT");
       break;
       }
 
@@ -4552,35 +4787,45 @@ while (done <= 0)
       break;
       }
 
-    /* If there is an ACL, re-check the synchronization afterwards, since the
-    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
-      {
-      uschar * acl= acl_smtp_predata ? acl_smtp_predata : US"accept";
-      enable_dollar_recipients = TRUE;
-      rc = acl_check(ACL_WHERE_PREDATA, NULL, acl, &user_msg,
-        &log_msg);
-      enable_dollar_recipients = FALSE;
-      if (rc == OK && !check_sync()) goto SYNC_FAILURE;
+    if (chunking_state > CHUNKING_OFFERED)
+      {                                /* No predata ACL or go-ahead output for BDAT */
+      rc = OK;
       }
-
-    if (rc == OK)
+    else
       {
-      uschar * code;
-      code = US"354";
-      if (user_msg == NULL)
-        smtp_printf("%s Enter message, ending with \".\" on a line by itself\r\n", code);
-      else smtp_user_msg(code, user_msg);
-      done = 3;
-      message_ended = END_NOTENDED;   /* Indicate in middle of data */
+      /* If there is an ACL, re-check the synchronization afterwards, since the
+      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
+       {
+       uschar * acl = acl_smtp_predata ? acl_smtp_predata : US"accept";
+       enable_dollar_recipients = TRUE;
+       rc = acl_check(ACL_WHERE_PREDATA, NULL, acl, &user_msg,
+         &log_msg);
+       enable_dollar_recipients = FALSE;
+       if (rc == OK && !check_sync())
+         goto SYNC_FAILURE;
+
+       if (rc != OK)
+         {     /* Either the ACL failed the address, or it was deferred. */
+         done = smtp_handle_acl_fail(ACL_WHERE_PREDATA, rc, user_msg, log_msg);
+         break;
+         }
+       }
+
+      if (user_msg)
+       smtp_user_msg(US"354", user_msg);
+      else
+       smtp_printf(
+         "354 Enter message, ending with \".\" on a line by itself\r\n");
       }
 
-    /* Either the ACL failed the address, or it was deferred. */
+    done = 3;
+    message_ended = END_NOTENDED;   /* Indicate in middle of data */
 
-    else
-      done = smtp_handle_acl_fail(ACL_WHERE_PREDATA, rc, user_msg, log_msg);
     break;
 
 
@@ -4699,7 +4944,7 @@ while (done <= 0)
     if (receive_smtp_buffered())
       {
       DEBUG(D_any)
-        debug_printf("Non-empty input buffer after STARTTLS; naive attack?");
+        debug_printf("Non-empty input buffer after STARTTLS; naive attack?\n");
       if (tls_in.active < 0)
         smtp_inend = smtp_inptr = smtp_inbuffer;
       /* and if TLS is already active, tls_server_start() should fail */
@@ -4816,37 +5061,15 @@ while (done <= 0)
     message. */
 
     case QUIT_CMD:
-    HAD(SCH_QUIT);
-    incomplete_transaction_log(US"QUIT");
-    if (acl_smtp_quit != NULL)
-      {
-      rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, &user_msg, &log_msg);
-      if (rc == ERROR)
-        log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s",
-          log_msg);
-      }
-    if (user_msg == NULL)
-      smtp_printf("221 %s closing connection\r\n", smtp_active_hostname);
-    else
-      smtp_respond(US"221", 3, TRUE, user_msg);
-
-    #ifdef SUPPORT_TLS
-    tls_close(TRUE, TRUE);
-    #endif
-
+    smtp_quit_handler(&user_msg, &log_msg);
     done = 2;
-    log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT",
-      smtp_get_connection_info());
     break;
 
 
     case RSET_CMD:
-    HAD(SCH_RSET);
-    incomplete_transaction_log(US"RSET");
+    smtp_rset_handler();
     smtp_reset(reset_point);
     toomany = FALSE;
-    smtp_printf("250 Reset OK\r\n");
-    cmd_list[CMD_LIST_RSET].is_mail_cmd = FALSE;
     break;
 
 
@@ -4873,7 +5096,7 @@ while (done <= 0)
           verify_check_host(&tls_advertise_hosts) != FAIL)
         Ustrcat(buffer, " STARTTLS");
       #endif
-      Ustrcat(buffer, " HELO EHLO MAIL RCPT DATA");
+      Ustrcat(buffer, " HELO EHLO MAIL RCPT DATA BDAT");
       Ustrcat(buffer, " NOOP QUIT RSET HELP");
       if (acl_smtp_etrn != NULL) Ustrcat(buffer, " ETRN");
       if (acl_smtp_expn != NULL) Ustrcat(buffer, " EXPN");
index 6b48431..76181b5 100644 (file)
@@ -357,6 +357,7 @@ Arguments:
   noflush    if TRUE, save the command in the output buffer, for pipelining
   format     a format, starting with one of
              of HELO, MAIL FROM, RCPT TO, DATA, ".", or QUIT.
+            If NULL, flush pipeline buffer only.
   ...        data for the format
 
 Returns:     0 if command added to pipelining buffer, with nothing transmitted
@@ -371,48 +372,51 @@ int count;
 int rc = 0;
 va_list ap;
 
-va_start(ap, format);
-if (!string_vformat(big_buffer, big_buffer_size, CS format, ap))
-  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
-    "SMTP");
-va_end(ap);
-count = Ustrlen(big_buffer);
-
-if (count > outblock->buffersize)
-  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
-    "SMTP");
-
-if (count > outblock->buffersize - (outblock->ptr - outblock->buffer))
+if (format)
   {
-  rc = outblock->cmd_count;                 /* flush resets */
-  if (!flush_buffer(outblock)) return -1;
-  }
+  va_start(ap, format);
+  if (!string_vformat(big_buffer, big_buffer_size, CS format, ap))
+    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
+      "SMTP");
+  va_end(ap);
+  count = Ustrlen(big_buffer);
+
+  if (count > outblock->buffersize)
+    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
+      "SMTP");
+
+  if (count > outblock->buffersize - (outblock->ptr - outblock->buffer))
+    {
+    rc = outblock->cmd_count;                 /* flush resets */
+    if (!flush_buffer(outblock)) return -1;
+    }
 
-Ustrncpy(CS outblock->ptr, big_buffer, count);
-outblock->ptr += count;
-outblock->cmd_count++;
-count -= 2;
-big_buffer[count] = 0;     /* remove \r\n for error message */
+  Ustrncpy(CS outblock->ptr, big_buffer, count);
+  outblock->ptr += count;
+  outblock->cmd_count++;
+  count -= 2;
+  big_buffer[count] = 0;     /* remove \r\n for error message */
 
-/* We want to hide the actual data sent in AUTH transactions from reflections
-and logs. While authenticating, a flag is set in the outblock to enable this.
-The AUTH command itself gets any data flattened. Other lines are flattened
-completely. */
+  /* We want to hide the actual data sent in AUTH transactions from reflections
+  and logs. While authenticating, a flag is set in the outblock to enable this.
+  The AUTH command itself gets any data flattened. Other lines are flattened
+  completely. */
 
-if (outblock->authenticating)
-  {
-  uschar *p = big_buffer;
-  if (Ustrncmp(big_buffer, "AUTH ", 5) == 0)
+  if (outblock->authenticating)
     {
-    p += 5;
-    while (isspace(*p)) p++;
-    while (!isspace(*p)) p++;
-    while (isspace(*p)) p++;
+    uschar *p = big_buffer;
+    if (Ustrncmp(big_buffer, "AUTH ", 5) == 0)
+      {
+      p += 5;
+      while (isspace(*p)) p++;
+      while (!isspace(*p)) p++;
+      while (isspace(*p)) p++;
+      }
+    while (*p != 0) *p++ = '*';
     }
-  while (*p != 0) *p++ = '*';
-  }
 
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>> %s\n", big_buffer);
+  HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>> %s\n", big_buffer);
+  }
 
 if (!noflush)
   {
index 6666c52..ffbc899 100644 (file)
@@ -51,6 +51,11 @@ typedef struct ugid_block {
   BOOL    initgroups;
 } ugid_block;
 
+typedef enum { CHUNKING_NOT_OFFERED = -1,
+               CHUNKING_OFFERED,
+               CHUNKING_ACTIVE,
+               CHUNKING_LAST} chunking_state_t;
+
 /* Structure for holding information about a host for use mainly by routers,
 but also used when checking lists of hosts and when transporting. Looking up
 host addresses is done using this structure. */
@@ -218,14 +223,38 @@ typedef struct transport_info {
 } transport_info;
 
 
+/* smtp transport datachunk callback */
+
+#define tc_reap_prev   BIT(0)  /* Flags: reap previous SMTP cmd responses */
+#define tc_reap_one    BIT(1)  /* reap one SMTP response */
+#define tc_chunk_last  BIT(2)  /* annotate chunk SMTP cmd as LAST */
+
+struct transport_context;
+typedef int (*tpt_chunk_cmd_cb)(int fd, struct transport_context * tctx,
+                               unsigned len, unsigned flags);
+
 /* Structure for information about a delivery-in-progress */
 
 typedef struct transport_context {
-  transport_instance * tblock;
-  struct address_item * addr;
-  uschar       * check_string;
-  uschar       * escape_string;
-  int            options;              /* topt_* */
+  transport_instance   * tblock;               /* transport */
+  struct address_item  * addr;
+  uschar               * check_string;         /* string replacement */
+  uschar               * escape_string;
+  int                    options;              /* output processing topt_* */
+
+  /* items below only used with option topt_use_bdat */
+  tpt_chunk_cmd_cb       chunk_cb;             /* per-datachunk callback */
+  struct smtp_inblock  * inblock;
+  struct smtp_outblock * outblock;
+  host_item            * host;
+  struct address_item  * first_addr;
+  struct address_item  **sync_addr;
+  BOOL                   pending_MAIL;
+  BOOL                   pending_BDAT;
+  BOOL                   good_RCPT;
+  BOOL                 * completed_address;
+  int                    cmd_count;
+  uschar               * buffer;
 } transport_ctx;
 
 
@@ -517,12 +546,13 @@ typedef struct address_item_propagated {
 #ifndef DISABLE_PRDR
 # define af_prdr_used          0x08000000 /* delivery used SMTP PRDR */
 #endif
-#define af_force_command       0x10000000 /* force_command in pipe transport */
+#define af_chunking_used       0x10000000 /* delivery used SMTP CHUNKING */
+#define af_force_command       0x20000000 /* force_command in pipe transport */
 #ifdef EXPERIMENTAL_DANE
-# define af_dane_verified      0x20000000 /* TLS cert verify done with DANE */
+# define af_dane_verified      0x40000000 /* TLS cert verify done with DANE */
 #endif
 #ifdef SUPPORT_I18N
-# define af_utf8_downcvt       0x40000000 /* downconvert was done for delivery */
+# define af_utf8_downcvt       0x80000000 /* downconvert was done for delivery */
 #endif
 
 /* These flags must be propagated when a child is created */
index c7c6b26..0774850 100644 (file)
@@ -1879,6 +1879,7 @@ and initialize appropriately. */
 state->xfer_buffer = store_malloc(ssl_xfer_buffer_size);
 
 receive_getc = tls_getc;
+receive_get_cache = tls_get_cache;
 receive_ungetc = tls_ungetc;
 receive_feof = tls_feof;
 receive_ferror = tls_ferror;
@@ -2179,6 +2180,7 @@ if (state->xfer_buffer_lwm >= state->xfer_buffer_hwm)
     DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
 
     receive_getc = smtp_getc;
+    receive_get_cache = smtp_get_cache;
     receive_ungetc = smtp_ungetc;
     receive_feof = smtp_feof;
     receive_ferror = smtp_ferror;
@@ -2217,6 +2219,17 @@ if (state->xfer_buffer_lwm >= state->xfer_buffer_hwm)
 return state->xfer_buffer[state->xfer_buffer_lwm++];
 }
 
+#ifndef DISABLE_DKIM
+void
+tls_get_cache()
+{
+exim_gnutls_state_st * state = &state_server;
+int n = state->xfer_buffer_hwm - state->xfer_buffer_lwm;
+if (n > 0)
+  dkim_exim_verify_feed(state->xfer_buffer+state->xfer_buffer_lwm, n);
+}
+#endif
+
 
 
 
index c24eb45..242394f 100644 (file)
@@ -1943,6 +1943,7 @@ ssl_xfer_buffer_lwm = ssl_xfer_buffer_hwm = 0;
 ssl_xfer_eof = ssl_xfer_error = 0;
 
 receive_getc = tls_getc;
+receive_get_cache = tls_get_cache;
 receive_ungetc = tls_ungetc;
 receive_feof = tls_feof;
 receive_ferror = tls_ferror;
@@ -2313,6 +2314,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
     DEBUG(D_tls) debug_printf("Got SSL_ERROR_ZERO_RETURN\n");
 
     receive_getc = smtp_getc;
+    receive_get_cache = smtp_get_cache;
     receive_ungetc = smtp_ungetc;
     receive_feof = smtp_feof;
     receive_ferror = smtp_ferror;
@@ -2358,6 +2360,16 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
 return ssl_xfer_buffer[ssl_xfer_buffer_lwm++];
 }
 
+#ifndef DISABLE_DKIM
+void
+tls_get_cache()
+{
+int n = ssl_xfer_buffer_hwm - ssl_xfer_buffer_lwm;
+if (n > 0)
+  dkim_exim_verify_feed(ssl_xfer_buffer+ssl_xfer_buffer_lwm, n);
+}
+#endif
+
 
 
 /*************************************************
index 8e0a802..a68c22f 100644 (file)
@@ -236,10 +236,12 @@ for (i = 0; i < 100; i++)
   else
     {
     alarm(local_timeout);
-    #ifdef SUPPORT_TLS
-    if (tls_out.active == fd) rc = tls_write(FALSE, block, len); else
-    #endif
-    rc = write(fd, block, len);
+#ifdef SUPPORT_TLS
+    if (tls_out.active == fd)
+      rc = tls_write(FALSE, block, len);
+    else
+#endif
+      rc = write(fd, block, len);
     save_errno = errno;
     local_timeout = alarm(0);
     if (sigalrm_seen)
@@ -357,7 +359,7 @@ Arguments:
   fd         file descript to write to
   chunk      pointer to data to write
   len        length of data to write
-  usr_crlf   TRUE if CR LF is wanted at the end of each line
+  tctx       transport context - processing to be done during output
 
 In addition, the static nl_xxx variables must be set as required.
 
@@ -365,7 +367,7 @@ Returns:     TRUE on success, FALSE on failure (with errno preserved)
 */
 
 static BOOL
-write_chunk(int fd, uschar *chunk, int len, BOOL use_crlf)
+write_chunk(int fd, transport_ctx * tctx, uschar *chunk, int len)
 {
 uschar *start = chunk;
 uschar *end = chunk + len;
@@ -408,16 +410,22 @@ possible. */
 
 for (ptr = start; ptr < end; ptr++)
   {
-  int ch;
+  int ch, len;
 
   /* Flush the buffer if it has reached the threshold - we want to leave enough
   room for the next uschar, plus a possible extra CR for an LF, plus the escape
   string. */
 
-  if (chunk_ptr - deliver_out_buffer > mlen)
+  if ((len = chunk_ptr - deliver_out_buffer) > mlen)
     {
-    if (!transport_write_block(fd, deliver_out_buffer,
-          chunk_ptr - deliver_out_buffer))
+    /* If CHUNKING, prefix with BDAT (size) NON-LAST.  Also, reap responses
+    from previous SMTP commands. */
+
+    if (tctx &&  tctx->options & topt_use_bdat  &&  tctx->chunk_cb)
+      if (tctx->chunk_cb(fd, tctx, (unsigned)len, tc_reap_prev|tc_reap_one) != OK)
+       return FALSE;
+
+    if (!transport_write_block(fd, deliver_out_buffer, len))
       return FALSE;
     chunk_ptr = deliver_out_buffer;
     }
@@ -428,7 +436,7 @@ for (ptr = start; ptr < end; ptr++)
 
     /* Insert CR before NL if required */
 
-    if (use_crlf) *chunk_ptr++ = '\r';
+    if (tctx  &&  tctx->options & topt_use_crlf) *chunk_ptr++ = '\r';
     *chunk_ptr++ = '\n';
     transport_newlines++;
 
@@ -545,14 +553,14 @@ Arguments:
   pdlist    address of anchor of the list of processed addresses
   first     TRUE if this is the first address; set it FALSE afterwards
   fd        the file descriptor to write to
-  use_crlf  to be passed on to write_chunk()
+  tctx      transport context - processing to be done during output
 
 Returns:    FALSE if writing failed
 */
 
 static BOOL
 write_env_to(address_item *p, struct aci **pplist, struct aci **pdlist,
-  BOOL *first, int fd, BOOL use_crlf)
+  BOOL *first, int fd, transport_ctx * tctx)
 {
 address_item *pp;
 struct aci *ppp;
@@ -574,7 +582,7 @@ for (pp = p;; pp = pp->parent)
   address_item *dup;
   for (dup = addr_duplicate; dup; dup = dup->next)
     if (dup->dupof == pp)   /* a dup of our address */
-      if (!write_env_to(dup, pplist, pdlist, first, fd, use_crlf))
+      if (!write_env_to(dup, pplist, pdlist, first, fd, tctx))
        return FALSE;
   if (!pp->parent) break;
   }
@@ -591,9 +599,9 @@ ppp->next = *pplist;
 *pplist = ppp;
 ppp->ptr = pp;
 
-if (!(*first) && !write_chunk(fd, US",\n ", 3, use_crlf)) return FALSE;
+if (!*first && !write_chunk(fd, tctx, US",\n ", 3)) return FALSE;
 *first = FALSE;
-return write_chunk(fd, pp->address, Ustrlen(pp->address), use_crlf);
+return write_chunk(fd, tctx, pp->address, Ustrlen(pp->address));
 }
 
 
@@ -608,20 +616,19 @@ 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
+  tctx                  transport context
+  sendfn               function for output (transport or verify)
 
 Returns:                TRUE on success; FALSE on failure.
 */
 BOOL
-transport_headers_send(address_item *addr, int fd, transport_instance * tblock,
-  BOOL (*sendfn)(int fd, uschar * s, int len, BOOL use_crlf),
-  BOOL use_crlf)
+transport_headers_send(int fd, transport_ctx * tctx,
+  BOOL (*sendfn)(int fd, transport_ctx * tctx, uschar * s, int len))
 {
 header_line *h;
 const uschar *list;
+transport_instance * tblock = tctx ? tctx->tblock : NULL;
+address_item * addr = tctx ? tctx->addr : NULL;
 
 /* 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
@@ -676,7 +683,7 @@ for (h = header_list; h; h = h->next) if (h->type != htype_old)
       if ((hh = rewrite_header(h, NULL, NULL, tblock->rewrite_rules,
                  tblock->rewrite_existflags, FALSE)))
        {
-       if (!sendfn(fd, hh->text, hh->slen, use_crlf)) return FALSE;
+       if (!sendfn(fd, tctx, hh->text, hh->slen)) return FALSE;
        store_reset(reset_point);
        continue;     /* With the next header line */
        }
@@ -684,7 +691,7 @@ for (h = header_list; h; h = h->next) if (h->type != htype_old)
 
     /* Either no rewriting rules, or it didn't get rewritten */
 
-    if (!sendfn(fd, h->text, h->slen, use_crlf)) return FALSE;
+    if (!sendfn(fd, tctx, h->text, h->slen)) return FALSE;
     }
 
   /* Header removed */
@@ -719,7 +726,7 @@ if (addr)
       hprev = h;
       if (i == 1)
        {
-       if (!sendfn(fd, h->text, h->slen, use_crlf)) return FALSE;
+       if (!sendfn(fd, tctx, h->text, h->slen)) return FALSE;
        DEBUG(D_transport)
          debug_printf("added header line(s):\n%s---\n", h->text);
        }
@@ -744,8 +751,8 @@ if (tblock && (list = CUS tblock->add_headers))
       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))
+       if (!sendfn(fd, tctx, s, len)) return FALSE;
+       if (s[len-1] != '\n' && !sendfn(fd, tctx, US"\n", 1))
          return FALSE;
        DEBUG(D_transport)
          {
@@ -761,7 +768,7 @@ if (tblock && (list = CUS tblock->add_headers))
 
 /* Separate headers from body with a blank line */
 
-return sendfn(fd, US"\n", 1, use_crlf);
+return sendfn(fd, tctx, US"\n", 1);
 }
 
 
@@ -814,12 +821,12 @@ Arguments:
       end_dot               if TRUE, send a terminating "." line at the end
       no_headers            if TRUE, omit the headers
       no_body               if TRUE, omit the body
-    size_limit            if > 0, this is a limit to the size of message written;
+    check_string          a string to check for at the start of lines, or NULL
+    escape_string         a string to insert in front of any check string
+  size_limit              if > 0, this is a limit to the size of message written;
                             it is used when returning messages to their senders,
                             and is approximate rather than exact, owing to chunk
                             buffering
-    check_string          a string to check for at the start of lines, or NULL
-    escape_string         a string to insert in front of any check string
 
 Returns:                TRUE on success; FALSE (with errno) on failure.
                         In addition, the global variable transport_count
@@ -829,9 +836,7 @@ Returns:                TRUE on success; FALSE (with errno) on failure.
 static BOOL
 internal_transport_write_message(int fd, transport_ctx * tctx, int size_limit)
 {
-int written = 0;
 int len;
-BOOL use_crlf = (tctx->options & topt_use_crlf) != 0;
 
 /* Initialize pointer in output buffer. */
 
@@ -869,7 +874,7 @@ if (!(tctx->options & topt_no_headers))
     uschar buffer[ADDRESS_MAXLENGTH + 20];
     int n = sprintf(CS buffer, "Return-path: <%.*s>\n", ADDRESS_MAXLENGTH,
       return_path);
-    if (!write_chunk(fd, buffer, n, use_crlf)) return FALSE;
+    if (!write_chunk(fd, tctx, buffer, n)) return FALSE;
     }
 
   /* Add envelope-to: if requested */
@@ -882,19 +887,19 @@ if (!(tctx->options & topt_no_headers))
     struct aci *dlist = NULL;
     void *reset_point = store_get(0);
 
-    if (!write_chunk(fd, US"Envelope-to: ", 13, use_crlf)) return FALSE;
+    if (!write_chunk(fd, tctx, US"Envelope-to: ", 13)) return FALSE;
 
     /* Pick up from all the addresses. The plist and dlist variables are
     anchors for lists of addresses already handled; they have to be defined at
     this level becuase write_env_to() calls itself recursively. */
 
     for (p = tctx->addr; p; p = p->next)
-      if (!write_env_to(p, &plist, &dlist, &first, fd, use_crlf))
+      if (!write_env_to(p, &plist, &dlist, &first, fd, tctx))
        return FALSE;
 
     /* Add a final newline and reset the store used for tracking duplicates */
 
-    if (!write_chunk(fd, US"\n", 1, use_crlf)) return FALSE;
+    if (!write_chunk(fd, tctx, US"\n", 1)) return FALSE;
     store_reset(reset_point);
     }
 
@@ -904,7 +909,7 @@ if (!(tctx->options & topt_no_headers))
     {
     uschar buffer[100];
     int n = sprintf(CS buffer, "Delivery-date: %s\n", tod_stamp(tod_full));
-    if (!write_chunk(fd, buffer, n, use_crlf)) return FALSE;
+    if (!write_chunk(fd, tctx, buffer, n)) return FALSE;
     }
 
   /* Then the message's headers. Don't write any that are flagged as "old";
@@ -913,8 +918,63 @@ if (!(tctx->options & topt_no_headers))
   match any entries therein. Then check addr->prop.remove_headers too, provided that
   addr is not NULL. */
 
-  if (!transport_headers_send(tctx->addr, fd, tctx->tblock, &write_chunk, use_crlf))
+  if (!transport_headers_send(fd, tctx, &write_chunk))
+    return FALSE;
+  }
+
+/* When doing RFC3030 CHUNKING output, work out how much data will be in the
+last BDAT, consisting of the current write_chunk() output buffer fill
+(optimally, all of the headers - but it does not matter if we already had to
+flush that buffer with non-last BDAT prependix) plus the amount of body data
+(as expanded for CRLF lines).  Then create and write the BDAT, and ensure
+that further use of write_chunk() will not prepend BDATs.
+The first BDAT written will also first flush any outstanding MAIL and RCPT
+commands which were buffered thans to PIPELINING.
+Commands go out (using a send()) from a different buffer to data (using a
+write()).  They might not end up in the same TCP segment, which is
+suboptimal. */
+
+if (tctx->options & topt_use_bdat)
+  {
+  off_t fsize;
+  int hsize, size;
+
+  if ((hsize = chunk_ptr - deliver_out_buffer) < 0)
+    hsize = 0;
+  if (!(tctx->options & topt_no_body))
+    {
+    if ((fsize = lseek(deliver_datafile, 0, SEEK_END)) < 0) return FALSE;
+    fsize -= SPOOL_DATA_START_OFFSET;
+    if (size_limit > 0  &&  fsize > size_limit)
+      fsize = size_limit;
+    size = hsize + fsize;
+    if (tctx->options & topt_use_crlf)
+      size += body_linecount;  /* account for CRLF-expansion */
+    }
+
+  /* If the message is large, emit first a non-LAST chunk with just the
+  headers, and reap the command responses.  This lets us error out early
+  on RCPT rejects rather than sending megabytes of data.  Include headers
+  on the assumption they are cheap enough and some clever implementations
+  might errorcheck them too, on-the-fly, and reject that chunk. */
+
+  if (size > DELIVER_OUT_BUFFER_SIZE && hsize > 0)
+    {
+    if (  tctx->chunk_cb(fd, tctx, hsize, 0) != OK
+       || !transport_write_block(fd, deliver_out_buffer, hsize)
+       || tctx->chunk_cb(fd, tctx, 0, tc_reap_prev) != OK
+       )
+      return FALSE;
+    chunk_ptr = deliver_out_buffer;
+    size -= hsize;
+    }
+
+  /* Emit a LAST datachunk command. */
+
+  if (tctx->chunk_cb(fd, tctx, size, tc_chunk_last) != OK)
     return FALSE;
+
+  tctx->options &= ~topt_use_bdat;
   }
 
 /* If the body is required, ensure that the data for check strings (formerly
@@ -925,23 +985,18 @@ it, applying the size limit if required. */
 
 if (!(tctx->options & topt_no_body))
   {
+  int size = size_limit;
+
   nl_check_length = abs(nl_check_length);
   nl_partial_match = 0;
   if (lseek(deliver_datafile, SPOOL_DATA_START_OFFSET, SEEK_SET) < 0)
     return FALSE;
-  while ((len = read(deliver_datafile, deliver_in_buffer,
-           DELIVER_IN_BUFFER_SIZE)) > 0)
+  while (  (len = MAX(DELIVER_IN_BUFFER_SIZE, size)) > 0
+       && (len = read(deliver_datafile, deliver_in_buffer, len)) > 0)
     {
-    if (!write_chunk(fd, deliver_in_buffer, len, use_crlf)) return FALSE;
-    if (size_limit > 0)
-      {
-      written += len;
-      if (written > size_limit)
-        {
-        len = 0;    /* Pretend EOF */
-        break;
-        }
-      }
+    if (!write_chunk(fd, tctx, deliver_in_buffer, len))
+      return FALSE;
+    size -= len;
     }
 
   /* A read error on the body will have left len == -1 and errno set. */
@@ -955,7 +1010,7 @@ nl_check_length = nl_escape_length = 0;
 
 /* If requested, add a terminating "." line (SMTP output). */
 
-if (tctx->options & topt_end_dot && !write_chunk(fd, US".\n", 2, use_crlf))
+if (tctx->options & topt_end_dot && !write_chunk(fd, tctx, US".\n", 2))
   return FALSE;
 
 /* Write out any remaining data in the buffer before returning. */
@@ -997,7 +1052,9 @@ uschar * dkim_spool_name;
 int sread = 0;
 int wwritten = 0;
 uschar *dkim_signature = NULL;
+int siglen = 0;
 off_t k_file_size;
+int options;
 
 /* If we can't sign, just call the original function. */
 
@@ -1017,7 +1074,10 @@ if ((dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE)) < 0)
 
 /* Call original function to write the -K file; does the CRLF expansion */
 
+options = tctx->options;
+tctx->options &= ~topt_use_bdat;
 rc = transport_write_message(dkim_fd, tctx, 0);
+tctx->options = options;
 
 /* Save error state. We must clean up before returning. */
 if (!rc)
@@ -1026,60 +1086,61 @@ if (!rc)
   goto CLEANUP;
   }
 
-if (dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector)
+/* Rewind file and feed it to the goats^W DKIM lib */
+lseek(dkim_fd, 0, SEEK_SET);
+dkim_signature = dkim_exim_sign(dkim_fd,
+                               dkim->dkim_private_key,
+                               dkim->dkim_domain,
+                               dkim->dkim_selector,
+                               dkim->dkim_canon,
+                               dkim->dkim_sign_headers);
+if (dkim_signature)
+  siglen = Ustrlen(dkim_signature);
+else if (dkim->dkim_strict)
   {
-  /* Rewind file and feed it to the goats^W DKIM lib */
-  lseek(dkim_fd, 0, SEEK_SET);
-  dkim_signature = dkim_exim_sign(dkim_fd,
-                                 dkim->dkim_private_key,
-                                 dkim->dkim_domain,
-                                 dkim->dkim_selector,
-                                 dkim->dkim_canon,
-                                 dkim->dkim_sign_headers);
-  if (!dkim_signature)
-    {
-    if (dkim->dkim_strict)
+  uschar *dkim_strict_result = expand_string(dkim->dkim_strict);
+  if (dkim_strict_result)
+    if ( (strcmpic(dkim->dkim_strict,US"1") == 0) ||
+        (strcmpic(dkim->dkim_strict,US"true") == 0) )
       {
-      uschar *dkim_strict_result = expand_string(dkim->dkim_strict);
-      if (dkim_strict_result)
-       if ( (strcmpic(dkim->dkim_strict,US"1") == 0) ||
-            (strcmpic(dkim->dkim_strict,US"true") == 0) )
-         {
-         /* Set errno to something halfway meaningful */
-         save_errno = EACCES;
-         log_write(0, LOG_MAIN, "DKIM: message could not be signed,"
-           " and dkim_strict is set. Deferring message delivery.");
-         rc = FALSE;
-         goto CLEANUP;
-         }
+      /* Set errno to something halfway meaningful */
+      save_errno = EACCES;
+      log_write(0, LOG_MAIN, "DKIM: message could not be signed,"
+       " and dkim_strict is set. Deferring message delivery.");
+      rc = FALSE;
+      goto CLEANUP;
       }
-    }
+  }
 
-  if (dkim_signature)
-    {
-    int siglen = Ustrlen(dkim_signature);
-    while(siglen > 0)
-      {
-#ifdef SUPPORT_TLS
-       wwritten = tls_out.active == out_fd
-         ? tls_write(FALSE, dkim_signature, siglen)
-         : write(out_fd, dkim_signature, siglen);
-#else
-       wwritten = write(out_fd, dkim_signature, siglen);
+#ifndef HAVE_LINUX_SENDFILE
+if (options & topt_use_bdat)
 #endif
-      if (wwritten == -1)
-       {
-       /* error, bail out */
-       save_errno = errno;
-       rc = FALSE;
-       goto CLEANUP;
-       }
-      siglen -= wwritten;
-      dkim_signature += wwritten;
-      }
+  k_file_size = lseek(dkim_fd, 0, SEEK_END); /* Fetch file size */
+
+if (options & topt_use_bdat)
+  {
+
+  /* On big messages output a precursor chunk to get any pipelined
+  MAIL & RCPT commands flushed, then reap the responses so we can
+  error out on RCPT rejects before sending megabytes. */
+
+  if (siglen + k_file_size > DELIVER_OUT_BUFFER_SIZE && siglen > 0)
+    {
+    if (  tctx->chunk_cb(out_fd, tctx, siglen, 0) != OK
+       || !transport_write_block(out_fd, dkim_signature, siglen)
+       || tctx->chunk_cb(out_fd, tctx, 0, tc_reap_prev) != OK
+       )
+      goto err;
+    siglen = 0;
     }
+
+  if (tctx->chunk_cb(out_fd, tctx, siglen + k_file_size, tc_chunk_last) != OK)
+    goto err;
   }
 
+if(siglen > 0 && !transport_write_block(out_fd, dkim_signature, siglen))
+  goto err;
+
 #ifdef HAVE_LINUX_SENDFILE
 /* We can use sendfile() to shove the file contents
    to the socket. However only if we don't use TLS,
@@ -1090,18 +1151,13 @@ if (tls_out.active != out_fd)
   ssize_t copied = 0;
   off_t offset = 0;
 
-  k_file_size = lseek(dkim_fd, 0, SEEK_END); /* Fetch file size */
-
   /* Rewind file */
   lseek(dkim_fd, 0, SEEK_SET);
 
   while(copied >= 0 && offset < k_file_size)
     copied = sendfile(out_fd, dkim_fd, &offset, k_file_size - offset);
   if (copied < 0)
-    {
-    save_errno = errno;
-    rc = FALSE;
-    }
+    goto err;
   }
 else
 
@@ -1127,12 +1183,7 @@ else
       wwritten = write(out_fd, p, sread);
 #endif
       if (wwritten == -1)
-       {
-       /* error, bail out */
-       save_errno = errno;
-       rc = FALSE;
-       goto CLEANUP;
-       }
+       goto err;
       p += wwritten;
       sread -= wwritten;
       }
@@ -1146,11 +1197,16 @@ else
   }
 
 CLEANUP:
-/* unlink -K file */
-(void)close(dkim_fd);
-Uunlink(dkim_spool_name);
-errno = save_errno;
-return rc;
+  /* unlink -K file */
+  (void)close(dkim_fd);
+  Uunlink(dkim_spool_name);
+  errno = save_errno;
+  return rc;
+
+err:
+  save_errno = errno;
+  rc = FALSE;
+  goto CLEANUP;
 }
 
 #endif
@@ -1177,12 +1233,12 @@ Returns:       TRUE on success; FALSE (with errno) for any failure
 BOOL
 transport_write_message(int fd, transport_ctx * tctx, int size_limit)
 {
-BOOL use_crlf;
+unsigned wck_flags;
 BOOL last_filter_was_NL = TRUE;
 int rc, len, yield, fd_read, fd_write, save_errno;
 int pfd[2] = {-1, -1};
 pid_t filter_pid, write_pid;
-static transport_ctx dummy_tctx = { NULL, NULL, NULL, NULL, 0 };
+static transport_ctx dummy_tctx = {0};
 
 if (!tctx) tctx = &dummy_tctx;
 
@@ -1201,7 +1257,7 @@ if (  !transport_filter_argv
 before being written to the incoming fd. First set up the special processing to
 be done during the copying. */
 
-use_crlf = (tctx->options & topt_use_crlf) != 0;
+wck_flags = tctx->options & topt_use_crlf;
 nl_partial_match = -1;
 
 if (tctx->check_string && tctx->escape_string)
@@ -1248,7 +1304,7 @@ if ((write_pid = fork()) == 0)
   nl_check_length = nl_escape_length = 0;
 
   tctx->check_string = tctx->escape_string = NULL;
-  tctx->options &= ~(topt_use_crlf | topt_end_dot);
+  tctx->options &= ~(topt_use_crlf | topt_end_dot | topt_use_bdat);
 
   rc = internal_transport_write_message(fd_write, tctx, size_limit);
 
@@ -1317,7 +1373,7 @@ for (;;)
 
   if (len > 0)
     {
-    if (!write_chunk(fd, deliver_in_buffer, len, use_crlf)) goto TIDY_UP;
+    if (!write_chunk(fd, tctx, deliver_in_buffer, len)) goto TIDY_UP;
     last_filter_was_NL = (deliver_in_buffer[len-1] == '\n');
     }
 
@@ -1399,8 +1455,8 @@ if (yield)
   nl_check_length = nl_escape_length = 0;
   if (  tctx->options & topt_end_dot
      && ( last_filter_was_NL
-        ? !write_chunk(fd, US".\n", 2, use_crlf)
-       : !write_chunk(fd, US"\n.\n", 3, use_crlf)
+        ? !write_chunk(fd, tctx, US".\n", 2)
+       : !write_chunk(fd, tctx, US"\n.\n", 3)
      )  )
     yield = FALSE;
 
@@ -1883,7 +1939,7 @@ DEBUG(D_transport) debug_printf("transport_pass_socket entered\n");
 
 if ((pid = fork()) == 0)
   {
-  int i = 16;
+  int i = 17;
   const uschar **argv;
 
   /* Disconnect entirely from the parent process. If we are running in the
@@ -1899,16 +1955,15 @@ if ((pid = fork()) == 0)
 
   argv = CUSS child_exec_exim(CEE_RETURN_ARGV, TRUE, &i, FALSE, 0);
 
-  if (smtp_use_dsn) argv[i++] = US"-MCD";
-
   if (smtp_authenticated) argv[i++] = US"-MCA";
 
-  #ifdef SUPPORT_TLS
-  if (tls_offered) argv[i++] = US"-MCT";
-  #endif
-
-  if (smtp_use_size) argv[i++] = US"-MCS";
-  if (smtp_use_pipelining) argv[i++] = US"-MCP";
+  if (smtp_peer_options & PEER_OFFERED_CHUNKING) argv[i++] = US"-MCK";
+  if (smtp_peer_options & PEER_OFFERED_DSN) argv[i++] = US"-MCD";
+  if (smtp_peer_options & PEER_OFFERED_PIPE) argv[i++] = US"-MCP";
+  if (smtp_peer_options & PEER_OFFERED_SIZE) argv[i++] = US"-MCS";
+#ifdef SUPPORT_TLS
+  if (smtp_peer_options & PEER_OFFERED_TLS) argv[i++] = US"-MCT";
+#endif
 
   if (queue_run_pid != (pid_t)0)
     {
index 36a68b9..f07cd83 100644 (file)
@@ -694,8 +694,7 @@ if (return_message)
   transport_ctx tctx = {
     tblock,
     addr,
-    NULL,
-    NULL,
+    NULL, NULL,
     (tblock->body_only ? topt_no_headers : 0) |
     (tblock->headers_only ? topt_no_body : 0) |
     (tblock->return_path_add ? topt_add_return_path : 0) |
index 9624ece..0cc9810 100644 (file)
@@ -612,8 +612,7 @@ if (send_data)
   transport_ctx tctx = {
     tblock,
     addrlist,
-    US".",
-    US"..",
+    US".", US"..",
     ob->options
   };
 
index e3d0197..d3841e0 100644 (file)
@@ -554,7 +554,7 @@ const uschar **argv;
 uschar *envp[50];
 const uschar *envlist = ob->environment;
 uschar *cmd, *ss;
-uschar *eol = (ob->use_crlf)? US"\r\n" : US"\n";
+uschar *eol = ob->use_crlf ? US"\r\n" : US"\n";
 transport_ctx tctx = {
   tblock,
   addr,
index bbfef06..52b2b91 100644 (file)
@@ -12,6 +12,8 @@
 #define PENDING_DEFER   (PENDING + DEFER)
 #define PENDING_OK      (PENDING + OK)
 
+#define DELIVER_BUFFER_SIZE 4096
+
 
 /* Options specific to the smtp transport. This transport also supports LMTP
 over TCP/IP. The options must be in alphabetic order (note that "_" comes
@@ -116,6 +118,8 @@ optionlist smtp_transport_options[] = {
 #endif
   { "hosts_try_auth",       opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, hosts_try_auth) },
+  { "hosts_try_chunking",   opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, hosts_try_chunking) },
 #if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
   { "hosts_try_dane",       opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, hosts_try_dane) },
@@ -200,12 +204,13 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   NULL,                /* serialize_hosts */
   NULL,                /* hosts_try_auth */
   NULL,                /* hosts_require_auth */
+  US"*",               /* hosts_try_chunking */
 #ifdef EXPERIMENTAL_DANE
   NULL,                /* hosts_try_dane */
   NULL,                /* hosts_require_dane */
 #endif
 #ifndef DISABLE_PRDR
-  US"*",                /* hosts_try_prdr */
+  US"*",               /* hosts_try_prdr */
 #endif
 #ifndef DISABLE_OCSP
   US"*",               /* hosts_request_ocsp (except under DANE; tls_client_start()) */
@@ -778,6 +783,7 @@ if (pending_MAIL)
   count--;
   if (!smtp_read_response(inblock, buffer, buffsize, '2', timeout))
     {
+    DEBUG(D_transport) debug_printf("bad response for MAIL\n");
     Ustrcpy(big_buffer, mail_command);  /* Fits, because it came from there! */
     if (errno == 0 && buffer[0] != 0)
       {
@@ -1321,6 +1327,10 @@ if (  checks & PEER_OFFERED_IGNQ
                PCRE_EOPT, NULL, 0) < 0)
   checks &= ~PEER_OFFERED_IGNQ;
 
+if (  checks & PEER_OFFERED_CHUNKING
+   && pcre_exec(regex_CHUNKING, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_CHUNKING;
+
 #ifndef DISABLE_PRDR
 if (  checks & PEER_OFFERED_PRDR
    && pcre_exec(regex_PRDR, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
@@ -1350,6 +1360,99 @@ return checks;
 }
 
 
+
+/* Callback for emitting a BDAT data chunk header.
+
+If given a nonzero size, first flush any buffered SMTP commands
+then emit the command.
+
+Reap previous SMTP command responses if requested.
+Reap one SMTP command response if requested.
+
+Returns:       OK or ERROR
+*/
+
+static int
+smtp_chunk_cmd_callback(int fd, transport_ctx * tctx,
+  unsigned chunk_size, unsigned flags)
+{
+smtp_transport_options_block * ob =
+  (smtp_transport_options_block *)(tctx->tblock->options_block);
+int cmd_count = 0;
+int prev_cmd_count;
+uschar * buffer = tctx->buffer;
+
+
+/* Write SMTP chunk header command */
+
+if (chunk_size > 0)
+  if((cmd_count = smtp_write_command(tctx->outblock, FALSE, "BDAT %u%s\r\n",
+                             chunk_size,
+                             flags & tc_chunk_last ? " LAST" : "")
+     ) < 0) return ERROR;
+
+prev_cmd_count = cmd_count += tctx->cmd_count;
+
+/* Reap responses for any previous, but not one we just emitted */
+
+if (chunk_size > 0)
+  prev_cmd_count--;
+if (tctx->pending_BDAT)
+  prev_cmd_count--;
+
+if (flags & tc_reap_prev  &&  prev_cmd_count > 0)
+  {
+
+  switch(sync_responses(tctx->first_addr, tctx->tblock->rcpt_include_affixes,
+         tctx->sync_addr, tctx->host, prev_cmd_count,
+         ob->address_retry_include_sender,
+         tctx->pending_MAIL, 0,
+         tctx->inblock,
+         ob->command_timeout,
+         buffer, DELIVER_BUFFER_SIZE))
+    {
+    case 1:                            /* 2xx (only) => OK */
+    case 3: tctx->good_RCPT = TRUE;    /* 2xx & 5xx => OK & progress made */
+    case 2: *tctx->completed_address = TRUE; /* 5xx (only) => progress made */
+    case 0: break;                     /* No 2xx or 5xx, but no probs */
+
+    case -1:                           /* Timeout on RCPT */
+    default: return ERROR;             /* I/O error, or any MAIL/DATA error */
+    }
+  cmd_count = 1;
+  if (!tctx->pending_BDAT)
+    pipelining_active = FALSE;
+  }
+
+/* Reap response for the cmd we just emitted, or an outstanding BDAT */
+
+if (flags & tc_reap_one  ||  tctx->pending_BDAT)
+  {
+  if (!smtp_read_response(tctx->inblock, buffer, DELIVER_BUFFER_SIZE, '2',
+       ob->command_timeout))
+    {
+    if (errno == 0 && buffer[0] == '4')
+      {
+      errno = ERRNO_DATA4XX;   /*XXX does this actually get used? */
+      tctx->first_addr->more_errno |=
+       ((buffer[1] - '0')*10 + buffer[2] - '0') << 8;
+      }
+    return ERROR;
+    }
+  cmd_count--;
+  tctx->pending_BDAT = FALSE;
+  pipelining_active = FALSE;
+  }
+else if (chunk_size > 0)
+  tctx->pending_BDAT = TRUE;
+
+
+tctx->cmd_count = cmd_count;
+return OK;
+}
+
+
+
 /*************************************************
 *       Deliver address list to given host       *
 *************************************************/
@@ -1419,7 +1522,7 @@ BOOL completed_address = FALSE;
 BOOL esmtp = TRUE;
 BOOL pending_MAIL;
 BOOL pass_message = FALSE;
-uschar peer_offered = 0;       /*XXX should this be handed on cf. tls_offered, smtp_use_dsn ? */
+uschar peer_offered = 0;
 #ifndef DISABLE_PRDR
 BOOL prdr_active;
 #endif
@@ -1446,7 +1549,7 @@ uschar *helo_data = NULL;
 uschar *message = NULL;
 uschar new_message_id[MESSAGE_ID_LENGTH + 1];
 uschar *p;
-uschar buffer[4096];
+uschar buffer[DELIVER_BUFFER_SIZE];
 uschar inbuffer[4096];
 uschar outbuffer[4096];
 
@@ -1654,7 +1757,7 @@ goto SEND_QUIT;
 #ifdef SUPPORT_TLS
   if (smtps)
     {
-    tls_offered = TRUE;
+    smtp_peer_options |= PEER_OFFERED_TLS;
     suppress_tls = FALSE;
     ob->tls_tempfail_tryclear = FALSE;
     smtp_command = US"SSL-on-connect";
@@ -1703,7 +1806,10 @@ goto SEND_QUIT;
     if (!good_response) goto RESPONSE_FAILED;
     }
 
+  peer_offered = smtp_peer_options = 0;
+
   if (esmtp || lmtp)
+    {
     peer_offered = ehlo_response(buffer, Ustrlen(buffer),
       PEER_OFFERED_TLS /* others checked later */
       );
@@ -1711,14 +1817,15 @@ goto SEND_QUIT;
   /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
 
 #ifdef SUPPORT_TLS
-  tls_offered = !!(peer_offered & PEER_OFFERED_TLS);
+    smtp_peer_options |= peer_offered & PEER_OFFERED_TLS;
 #endif
+    }
   }
 
 /* For continuing deliveries down the same channel, the socket is the standard
 input, and we don't need to redo EHLO here (but may need to do so for TLS - see
 below). Set up the pointer to where subsequent commands will be left, for
-error messages. Note that smtp_use_size and smtp_use_pipelining will have been
+error messages. Note that smtp_peer_options will have been
 set from the command line if they were set in the process that passed the
 connection on. */
 
@@ -1743,7 +1850,7 @@ the client not be required to use TLS. If the response is bad, copy the buffer
 for error analysis. */
 
 #ifdef SUPPORT_TLS
-if (  tls_offered
+if (  smtp_peer_options & PEER_OFFERED_TLS
    && !suppress_tls
    && verify_check_given_host(&ob->hosts_avoid_tls, host) != OK)
   {
@@ -1805,6 +1912,7 @@ if (  tls_offered
 
     /* TLS session is set up */
 
+    smtp_peer_options_wrap = smtp_peer_options;
     for (addr = addrlist; addr; addr = addr->next)
       if (addr->transport_return == PENDING_DEFER)
         {
@@ -1874,6 +1982,7 @@ if (tls_out.active >= 0)
   helo_response = string_copy(buffer);
 #endif
   if (!good_response) goto RESPONSE_FAILED;
+  smtp_peer_options = 0;
   }
 
 /* If the host is required to use a secure channel, ensure that we
@@ -1888,8 +1997,8 @@ else if (  smtps
   {
   save_errno = ERRNO_TLSREQUIRED;
   message = string_sprintf("a TLS session is required, but %s",
-    tls_offered ? "an attempt to start TLS failed"
-               : "the server did not offer TLS support");
+    smtp_peer_options & PEER_OFFERED_TLS
+    ? "an attempt to start TLS failed" : "the server did not offer TLS support");
   goto TLS_FAILED;
   }
 #endif /*SUPPORT_TLS*/
@@ -1906,13 +2015,15 @@ if (continue_hostname == NULL
     )
   {
   if (esmtp || lmtp)
+    {
     peer_offered = ehlo_response(buffer, Ustrlen(buffer),
       0 /* no TLS */
       | (lmtp && ob->lmtp_ignore_quota ? PEER_OFFERED_IGNQ : 0)
+      | PEER_OFFERED_CHUNKING
       | PEER_OFFERED_PRDR
 #ifdef SUPPORT_I18N
       | (addrlist->prop.utf8_msg ? PEER_OFFERED_UTF8 : 0)
-       /*XXX if we hand peercaps on to continued-conn processes,
+       /*XXX if we hand peercaps on to continued-conn processes,
              must not depend on this addr */
 #endif
       | PEER_OFFERED_DSN
@@ -1920,54 +2031,64 @@ if (continue_hostname == NULL
       | (ob->size_addition >= 0 ? PEER_OFFERED_SIZE : 0)
       );
 
-  /* Set for IGNOREQUOTA if the response to LHLO specifies support and the
-  lmtp_ignore_quota option was set. */
+    /* Set for IGNOREQUOTA if the response to LHLO specifies support and the
+    lmtp_ignore_quota option was set. */
+
+    igquotstr = peer_offered & PEER_OFFERED_IGNQ ? US" IGNOREQUOTA" : US"";
 
-  igquotstr = peer_offered & PEER_OFFERED_IGNQ ? US" IGNOREQUOTA" : US"";
+    /* If the response to EHLO specified support for the SIZE parameter, note
+    this, provided size_addition is non-negative. */
 
-  /* If the response to EHLO specified support for the SIZE parameter, note
-  this, provided size_addition is non-negative. */
+    smtp_peer_options |= peer_offered & PEER_OFFERED_SIZE;
 
-  smtp_use_size = !!(peer_offered & PEER_OFFERED_SIZE);
+    /* Note whether the server supports PIPELINING. If hosts_avoid_esmtp matched
+    the current host, esmtp will be false, so PIPELINING can never be used. If
+    the current host matches hosts_avoid_pipelining, don't do it. */
 
-  /* Note whether the server supports PIPELINING. If hosts_avoid_esmtp matched
-  the current host, esmtp will be false, so PIPELINING can never be used. If
-  the current host matches hosts_avoid_pipelining, don't do it. */
+    if (  peer_offered & PEER_OFFERED_PIPE
+       && verify_check_given_host(&ob->hosts_avoid_pipelining, host) != OK)
+      smtp_peer_options |= PEER_OFFERED_PIPE;
 
-  smtp_use_pipelining = peer_offered & PEER_OFFERED_PIPE
-    && verify_check_given_host(&ob->hosts_avoid_pipelining, host) != OK;
+    DEBUG(D_transport) debug_printf("%susing PIPELINING\n",
+      smtp_peer_options & PEER_OFFERED_PIPE ? "" : "not ");
 
-  DEBUG(D_transport) debug_printf("%susing PIPELINING\n",
-    smtp_use_pipelining ? "" : "not ");
+    if (  peer_offered & PEER_OFFERED_CHUNKING
+       && verify_check_given_host(&ob->hosts_try_chunking, host) != OK)
+      peer_offered &= ~PEER_OFFERED_CHUNKING;
+
+    if (peer_offered & PEER_OFFERED_CHUNKING)
+      {DEBUG(D_transport) debug_printf("CHUNKING usable\n");}
 
 #ifndef DISABLE_PRDR
-  if (  peer_offered & PEER_OFFERED_PRDR
-     && verify_check_given_host(&ob->hosts_try_prdr, host) != OK)
-    peer_offered &= ~PEER_OFFERED_PRDR;
+    if (  peer_offered & PEER_OFFERED_PRDR
+       && verify_check_given_host(&ob->hosts_try_prdr, host) != OK)
+      peer_offered &= ~PEER_OFFERED_PRDR;
 
-  if (peer_offered & PEER_OFFERED_PRDR)
-    {DEBUG(D_transport) debug_printf("PRDR usable\n");}
+    if (peer_offered & PEER_OFFERED_PRDR)
+      {DEBUG(D_transport) debug_printf("PRDR usable\n");}
 #endif
 
-  /* Note if the server supports DSN */
-  smtp_use_dsn = !!(peer_offered & PEER_OFFERED_DSN);
-  DEBUG(D_transport) debug_printf("%susing DSN\n", smtp_use_dsn ? "" : "not ");
+    /* Note if the server supports DSN */
+    smtp_peer_options |= peer_offered & PEER_OFFERED_DSN;
+    DEBUG(D_transport) debug_printf("%susing DSN\n",
+                       peer_offered & PEER_OFFERED_DSN ? "" : "not ");
 
-  /* Note if the response to EHLO specifies support for the AUTH extension.
-  If it has, check that this host is one we want to authenticate to, and do
-  the business. The host name and address must be available when the
-  authenticator's client driver is running. */
+    /* Note if the response to EHLO specifies support for the AUTH extension.
+    If it has, check that this host is one we want to authenticate to, and do
+    the business. The host name and address must be available when the
+    authenticator's client driver is running. */
 
-  switch (yield = smtp_auth(buffer, sizeof(buffer), addrlist, host,
-                           ob, esmtp, &inblock, &outblock))
-    {
-    default:           goto SEND_QUIT;
-    case OK:           break;
-    case FAIL_SEND:    goto SEND_FAILED;
-    case FAIL:         goto RESPONSE_FAILED;
+    switch (yield = smtp_auth(buffer, sizeof(buffer), addrlist, host,
+                             ob, esmtp, &inblock, &outblock))
+      {
+      default:         goto SEND_QUIT;
+      case OK:         break;
+      case FAIL_SEND:  goto SEND_FAILED;
+      case FAIL:       goto RESPONSE_FAILED;
+      }
     }
   }
-pipelining_active = smtp_use_pipelining;
+pipelining_active = !!(smtp_peer_options & PEER_OFFERED_PIPE);
 
 /* The setting up of the SMTP call is now complete. Any subsequent errors are
 message-specific. */
@@ -2013,6 +2134,16 @@ if (tblock->filter_command != NULL)
     yield = ERROR;
     goto SEND_QUIT;
     }
+
+  if (  transport_filter_argv
+     && *transport_filter_argv
+     && **transport_filter_argv
+     && peer_offered & PEER_OFFERED_CHUNKING
+     )
+    {
+    peer_offered &= ~PEER_OFFERED_CHUNKING;
+    DEBUG(D_transport) debug_printf("CHUNKING not usable due to transport filter\n");
+    }
   }
 
 
@@ -2042,7 +2173,7 @@ included in the count.) */
 p = buffer;
 *p = 0;
 
-if (smtp_use_size)
+if (peer_offered & PEER_OFFERED_SIZE)
   {
   sprintf(CS p, " SIZE=%d", message_size+message_linecount+ob->size_addition);
   while (*p) p++;
@@ -2086,17 +2217,14 @@ for (dsn_all_lasthop = TRUE, addr = first_addr;
 
 /* Add any DSN flags to the mail command */
 
-if (smtp_use_dsn && !dsn_all_lasthop)
+if (peer_offered & PEER_OFFERED_DSN && !dsn_all_lasthop)
   {
   if (dsn_ret == dsn_ret_hdrs)
-    {
-    Ustrcpy(p, " RET=HDRS"); p += 9;
-    }
+    { Ustrcpy(p, " RET=HDRS"); p += 9; }
   else if (dsn_ret == dsn_ret_full)
-    {
-    Ustrcpy(p, " RET=FULL"); p += 9;
-    }
-  if (dsn_envid != NULL)
+    { Ustrcpy(p, " RET=FULL"); p += 9; }
+
+  if (dsn_envid)
     {
     string_format(p, sizeof(buffer) - (p-buffer), " ENVID=%s", dsn_envid);
     while (*p) p++;
@@ -2147,7 +2275,7 @@ pending_MAIL = TRUE;     /* The block starts with MAIL */
     }
 #endif
 
-  rc = smtp_write_command(&outblock, smtp_use_pipelining,
+  rc = smtp_write_command(&outblock, pipelining_active,
          "MAIL FROM:<%s>%s\r\n", s, buffer);
   }
 
@@ -2194,21 +2322,22 @@ for (addr = first_addr;
   BOOL no_flush;
   uschar * rcpt_addr;
 
-  addr->dsn_aware = smtp_use_dsn ? dsn_support_yes : dsn_support_no;
+  addr->dsn_aware = peer_offered & PEER_OFFERED_DSN
+    ? dsn_support_yes : dsn_support_no;
 
   if (addr->transport_return != PENDING_DEFER) continue;
 
   address_count++;
-  no_flush = smtp_use_pipelining && (!mua_wrapper || addr->next);
+  no_flush = pipelining_active && (!mua_wrapper || addr->next);
 
   /* Add any DSN flags to the rcpt command and add to the sent string */
 
   p = buffer;
   *p = 0;
 
-  if (smtp_use_dsn && !(addr->dsn_flags & rf_dsnlasthop))
+  if (peer_offered & PEER_OFFERED_DSN && !(addr->dsn_flags & rf_dsnlasthop))
     {
-    if ((addr->dsn_flags & rf_dsnflags) != 0)
+    if (addr->dsn_flags & rf_dsnflags)
       {
       int i;
       BOOL first = TRUE;
@@ -2302,15 +2431,19 @@ if (mua_wrapper)
 send DATA, but if it is FALSE (in the normal, non-wrapper case), we may still
 have a good recipient buffered up if we are pipelining. We don't want to waste
 time sending DATA needlessly, so we only send it if either ok is TRUE or if we
-are pipelining. The responses are all handled by sync_responses(). */
+are pipelining. The responses are all handled by sync_responses().
+If using CHUNKING, do not send a BDAT until we know how big a chunk we want
+to send is. */
 
-if (ok || (smtp_use_pipelining && !mua_wrapper))
+if (  !(peer_offered & PEER_OFFERED_CHUNKING)
+   && (ok || (pipelining_active && !mua_wrapper)))
   {
   int count = smtp_write_command(&outblock, FALSE, "DATA\r\n");
+
   if (count < 0) goto SEND_FAILED;
   switch(sync_responses(first_addr, tblock->rcpt_include_affixes, &sync_addr,
            host, count, ob->address_retry_include_sender, pending_MAIL,
-           ok? +1 : -1, &inblock, ob->command_timeout, buffer, sizeof(buffer)))
+           ok ? +1 : -1, &inblock, ob->command_timeout, buffer, sizeof(buffer)))
     {
     case 3: ok = TRUE;                   /* 2xx & 5xx => OK & progress made */
     case 2: completed_address = TRUE;    /* 5xx (only) => progress made */
@@ -2326,10 +2459,6 @@ if (ok || (smtp_use_pipelining && !mua_wrapper))
   pipelining_active = FALSE;
   }
 
-/* Save the first address of the next batch. */
-
-first_addr = addr;
-
 /* If there were no good recipients (but otherwise there have been no
 problems), just set ok TRUE, since we have handled address-specific errors
 already. Otherwise, it's OK to send the message. Use the check/escape mechanism
@@ -2337,15 +2466,20 @@ for handling the SMTP dot-handling protocol, flagging to apply to headers as
 well as body. Set the appropriate timeout value to be used for each chunk.
 (Haven't been able to make it work using select() for writing yet.) */
 
-if (!ok)
+if (!(peer_offered & PEER_OFFERED_CHUNKING) && !ok)
+  {
+  /* Save the first address of the next batch. */
+  first_addr = addr;
+
   ok = TRUE;
+  }
 else
   {
   transport_ctx tctx = {
     tblock,
     addrlist,
     US".", US"..",    /* Escaping strings */
-    topt_use_crlf | topt_end_dot | topt_escape_headers
+    topt_use_crlf | topt_escape_headers
     | (tblock->body_only       ? topt_no_headers : 0)
     | (tblock->headers_only    ? topt_no_body : 0)
     | (tblock->return_path_add ? topt_add_return_path : 0)
@@ -2353,11 +2487,47 @@ else
     | (tblock->envelope_to_add ? topt_add_envelope_to : 0)
   };
 
+  /* If using CHUNKING we need a callback from the generic transport
+  support to us, for the sending of BDAT smtp commands and the reaping
+  of responses.  The callback needs a whole bunch of state so set up
+  a transport-context structure to be passed around. */
+
+  if (peer_offered & PEER_OFFERED_CHUNKING)
+    {
+    tctx.check_string = tctx.escape_string = NULL;
+    tctx.options |= topt_use_bdat;
+    tctx.chunk_cb = smtp_chunk_cmd_callback;
+    tctx.inblock = &inblock;
+    tctx.outblock = &outblock;
+    tctx.host = host;
+    tctx.first_addr = first_addr;
+    tctx.sync_addr = &sync_addr;
+    tctx.pending_MAIL = pending_MAIL;
+    tctx.pending_BDAT = FALSE;
+    tctx.good_RCPT = ok;
+    tctx.completed_address = &completed_address;
+    tctx.cmd_count = 0;
+    tctx.buffer = buffer;
+    }
+  else
+    tctx.options |= topt_end_dot;
+
+  /* Save the first address of the next batch. */
+  first_addr = addr;
+
+  /* Responses from CHUNKING commands go in buffer.  Otherwise,
+  there has not been a response. */
+
+  buffer[0] = 0;
+
   sigalrm_seen = FALSE;
   transport_write_timeout = ob->data_timeout;
   smtp_command = US"sending data block";   /* For error messages */
   DEBUG(D_transport|D_v)
-    debug_printf("  SMTP>> writing message and terminating \".\"\n");
+    if (peer_offered & PEER_OFFERED_CHUNKING)
+      debug_printf("         will write message using CHUNKING\n");
+    else
+      debug_printf("  SMTP>> writing message and terminating \".\"\n");
   transport_count = 0;
 
 #ifndef DISABLE_DKIM
@@ -2374,13 +2544,11 @@ else
   transport_write_timeout = 0;   /* for subsequent transports */
 
   /* Failure can either be some kind of I/O disaster (including timeout),
-  or the failure of a transport filter or the expansion of added headers. */
+  or the failure of a transport filter or the expansion of added headers.
+  Or, when CHUNKING, it can be a protocol-detected failure. */
 
   if (!ok)
-    {
-    buffer[0] = 0;              /* There hasn't been a response */
     goto RESPONSE_FAILED;
-    }
 
   /* We used to send the terminating "." explicitly here, but because of
   buffering effects at both ends of TCP/IP connections, you don't gain
@@ -2390,6 +2558,27 @@ else
 
   smtp_command = US"end of data";
 
+  if (peer_offered & PEER_OFFERED_CHUNKING && tctx.cmd_count > 1)
+    {
+    /* Reap any outstanding MAIL & RCPT commands, but not a DATA-go-ahead */
+    switch(sync_responses(first_addr, tblock->rcpt_include_affixes, &sync_addr,
+            host, tctx.cmd_count-1, ob->address_retry_include_sender,
+            pending_MAIL, 0,
+            &inblock, ob->command_timeout, buffer, sizeof(buffer)))
+      {
+      case 3: ok = TRUE;                   /* 2xx & 5xx => OK & progress made */
+      case 2: completed_address = TRUE;    /* 5xx (only) => progress made */
+      break;
+
+      case 1: ok = TRUE;                   /* 2xx (only) => OK, but if LMTP, */
+      if (!lmtp) completed_address = TRUE; /* can't tell about progress yet */
+      case 0: break;                       /* No 2xx or 5xx, but no probs */
+
+      case -1: goto END_OFF;               /* Timeout on RCPT */
+      default: goto RESPONSE_FAILED;       /* I/O error, or any MAIL/DATA error */
+      }
+    }
+
 #ifndef DISABLE_PRDR
   /* For PRDR we optionally get a partial-responses warning
    * followed by the individual responses, before going on with
@@ -2399,16 +2588,16 @@ else
     {
     ok = smtp_read_response(&inblock, buffer, sizeof(buffer), '3',
       ob->final_timeout);
-    if (!ok && errno == 0)
-      switch(buffer[0])
-        {
-       case '2': prdr_active = FALSE;
-                 ok = TRUE;
-                 break;
-       case '4': errno = ERRNO_DATA4XX;
-                  addrlist->more_errno |= ((buffer[1] - '0')*10 + buffer[2] - '0') << 8;
-                 break;
-        }
+    if (!ok && errno == 0) switch(buffer[0])
+      {
+      case '2': prdr_active = FALSE;
+               ok = TRUE;
+               break;
+      case '4': errno = ERRNO_DATA4XX;
+               addrlist->more_errno |=
+                 ((buffer[1] - '0')*10 + buffer[2] - '0') << 8;
+               break;
+      }
     }
   else
 #endif
@@ -2527,6 +2716,7 @@ else
 #ifndef DISABLE_PRDR
       if (prdr_active) addr->flags |= af_prdr_used;
 #endif
+      if (peer_offered & PEER_OFFERED_CHUNKING) addr->flags |= af_chunking_used;
       flag = '-';
 
 #ifndef DISABLE_PRDR
@@ -2853,6 +3043,7 @@ if (completed_address && ok && send_quit)
       if (tls_out.active >= 0)
         {
         tls_close(FALSE, TRUE);
+       smtp_peer_options = smtp_peer_options_wrap;
         if (smtps)
           ok = FALSE;
         else
index 804b994..d3666ae 100644 (file)
@@ -21,6 +21,7 @@ typedef struct {
   uschar *serialize_hosts;
   uschar *hosts_try_auth;
   uschar *hosts_require_auth;
+  uschar *hosts_try_chunking;
 #ifdef EXPERIMENTAL_DANE
   uschar *hosts_try_dane;
   uschar *hosts_require_dane;
index c04b288..d890f5f 100644 (file)
@@ -759,7 +759,7 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
       ? string_sprintf(" SIZE=%d", message_size + ob->size_addition) : US"";
 
 #ifdef SUPPORT_TLS
-    tls_offered = !!(peer_offered & PEER_OFFERED_TLS);
+    smtp_peer_options |= peer_offered & PEER_OFFERED_TLS;
 #endif
 
     /* If TLS is available on this connection attempt to
@@ -1559,9 +1559,9 @@ return cutthrough_response('3', NULL) == '3';
 }
 
 
-/* fd and use_crlf args only to match write_chunk() */
+/* fd and tctx args only to match write_chunk() */
 static BOOL
-cutthrough_write_chunk(int fd, uschar * s, int len, BOOL use_crlf)
+cutthrough_write_chunk(int fd, transport_ctx * tctx, uschar * s, int len)
 {
 uschar * s2;
 while(s && (s2 = Ustrchr(s, '\n')))
@@ -1580,6 +1580,8 @@ return TRUE;
 BOOL
 cutthrough_headers_send(void)
 {
+transport_ctx tctx;
+
 if(cutthrough.fd < 0)
   return FALSE;
 
@@ -1588,9 +1590,13 @@ 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,
-       &cutthrough_write_chunk, TRUE))
+tctx.tblock = cutthrough.addr.transport;
+tctx.addr = &cutthrough.addr;
+tctx.check_string = US".";
+tctx.escape_string = US"..";
+tctx.options = topt_use_crlf;
+
+if (!transport_headers_send(cutthrough.fd, &tctx, &cutthrough_write_chunk))
   return FALSE;
 
 HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
index 3beafd9..39dddd9 100644 (file)
@@ -11,3 +11,4 @@ log_file_path = DIR/spool/log/%slog
 
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
index e464f96..6a23896 100644 (file)
@@ -7,6 +7,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
 tls_advertise_hosts =
 
 # ----- Main settings -----
index e8b4c51..4f6f490 100644 (file)
@@ -11,6 +11,7 @@ spool_directory = DIR/spool
 gecos_pattern = ""
 gecos_name = CALLER_NAME
 tls_advertise_hosts =
+chunking_advertise_hosts =
 
 # ----- Main settings -----
 
diff --git a/test/confs/0900 b/test/confs/0900
new file mode 100644 (file)
index 0000000..427669c
--- /dev/null
@@ -0,0 +1,117 @@
+# Exim test configuration 0900
+SERVER=
+X=
+Y=
+OPT=
+ALLOW=
+
+exim_path = EXIM_PATH
+keep_environment =
+host_lookup_order = bydns
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/SERVER%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+chunking_advertise_hosts = *
+tls_advertise_hosts = ${if eq {Y}{tls} {*}}
+
+
+# ----- Main settings -----
+
+domainlist local_domains = @ : test.ex
+
+acl_smtp_rcpt = check_recipient
+acl_smtp_data_prdr = check_prdr
+acl_smtp_data = check_data
+trusted_users = CALLER
+queue_only
+smtp_receive_timeout = 2s
+log_selector = +received_recipients
+
+tls_certificate = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}
+tls_privatekey = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}
+
+ALLOW
+
+# ----- ACL -----
+
+begin acl
+
+check_recipient:
+  accept hosts = :
+  accept domains = +local_domains
+  deny   message = relay not permitted
+
+check_prdr:
+  accept local_parts = good
+  deny
+
+check_data:
+  warn   message = X-acl-message-linecount: $message_linecount
+  accept
+
+
+# ----- Routers -----
+
+begin routers
+
+to_server:
+  driver = accept
+  condition =  ${if !eq {SERVER}{server}}
+  transport =  remote_smtp${if eq {X}{dkim} {_dkim}}
+  errors_to =  ""
+
+fail_remote_domains:
+  driver = redirect
+  domains = ! +local_domains
+  data = :fail: unrouteable mail domain "$domain"
+
+localuser:
+  driver = accept
+  check_local_user
+  transport = local_delivery
+  headers_add = X-local-user: uid=$local_user_uid gid=$local_user_gid
+
+
+# ----- Transports -----
+
+begin transports
+
+local_delivery:
+  driver = appendfile
+  delivery_date_add
+  envelope_to_add
+  file = DIR/test-mail/$local_part
+  headers_add = "X-body-linecount: $body_linecount\n\
+                 X-message-linecount: $message_linecount\n\
+                 X-received-count: $received_count"
+  return_path_add
+
+remote_smtp:
+  driver = smtp
+  hosts =      127.0.0.1
+  port =       PORT_S
+  allow_localhost
+  command_timeout = 2s
+  final_timeout = 2s
+
+remote_smtp_dkim:
+  driver = smtp
+  hosts =      127.0.0.1
+  port =       PORT_S
+  allow_localhost
+  command_timeout = 2s
+  final_timeout = 2s
+
+  dkim_domain =                test.ex
+  dkim_selector =      sel
+  dkim_private_key =   DIR/aux-fixed/dkim/dkim.private
+.ifndef HEADERS_MAXSIZE
+  dkim_sign_headers =  OPT
+.endif
+
+# ----- Retry -----
+
+begin retry
+* * F,30m,5m;
+# End
diff --git a/test/confs/0901 b/test/confs/0901
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/0902 b/test/confs/0902
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/2090 b/test/confs/2090
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/2091 b/test/confs/2091
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/2190 b/test/confs/2190
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/2191 b/test/confs/2191
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
index e151e5f..64c3cf4 100644 (file)
@@ -11,6 +11,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
 tls_advertise_hosts =
 
 # ----- Main settings -----
diff --git a/test/confs/4509 b/test/confs/4509
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/5590 b/test/confs/5590
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
diff --git a/test/confs/5591 b/test/confs/5591
new file mode 120000 (symlink)
index 0000000..1bb9871
--- /dev/null
@@ -0,0 +1 @@
+0900
\ No newline at end of file
index 185b067..788f509 100644 (file)
@@ -10,6 +10,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/SERVER%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
 primary_hostname = server1.example.com
 
 
index 6c46144..2f0fc25 100644 (file)
@@ -10,6 +10,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/SERVER%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
 primary_hostname = server1.example.com
 
 
diff --git a/test/log/0900 b/test/log/0900
new file mode 100644 (file)
index 0000000..63072b9
--- /dev/null
@@ -0,0 +1,10 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= someone@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@the.local.host.name
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= someone@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@the.local.host.name
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= someone@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@the.local.host.name
+1999-03-02 09:44:33 10HmbA-0005vi-00 SMTP data timeout (message abandoned) on connection from (tester) [127.0.0.1] F=<someone@some.domain>
+1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data
+1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= someone@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@the.local.host.name
diff --git a/test/log/0901 b/test/log/0901
new file mode 100644 (file)
index 0000000..0239bac
--- /dev/null
@@ -0,0 +1,38 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for a@test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for b@test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 == b@test.ex R=to_server T=remote_smtp defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after end of data (ddd bytes written)
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for c@test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => c@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for d@test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 ** d@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after end of data: 500 oops
+1999-03-02 09:44:33 10HmbA-0005vi-00 d@test.ex: error ignored
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for e@test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 == e@test.ex R=to_server T=remote_smtp defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after end of data: 400 not right now
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for p@test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 => p@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for q@test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 == q@test.ex R=to_server T=remote_smtp defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined end of data (ddd bytes written)
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for r@test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 => r@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for s@test.ex
+1999-03-02 09:44:33 10HmbF-0005vi-00 ** s@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 550 unacceptable mail-from
+1999-03-02 09:44:33 10HmbF-0005vi-00 s@test.ex: error ignored
+1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for s1@test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 == s1@test.ex R=to_server T=remote_smtp defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 450 greylisted mail-from
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for t@test.ex
+1999-03-02 09:44:33 10HmbH-0005vi-00 ** t@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<t@test.ex>: 550 no such recipient
+1999-03-02 09:44:33 10HmbH-0005vi-00 t@test.ex: error ignored
+1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for u@test.ex
+1999-03-02 09:44:33 10HmbI-0005vi-00 ** u@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 500 oops bdat
+1999-03-02 09:44:33 10HmbI-0005vi-00 u@test.ex: error ignored
+1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for v@test.ex
+1999-03-02 09:44:33 10HmbJ-0005vi-00 == v@test.ex R=to_server T=remote_smtp defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 400 not right now bdat
diff --git a/test/log/0902 b/test/log/0902
new file mode 100644 (file)
index 0000000..63e1801
--- /dev/null
@@ -0,0 +1,31 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for a@test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for d@test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 ** d@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after sending data block: 500 oops bdat-nonlast
+1999-03-02 09:44:33 10HmaY-0005vi-00 d@test.ex: error ignored
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for p@test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => p@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for s@test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 ** s@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined sending data block: 550 unacceptable mail-from
+1999-03-02 09:44:33 10HmbA-0005vi-00 s@test.ex: error ignored
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for t@test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** t@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<t@test.ex>: 550 no such recipient
+1999-03-02 09:44:33 10HmbB-0005vi-00 t@test.ex: error ignored
+1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for t1@test.ex t2@test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** t1@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<t1@test.ex>: 550 no such recipient
+1999-03-02 09:44:33 10HmbC-0005vi-00 => t2@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmbC-0005vi-00 t1@test.ex: error ignored
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for u@test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 ** u@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined sending data block: 500 oops nonlast bdat
+1999-03-02 09:44:33 10HmbD-0005vi-00 u@test.ex: error ignored
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for v@test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 ** v@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after end of data: 500 oops bdat
+1999-03-02 09:44:33 10HmbE-0005vi-00 v@test.ex: error ignored
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
index 90506c3..08255f8 100644 (file)
@@ -1,6 +1,6 @@
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<CALLER@myhost.test.ex> temporarily rejected RCPT <usery@myhost.test.ex>
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaY-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaY-0005vi-00@myhost.test.ex
 1999-03-02 09:44:33 10HmaX-0005vi-00 no immediate delivery: queued by ACL
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no S=sss id=E10HmaY-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no S=sss id=E10HmaY-0005vi-00@myhost.test.ex
 1999-03-02 09:44:33 10HmaZ-0005vi-00 no immediate delivery: queued by ACL
diff --git a/test/log/2090 b/test/log/2090
new file mode 100644 (file)
index 0000000..630d2c6
--- /dev/null
@@ -0,0 +1,5 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= someone@some.domain H=(rhu.barb) [127.0.0.1] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no K S=sss for CALLER@the.local.host.name
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= someone@some.domain H=(rhu.barb) [127.0.0.1] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no K S=sss for CALLER@the.local.host.name
diff --git a/test/log/2091 b/test/log/2091
new file mode 100644 (file)
index 0000000..62238f8
--- /dev/null
@@ -0,0 +1,7 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for CALLER@test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no K C="250- 340 byte chunk, total 340\\n250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1224
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (the.local.host.name) [127.0.0.1] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no K S=sss id=E10HmaX-0005vi-00@the.local.host.name for CALLER@test.ex
diff --git a/test/log/2190 b/test/log/2190
new file mode 100644 (file)
index 0000000..356a4ad
--- /dev/null
@@ -0,0 +1,5 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= someone@some.domain H=(rhu.barb) [127.0.0.1] P=esmtps X=TLSv1:AES256-SHA:256 CV=no K S=sss for CALLER@the.local.host.name
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= someone@some.domain H=(rhu.barb) [127.0.0.1] P=esmtps X=TLSv1:AES256-SHA:256 CV=no K S=sss for CALLER@the.local.host.name
diff --git a/test/log/2191 b/test/log/2191
new file mode 100644 (file)
index 0000000..38418fb
--- /dev/null
@@ -0,0 +1,9 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for CALLER@test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 [127.0.0.1] SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock
+1999-03-02 09:44:33 10HmaX-0005vi-00 [127.0.0.1] SSL verify error: certificate name mismatch: "/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock"
+1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] X=TLSv1:AES256-SHA:256 CV=no K C="250- 340 byte chunk, total 340\\n250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1224
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (the.local.host.name) [127.0.0.1] P=esmtps X=TLSv1:AES256-SHA:256 CV=no K S=sss id=E10HmaX-0005vi-00@the.local.host.name for CALLER@test.ex
diff --git a/test/log/4509 b/test/log/4509
new file mode 100644 (file)
index 0000000..e2d3bc7
--- /dev/null
@@ -0,0 +1,13 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for a@test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=to_server T=remote_smtp_dkim H=127.0.0.1 [127.0.0.1] K C="250- 973 byte chunk, total 973\\n250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for b@test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => b@test.ex R=to_server T=remote_smtp_dkim H=127.0.0.1 [127.0.0.1] K C="250- 8509 byte chunk, total 9160\\n250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1224
+1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (the.local.host.name) [127.0.0.1] P=esmtp K S=sss id=E10HmaX-0005vi-00@the.local.host.name for a@test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (the.local.host.name) [127.0.0.1] P=esmtp K S=sss id=E10HmaZ-0005vi-00@the.local.host.name for b@test.ex
diff --git a/test/log/5590 b/test/log/5590
new file mode 100644 (file)
index 0000000..1959dac
--- /dev/null
@@ -0,0 +1,7 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 PRDR R=<bad1@test.ex> refusal
+1999-03-02 09:44:33 10HmaX-0005vi-00 PRDR R=<good@test.ex> acceptance
+1999-03-02 09:44:33 10HmaX-0005vi-00 PRDR R=<bad2@test.ex> refusal
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= someone@some.domain H=(tester) [127.0.0.1] P=esmtp PRDR K S=sss for bad1@test.ex good@test.ex bad2@test.ex
diff --git a/test/log/5591 b/test/log/5591
new file mode 100644 (file)
index 0000000..b216ad9
--- /dev/null
@@ -0,0 +1,4 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= sender_gets_replaced@the.local.host.name U=CALLER P=local S=sss for usery userz
+1999-03-02 09:44:33 10HmaX-0005vi-00 => usery@the.local.host.name R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] PRDR K C="250 first rcpt was good"
+1999-03-02 09:44:33 10HmaX-0005vi-00 -> userz@the.local.host.name R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] PRDR K C="250 second rcpt was good"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
diff --git a/test/scripts/0000-Basic/0900 b/test/scripts/0000-Basic/0900
new file mode 100644 (file)
index 0000000..435906d
--- /dev/null
@@ -0,0 +1,195 @@
+# CHUNKING reception
+exim -DSERVER=server -bd -oX PORT_D
+****
+#
+# plain, small message (no body)
+client 127.0.0.1 PORT_D
+??? 220
+ehlo tester
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250 HELP
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 88 last
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250-
+??? 250
+quit
+??? 221
+****
+#
+# plain, small message (with body)
+# nonlast 1st bdat, noop, last-bdat(0)
+# immediate followon 2nd message
+client 127.0.0.1 PORT_D
+??? 220
+ehlo tester
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250 
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 100
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyfull test message
+
+1234567890
+??? 250
+noop
+??? 250
+bdat 0 last
+??? 250-
+??? 250
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 10
+To: Susan@bdat 78 last
+??? 250
+random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250-
+??? 250
+quit
+??? 221
+****
+#
+# not enough data in chunk
+#
+client 127.0.0.1 PORT_D
+??? 220
+ehlo tester
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250 
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 89 last
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 421
+****
+#
+# protocol failure cases
+#
+client 127.0.0.1 PORT_D
+??? 220
+ehlo tester
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250 
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 88
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250
+bdat 0
+??? 504
+quit
+??? 221
+****
+#
+# followon EHLO and another message
+client 127.0.0.1 PORT_D
+??? 220
+ehlo tester
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250 
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 88
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250
+data
+??? 503
+RSET
+??? 250
+EHLO tester
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250 
+mail from:someone@some.domain
+??? 250
+rcpt to:CALLER@HOSTNAME
+??? 250
+bdat 88
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250
+data
+??? 503
+data
+??? 503
+quit
+??? 221
+****
+#
+# plain, small message (no body)
+# pipelined
+client 127.0.0.1 PORT_D
+??? 220
+EHLO tester
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250 HELP
+MAIL FROM:<someone@some.domain>\r\nRCPT TO:<CALLER@HOSTNAME>\r\nBDAT 88 LAST\r\nTo: Susan@random.com\r\nFrom: Sam@random.com\r\nSubject: This is a bodyless test message\r\n
+??? 250
+??? 250
+??? 250-
+??? 250
+quit
+??? 221
+****
+#
+killdaemon
+no_msglog_check
diff --git a/test/scripts/0000-Basic/0901 b/test/scripts/0000-Basic/0901
new file mode 100644 (file)
index 0000000..7b0172a
--- /dev/null
@@ -0,0 +1,309 @@
+# CHUNKING transmission, short messages
+#
+# Start with non-pipelined cases
+#
+# Basic short message
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+BDAT 323 LAST
+*data 323
+250 OK
+QUIT
+225 OK
+*eof
+****
+exim -odf a@test.ex
+Subject: foo
+
+data
+****
+#
+# Error case: server wrongly expected more data, client gets timeout for data-ack
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 good mail cmd
+RCPT TO
+250 acceptable rcpt cmd
+BDAT 323 LAST
+*data 324
+250 OK got that data
+QUIT
+225 OK quitting
+****
+exim -odf b@test.ex
+Subject: foo
+
+data
+****
+#
+# Error case: server wrongly expected less data
+# client get the data-ack, sends quit - but server
+# sees a munged quit due to the outstanding data tail
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+BDAT 323 LAST
+*data 322
+250 OK
+QUIT
+225 OK
+****
+exim -odf c@test.ex
+Subject: foo
+
+data
+****
+#
+# server rejects BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+BDAT 323 LAST
+*data 323
+500 oops
+QUIT
+225 OK
+****
+exim -odf d@test.ex
+Subject: foo
+
+data
+****
+#
+# server tmp-rejects BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+BDAT 323 LAST
+*data 323
+400 not right now
+QUIT
+225 OK
+****
+exim -odf e@test.ex
+Subject: foo
+
+data
+****
+#
+#
+###################################################
+#
+# Pipelined cases
+#
+# Basic short message
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 323
+250 OK mail
+250 OK rcpt
+250 OK bdat
+QUIT
+225 OK
+*eof
+****
+exim -odf p@test.ex
+Subject: foo
+
+data
+****
+#
+# Error case: server wrongly expected more data, client gets timeout for data-ack
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 324
+250 good mail cmd
+****
+exim -odf q@test.ex
+Subject: foo
+
+data
+****
+#
+# Error case: server wrongly expected less data
+# client get the data-ack, sends quit - but server
+# sees a munged quit due to the outstanding data tail
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 322
+250 OK mail
+250 OK rcpt
+250 OK bdat
+QUIT
+225 OK
+****
+exim -odf r@test.ex
+Subject: foo
+
+data
+****
+#
+# server rejects MAIL cmd
+# transport coding does not handle the possible RSET-and-another transaction,
+# but always QUITs
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 323
+550 unacceptable mail-from
+550 rcpt ungood lacking mail-from
+500 bdat ungood lacking mail-from
+QUIT
+225 OK
+****
+exim -odf s@test.ex
+Subject: foo
+
+data
+****
+#
+# server tmp-rejects MAIL cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 324 LAST
+*data 324
+450 greylisted mail-from
+550 rcpt ungood lacking mail-from
+500 bdat ungood lacking mail-from
+QUIT
+225 OK
+****
+exim -odf s1@test.ex
+Subject: foo
+
+data
+****
+#
+# server rejects RCPT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 323
+250 OK mail
+550 no such recipient
+500 oops bdat
+QUIT
+225 OK
+****
+exim -odf t@test.ex
+Subject: foo
+
+data
+****
+#
+# server rejects BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 323
+250 OK mail
+250 OK rcpt
+500 oops bdat
+QUIT
+225 OK
+****
+exim -odf u@test.ex
+Subject: foo
+
+data
+****
+#
+# server tmp-rejects BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 323 LAST
+*data 323
+250 OK mail
+250 OK rcpt
+400 not right now bdat
+QUIT
+225 OK
+****
+exim -odf v@test.ex
+Subject: foo
+
+data
+****
+#
+#
+no_msglog_check
diff --git a/test/scripts/0000-Basic/0902 b/test/scripts/0000-Basic/0902
new file mode 100644 (file)
index 0000000..a1c4de4
--- /dev/null
@@ -0,0 +1,925 @@
+# CHUNKING transmission, long messages
+#
+# Start with non-pipelined cases
+#
+# Basic long message
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+BDAT 317
+*data 317
+250 OK nonlast bdat
+BDAT 8380 LAST
+*data 8380
+250 OK bdat
+QUIT
+225 OK
+*eof
+****
+exim -odf a@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+#
+# server rejects BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+BDAT 317
+*data 317
+500 oops bdat-nonlast
+QUIT
+225 OK
+****
+exim -odf d@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+#
+###################################################
+#
+# Pipelined cases
+#
+# Basic long message
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 317
+250 OK mail
+250 OK rcpt
+*data 317
+250 OK nonlast bdat
+BDAT 8380 LAST
+*data 8380
+250 OK bdat
+QUIT
+225 OK
+*eof
+****
+exim -odf p@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+# server rejects MAIL cmd
+# transport coding does not handle the possible RSET-and-another transaction,
+# but always QUITs
+#
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 317
+*data 317
+550 unacceptable mail-from
+550 rcpt ungood lacking mail-from
+500 bdat (nonlast) ungood lacking mail-from
+QUIT
+225 OK
+****
+exim -odf s@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+# server rejects RCPT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 317
+*data 317
+250 OK mail
+550 no such recipient
+500 oops nonlast bdat - no rcpt
+QUIT
+225 OK
+****
+exim -odf t@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+# server rejects 1st RCPT cmd of two
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+RCPT TO
+BDAT 301
+*data 301
+250 OK mail
+550 no such recipient
+250 good recipient
+200 OK nonlast bdat
+BDAT 8380 LAST
+*data 8380
+250 OK bdat
+QUIT
+225 OK
+****
+exim -odf t1@test.ex t2@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+# server rejects initial BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 317
+*data 317
+250 OK mail
+250 OK rcpt
+500 oops nonlast bdat
+QUIT
+225 OK
+****
+exim -odf u@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+# server rejects final BDAT cmd
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM
+RCPT TO
+BDAT 317
+*data 317
+250 OK mail
+250 OK rcpt
+250 OK nonlast bdat
+BDAT 8380 LAST
+*data 8380
+500 oops bdat
+QUIT
+225 OK
+****
+exim -odf v@test.ex
+Subject: foo
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+****
+#
+#
+no_msglog_check
diff --git a/test/scripts/2000-GnuTLS/2090 b/test/scripts/2000-GnuTLS/2090
new file mode 100644 (file)
index 0000000..f799016
--- /dev/null
@@ -0,0 +1,78 @@
+# TLS server, CHUNKING reception
+gnutls
+exim -DSERVER=server -DY=tls -bd -oX PORT_D
+****
+#
+# non-piplined
+client-gnutls 127.0.0.1 PORT_D
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250-STARTTLS
+??? 250 HELP
+STARTTLS
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250 HELP
+MAIL FROM:<someone@some.domain>
+??? 250
+RCPT TO:<CALLER@HOSTNAME>
+??? 250
+BDAT 88 LAST
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250-
+??? 250
+QUIT
+??? 221
+****
+#
+# pipelined
+client-gnutls 127.0.0.1 PORT_D
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250-STARTTLS
+??? 250 HELP
+STARTTLS
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250 HELP
+MAIL FROM:<someone@some.domain>
+RCPT TO:<CALLER@HOSTNAME>
+BDAT 88 LAST
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250
+??? 250
+??? 250-
+??? 250
+QUIT
+??? 221
+****
+#
+#
+killdaemon
+no_msglog_check
diff --git a/test/scripts/2000-GnuTLS/2091 b/test/scripts/2000-GnuTLS/2091
new file mode 100644 (file)
index 0000000..aa7b260
--- /dev/null
@@ -0,0 +1,9 @@
+# TLS client, CHUNKING transmission
+gnutls
+exim -DSERVER=server -DY=tls -bd -oX PORT_S
+****
+exim -odf CALLER@test.ex
+Test message. Contains FF: ΓΏ
+****
+killdaemon
+no_msglog_check
diff --git a/test/scripts/2100-OpenSSL/2190 b/test/scripts/2100-OpenSSL/2190
new file mode 100644 (file)
index 0000000..bacca67
--- /dev/null
@@ -0,0 +1,77 @@
+# TLS server, CHUNKING reception
+exim -DSERVER=server -DY=tls -bd -oX PORT_D
+****
+#
+# non-piplined
+client-ssl 127.0.0.1 PORT_D
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250-STARTTLS
+??? 250 HELP
+STARTTLS
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250 HELP
+MAIL FROM:<someone@some.domain>
+??? 250
+RCPT TO:<CALLER@HOSTNAME>
+??? 250
+BDAT 88 LAST
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250-
+??? 250
+QUIT
+??? 221
+****
+#
+# pipelined
+client-ssl 127.0.0.1 PORT_D
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250-STARTTLS
+??? 250 HELP
+STARTTLS
+??? 220
+EHLO rhu.barb
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250 HELP
+MAIL FROM:<someone@some.domain>
+RCPT TO:<CALLER@HOSTNAME>
+BDAT 88 LAST
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyless test message
+
+??? 250
+??? 250
+??? 250-
+??? 250
+QUIT
+??? 221
+****
+#
+#
+killdaemon
+no_msglog_check
diff --git a/test/scripts/2100-OpenSSL/2191 b/test/scripts/2100-OpenSSL/2191
new file mode 120000 (symlink)
index 0000000..825b021
--- /dev/null
@@ -0,0 +1 @@
+../2000-GnuTLS/2091
\ No newline at end of file
diff --git a/test/scripts/4500-Domain-Keys-Identified-Mail/4509 b/test/scripts/4500-Domain-Keys-Identified-Mail/4509
new file mode 100644 (file)
index 0000000..9e47901
--- /dev/null
@@ -0,0 +1,111 @@
+# DKIM signing, with CHUNKING
+#
+exim -bd -DSERVER=server -oX PORT_S
+****
+#
+# single header signed, short message
+exim -DX=dkim -DOPT=From -odf a@test.ex
+From: nobody@example.com
+From: second@example.com
+
+content
+****
+#
+# single header signed, long message
+exim -DX=dkim -DOPT=From -odf b@test.ex
+From: nobody@example.com
+From: second@example.com
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+
+The very last line
+****
+millisleep 500
+killdaemon
+no_msglog_check
diff --git a/test/scripts/5500-PRDR/5590 b/test/scripts/5500-PRDR/5590
new file mode 100644 (file)
index 0000000..a9722ff
--- /dev/null
@@ -0,0 +1,40 @@
+# PRDR and CHUNKING reception
+exim -DALLOW=prdr_enable -DSERVER=server -bd -oX PORT_D
+****
+#
+client 127.0.0.1 PORT_D
+??? 220
+EHLO tester
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-CHUNKING
+??? 250-PRDR
+??? 250 
+MAIL FROM:<someone@some.domain> PRDR
+??? 250
+RCPT TO:<bad1@test.ex>
+??? 250
+RCPT TO:<good@test.ex>
+??? 250
+RCPT TO:<bad2@test.ex>
+??? 250
+BDAT 100 last
+To: Susan@random.com
+From: Sam@random.com
+Subject: This is a bodyfull test message
+
+1234567890
+??? 353
+??? 550
+??? 250
+??? 550
+??? 250
+QUIT
+??? 221
+****
+#
+#
+killdaemon
+no_msglog_check
diff --git a/test/scripts/5500-PRDR/5591 b/test/scripts/5500-PRDR/5591
new file mode 100644 (file)
index 0000000..67b9de2
--- /dev/null
@@ -0,0 +1,32 @@
+# PRDR and CHUNKING transmission
+need_ipv4
+no_msglog_check
+#
+# Two recipients, accepted by full PRDR response sequence
+server PORT_S
+220 Server ready
+EHLO
+250-hiya matey
+250-PRDR
+250-CHUNKING
+250 OK
+MAIL FROM:<> PRDR
+250 OK
+RCPT TO
+250 OK
+RCPT TO
+250 OK
+BDAT 317 LAST
+*data 317
+353 prdr responses coming up
+250 first rcpt was good
+250 second rcpt was good
+250 OK, overall
+QUIT
+250 OK
+****
+exim -odi -f sender_gets_replaced usery userz
+Some message text.
+****
+#
+#
index 4f21723..1abd3f4 100644 (file)
@@ -640,6 +640,38 @@ for (count = 0; count < connection_count; count++)
       sleep(sleepfor);
       }
 
+    /* If the script line starts with "*data " we expect a numeric argument,
+    and we expect to read (and discard) that many data bytes from the input. */
+
+    else if (strncmp(ss, "*data ", 6) == 0)
+      {
+      int dlen = atoi(ss+6);
+      int n;
+
+      alarm(timeout);
+
+      if (!linebuf)
+       while (dlen > 0)
+         {
+         n = dlen < sizeof(buffer) ? dlen : sizeof(buffer);
+         if ((n = read(dup_accept_socket, CS buffer, n)) == 0)
+           {
+           printf("Unxpected EOF read from client\n");
+           s = s->next;
+           goto END_OFF;
+           }
+         dlen -= n;
+         }
+      else
+       while (dlen-- > 0)
+         if (fgetc(in) == EOF)
+           {
+           printf("Unxpected EOF read from client\n");
+           s = s->next;
+           goto END_OFF;
+           }
+      }
+
     /* Otherwise the script line is the start of an input line we are expecting
     from the client, or "*eof" indicating we expect the client to close the
     connection. Read command line or data lines; the latter are indicated
index 9f1632d..8137d87 100644 (file)
@@ -9,6 +9,7 @@
 >>> test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "warn"
 >>> check ratelimit = 0/1h/strict
@@ -47,6 +48,7 @@ LOG: 10HmaX-0005vi-00 H=(test.ex) [V4NET.9.8.7] F=<> rejected after DATA
 >>> test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "warn"
 >>> check ratelimit = 0/1h/strict
@@ -84,6 +86,7 @@ LOG: 10HmaY-0005vi-00 H=(test.ex) [V4NET.9.8.7] F=<> rejected after DATA
 >>> test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "warn"
 >>> check ratelimit = 0/1h/per_conn/strict
@@ -122,6 +125,7 @@ LOG: 10HmaZ-0005vi-00 H=(test.ex) [V4NET.9.8.7] F=<> rejected after DATA
 >>> test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "warn"
 >>> check ratelimit = 0/1h/per_conn/strict
@@ -159,6 +163,7 @@ LOG: 10HmbA-0005vi-00 H=(test.ex) [V4NET.9.8.7] F=<> rejected after DATA
 >>> test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "warn"
 >>> check ratelimit = 0/1h/per_rcpt
@@ -225,6 +230,7 @@ LOG: 10HmbB-0005vi-00 H=(test.ex) [V4NET.9.8.7] F=<> rejected after DATA
 >>> test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt2"
 >>> processing "warn"
 >>> check ratelimit = 1/1m/per_rcpt/noupdate
index 3c65514..55e7193 100644 (file)
@@ -9,6 +9,7 @@
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
index b261277..7c3fb0d 100644 (file)
@@ -9,6 +9,7 @@
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
@@ -56,6 +57,7 @@ LOG: 10HmaX-0005vi-00 <= postmaster@exim.test.ex H=(exim.test.ex) [V4NET.11.12.1
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
index c50f936..dcfc428 100644 (file)
@@ -258,6 +258,7 @@ MUNGED: ::1 will be omitted in what follows
 >>> rhubarb in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "rcpt"
 >>> processing "require"
 >>>   message: helo not verified
index 1fb29be..c46c66a 100644 (file)
@@ -9,6 +9,7 @@
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
index c5a40d7..d9ea2bf 100644 (file)
@@ -9,6 +9,7 @@
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check recipients = postmaster@exim.test.ex
index b578cce..97cbca9 100644 (file)
@@ -172,16 +172,21 @@ LOG: 10HmaZ-0005vi-00 H=[127.0.0.1] F=<userx@test.ex> temporarily rejected after
 >>> foo.bar in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> host in smtp_accept_max_nonmail_hosts? yes (matched "*")
 >>> foo.bar in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> foo.bar in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> foo.bar in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> foo.bar in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
index 5a69cc1..9c30eed 100644 (file)
@@ -9,6 +9,7 @@
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
@@ -56,6 +57,7 @@ LOG: 10HmaX-0005vi-00 <= postmaster@exim.test.ex H=(exim.test.ex) [V4NET.11.12.1
 >>> exim.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
index 4fa5388..7df430b 100644 (file)
@@ -9,6 +9,7 @@
 >>> some.host in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> host in hosts_connection_nolog? no (option unset)
 >>> host in host_lookup? no (option unset)
 >>> host in host_reject_connection? no (option unset)
@@ -20,3 +21,4 @@
 >>> some.host in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
index 9b8717f..dac2ea6 100644 (file)
@@ -9,6 +9,7 @@
 >>> xxxx in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "deny"
 >>>   message: unrouteable address
index cc6b08b..598ed62 100644 (file)
@@ -26,6 +26,7 @@
 >>>   V4NET.0.0.1 OK
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> host in hosts_connection_nolog? no (option unset)
 >>> host in host_lookup? no (option unset)
 >>> host in host_reject_connection? no (option unset)
@@ -69,6 +70,7 @@ sender_rcvhost = [V4NET.2.3.4]
 set_process_info: pppp handling incoming connection from ([V4NET.2.3.4]) [V4NET.2.3.4]
 host in dsn_advertise_hosts? no (option unset)
 host in pipelining_advertise_hosts? yes (matched "*")
+host in chunking_advertise_hosts? no (end of list)
 SMTP>> 250-myhost.test.ex Hello [V4NET.2.3.4] [V4NET.2.3.4]
 250-SIZE 52428800
 250-8BITMIME
@@ -142,6 +144,7 @@ sender_rcvhost = host.name.tld ([V4NET.2.3.4])
 set_process_info: pppp handling incoming connection from host.name.tld [V4NET.2.3.4]
 host in dsn_advertise_hosts? no (option unset)
 host in pipelining_advertise_hosts? yes (matched "*")
+host in chunking_advertise_hosts? no (end of list)
 SMTP>> 250-myhost.test.ex Hello host.name.tld [V4NET.2.3.4]
 250-SIZE 52428800
 250-8BITMIME
index 2eabbaa..5f97d4e 100644 (file)
@@ -37,6 +37,7 @@ sender_rcvhost = [V4NET.0.0.0] (helo=something)
 set_process_info: pppp handling incoming connection from (something) [V4NET.0.0.0]
 host in dsn_advertise_hosts? no (option unset)
 host in pipelining_advertise_hosts? yes (matched "*")
+host in chunking_advertise_hosts? no (end of list)
 SMTP>> 250-mail.test.ex Hello something [V4NET.0.0.0]
 250-SIZE 52428800
 250-8BITMIME
index 63ba003..1906cbd 100644 (file)
@@ -10,6 +10,7 @@
 >>> matched host address
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> host in smtp_accept_max_nonmail_hosts? yes (matched "*")
 >>> [1.2.3.4] in helo_lookup_domains? no (end of list)
 >>> verifying EHLO/HELO argument "[1.2.3.4]"
index 1f4f511..7f2ad50 100644 (file)
@@ -22,6 +22,7 @@ smtp_setup_msg entered
 SMTP<< ehlo x.y
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
 SMTP>> 250-myhost.test.ex Hello CALLER at x.y
 250-SIZE 52428800
 250-8BITMIME
@@ -38,6 +39,7 @@ DSN: orcpt: NULL  flags: 0
 SMTP<< data
 SMTP>> 354 Enter message, ending with "." on a line by itself
 search_tidyup called
+PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>
 >>Headers received:
 From: unqualified
 
index 9825070..864b2ea 100644 (file)
@@ -9,6 +9,7 @@
 >>> a.b.c.d in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "defer"
 >>> check !verify = recipient
index 363c8df..8344d34 100644 (file)
@@ -9,6 +9,7 @@
 >>> csa1.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_mail"
 >>> processing "accept"
 >>>   message: CSA status is $csa_status
@@ -19,6 +20,7 @@
 >>> csa2.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_mail"
 >>> processing "accept"
 >>>   message: CSA status is $csa_status
@@ -37,6 +39,7 @@ LOG: H=(csa2.test.ex) [V4NET.9.8.7] rejected MAIL <>: client SMTP authorization
 >>> csa1.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_mail"
 >>> processing "accept"
 >>>   message: CSA status is $csa_status
@@ -48,6 +51,7 @@ LOG: H=(csa1.test.ex) [V4NET.9.8.8] rejected MAIL <>: client SMTP authorization
 >>> csa2.test.ex in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_mail"
 >>> processing "accept"
 >>>   message: CSA status is $csa_status
index a892e73..c5a8b3e 100644 (file)
@@ -88,6 +88,7 @@ LOG: sender_ident=ident
 >>> end of ACL "connect": ACCEPT
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "mail"
 >>> processing "accept"
 >>> check acl = log
index 7615889..6aea66a 100644 (file)
@@ -59,6 +59,7 @@ LOG: smtp_connection MAIN
 >>> x.y.z in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_rcpt"
 >>> processing "accept"
 LOG: this is a warning at TESTSUITE/aux-fixed/3000.pl line 25.
index 1eba140..d25ef58 100644 (file)
@@ -9,6 +9,7 @@
 >>> remote.host in helo_lookup_domains? no (end of list)
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> test.ex in percent_hack_domains? no (matched "!test.ex")
 >>> using ACL "check_recipient"
 >>> processing "accept"
index 6eda313..541d08d 100644 (file)
@@ -87,6 +87,7 @@ LOG: H=[10.0.0.2] Warning: accepted ETRN #abcd
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in "10.0.0.1"? yes (matched "10.0.0.1")
 >>> host in auth_advertise_hosts? yes (matched "+auth_hosts")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> host in smtp_accept_max_nonmail_hosts? yes (matched "*")
 >>> using ACL "check_vrfy"
 >>> processing "deny"
@@ -290,6 +291,7 @@ LOG: H=(test.host) [10.0.0.1] Warning: accepted ETRN #abcd
 >>> host in "10.0.0.4"? no (end of list)
 >>> host in "10.0.0.3 : 10.0.0.4"? yes (matched "10.0.0.3")
 >>> host in auth_advertise_hosts? yes (matched "+auth_relay_hosts")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "warn"
 >>> check hosts = 10.0.0.5
@@ -385,6 +387,7 @@ LOG: H=(test.host) [10.0.0.3] F=<junk@jink.jonk.test.ex> rejected RCPT <userx@cu
 >>> host in "10.0.0.1"? no (end of list)
 >>> host in "10.0.0.4"? yes (matched "10.0.0.4")
 >>> host in auth_advertise_hosts? no (matched "!+relay_hosts")
+>>> host in chunking_advertise_hosts? no (end of list)
 Exim version x.yz ....
 changed uid/gid: forcing real = effective
   uid=uuuu gid=CALLER_GID pid=pppp
@@ -437,6 +440,7 @@ host in "10.0.0.1"? no (end of list)
 host in "10.0.0.4"? no (end of list)
 host in "10.0.0.3 : 10.0.0.4"? no (end of list)
 host in auth_advertise_hosts? yes (matched "10.0.0.5")
+host in chunking_advertise_hosts? no (end of list)
 SMTP>> 250-myhost.test.ex Hello CALLER at testing.testing [10.0.0.5]
 250-SIZE 52428800
 250-8BITMIME
index 8c6fb8b..3f53a12 100644 (file)
@@ -10,6 +10,7 @@
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in auth_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "check_recipient"
 >>> processing "accept"
 >>> check hosts = :
@@ -55,6 +56,7 @@ LOG: 10HmaX-0005vi-00 <= postmaster@exim.test.ex H=(exim.test.ex) [V4NET.11.12.1
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in auth_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> plain authenticator server_condition:
 >>>   $auth1 = 
 >>>   $auth2 = userx
index 2a6c3d5..36fbdb4 100644 (file)
@@ -17,6 +17,7 @@ LOG: H=[5.6.9.1] F=<x@y> rejected RCPT <x@y>: You must authenticate
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in auth_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> auth1 authenticator server_condition:
 >>>   $auth1 = 
 >>>   $auth2 = userx
@@ -50,6 +51,7 @@ LOG: H=[5.6.10.1] F=<x@y> rejected RCPT <x@y>
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in auth_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> auth1 authenticator server_condition:
 >>>   $auth1 = 
 >>>   $auth2 = userx
@@ -76,6 +78,7 @@ LOG: H=[5.6.10.1] F=<x@y> rejected RCPT <x@y>
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in auth_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> auth2 authenticator server_condition:
 >>>   $auth1 = userx
 >>>   $auth2 = secret
index 61225ae..9f4a5e0 100644 (file)
@@ -12,6 +12,7 @@
 >>> host in "10.0.0.1 : 10.0.0.5"? no (end of list)
 >>> host in "10.0.0.4"? yes (matched "10.0.0.4")
 >>> host in auth_advertise_hosts? no (matched "!+relay_hosts")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> host in hosts_connection_nolog? no (option unset)
 >>> host in host_lookup? no (option unset)
 >>> host in host_reject_connection? no (option unset)
@@ -25,6 +26,7 @@
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in "10.0.0.1 : 10.0.0.5"? yes (matched "10.0.0.1")
 >>> host in auth_advertise_hosts? yes (matched "+auth_hosts")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> +++CRAM-MD5 $auth1="tim" $auth2="" $auth3=""
 >>> CRAM-MD5: user name = tim
 >>>           challenge = <1896.697170952@postoffice.reston.mci.net>
@@ -76,6 +78,7 @@ LOG: 10HmaY-0005vi-00 <= userx@some.domain H=(test.host) [10.0.0.1] P=esmtpa A=c
 >>> host in pipelining_advertise_hosts? yes (matched "*")
 >>> host in "10.0.0.1 : 10.0.0.5"? yes (matched "10.0.0.5")
 >>> host in auth_advertise_hosts? yes (matched "+auth_hosts")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> +++CRAM-MD5 $auth1="tim" $auth2="" $auth3=""
 >>> CRAM-MD5: user name = tim
 >>>           challenge = <1896.697170952@postoffice.reston.mci.net>
index b6f8523..e1ed340 100644 (file)
@@ -269,6 +269,7 @@ host in helo_accept_junk_hosts? no (option unset)
 some.name in helo_lookup_domains? no (end of list)
 host in dsn_advertise_hosts? no (option unset)
 host in pipelining_advertise_hosts? yes (matched "*")
+host in chunking_advertise_hosts? no (end of list)
 processing "accept"
 check verify = recipient
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index b088f32..292f091 100644 (file)
@@ -11,6 +11,7 @@
 LOG: no host name found for IP address 1.2.3.4
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "ar"
 >>> processing "warn"
 >>> check control = cutthrough_delivery
@@ -39,6 +40,7 @@ LOG: 10HmaX-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [1.2.3.4] P=es
 LOG: no host name found for IP address 1.2.3.4
 >>> host in dsn_advertise_hosts? no (option unset)
 >>> host in pipelining_advertise_hosts? yes (matched "*")
+>>> host in chunking_advertise_hosts? no (end of list)
 >>> using ACL "ar"
 >>> processing "warn"
 >>> check control = cutthrough_delivery
index 837941d..fe3ed44 100644 (file)
@@ -9,6 +9,7 @@ considering: $smtp_active_hostname ESMTP Exim $version_number $tod_full
      result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
  in tls_advertise_hosts? yes (matched "*")
 considering: ${if eq {SERVER}{server}{queue}{cutthrough}}
 considering: SERVER}{server}{queue}{cutthrough}}
@@ -266,6 +267,7 @@ considering: $smtp_active_hostname ESMTP Exim $version_number $tod_full
      result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
  in tls_advertise_hosts? yes (matched "*")
 considering: ${if eq {SERVER}{server}{queue}{cutthrough}}
 considering: SERVER}{server}{queue}{cutthrough}}
@@ -492,6 +494,7 @@ considering: $smtp_active_hostname ESMTP Exim $version_number $tod_full
      result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
  in tls_advertise_hosts? yes (matched "*")
 considering: ${if eq {SERVER}{server}{queue}{cutthrough}}
 considering: SERVER}{server}{queue}{cutthrough}}
index a1d4d32..623b998 100644 (file)
@@ -9,6 +9,7 @@ considering: $smtp_active_hostname ESMTP Exim $version_number $tod_full
      result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
  in tls_advertise_hosts? yes (matched "*")
 considering: ${if eq {SERVER}{server}{queue}{cutthrough}}
 considering: SERVER}{server}{queue}{cutthrough}}
@@ -265,6 +266,7 @@ considering: $smtp_active_hostname ESMTP Exim $version_number $tod_full
      result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
  in tls_advertise_hosts? yes (matched "*")
 considering: ${if eq {SERVER}{server}{queue}{cutthrough}}
 considering: SERVER}{server}{queue}{cutthrough}}
@@ -491,6 +493,7 @@ considering: $smtp_active_hostname ESMTP Exim $version_number $tod_full
      result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
  in dsn_advertise_hosts? no (option unset)
  in pipelining_advertise_hosts? yes (matched "*")
+ in chunking_advertise_hosts? no (end of list)
  in tls_advertise_hosts? yes (matched "*")
 considering: ${if eq {SERVER}{server}{queue}{cutthrough}}
 considering: SERVER}{server}{queue}{cutthrough}}
index 7e93199..418ddc4 100644 (file)
@@ -61,31 +61,31 @@ End of script
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\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
 550 Administrative prohibition\r
@@ -100,15 +100,15 @@ End of script
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 214-Commands supported:\r
-214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP\r
+214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP\r
 250 Reset OK\r
 250 OK\r
 554 Too many nonmail commands\r
index d6efce0..12cd05b 100644 (file)
@@ -57,6 +57,7 @@ no_hosts_override
 no_hosts_randomize
 hosts_require_auth = 
 hosts_try_auth = 
+hosts_try_chunking = *
 hosts_try_prdr = *
 interface = ip4.ip4.ip4.ip4
 keepalive
@@ -83,6 +84,7 @@ spool_directory = TESTSUITE/spool
 log_file_path = TESTSUITE/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
 # 1 "TESTSUITE/aux-var/std_conf_prefix"
 # 5 "TESTSUITE/test-config"
 primary_hostname = myhost.test.ex
@@ -121,6 +123,7 @@ spool_directory = TESTSUITE/spool
 log_file_path = TESTSUITE/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
 # 1 "TESTSUITE/aux-var/std_conf_prefix"
 # 5 "TESTSUITE/test-config"
 primary_hostname = myhost.test.ex
diff --git a/test/stdout/0900 b/test/stdout/0900
new file mode 100644 (file)
index 0000000..28f479c
--- /dev/null
@@ -0,0 +1,261 @@
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> ehlo tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250 HELP
+<<< 250 HELP
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 88 last
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250-
+<<< 250- 88 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmaX-0005vi-00
+>>> quit
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> ehlo tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-
+<<< 250-SIZE 52428800
+??? 250-
+<<< 250-8BITMIME
+??? 250-
+<<< 250-PIPELINING
+??? 250-
+<<< 250-CHUNKING
+??? 250 
+<<< 250 HELP
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 100
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyfull test message
+>>> 
+>>> 1234567890
+??? 250
+<<< 250 100 byte chunk received
+>>> noop
+??? 250
+<<< 250 OK
+>>> bdat 0 last
+??? 250-
+<<< 250- 0 byte chunk, total 100
+??? 250
+<<< 250 OK id=10HmaY-0005vi-00
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 10
+>>> To: Susan@bdat 78 last
+??? 250
+<<< 250 10 byte chunk received
+>>> random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250-
+<<< 250- 78 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmaZ-0005vi-00
+>>> quit
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> ehlo tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-
+<<< 250-SIZE 52428800
+??? 250-
+<<< 250-8BITMIME
+??? 250-
+<<< 250-PIPELINING
+??? 250-
+<<< 250-CHUNKING
+??? 250 
+<<< 250 HELP
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 89 last
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 421
+<<< 421 the.local.host.name SMTP incoming data timeout - closing connection.
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> ehlo tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-
+<<< 250-SIZE 52428800
+??? 250-
+<<< 250-8BITMIME
+??? 250-
+<<< 250-PIPELINING
+??? 250-
+<<< 250-CHUNKING
+??? 250 
+<<< 250 HELP
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 88
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250
+<<< 250 88 byte chunk received
+>>> bdat 0
+??? 504
+<<< 504 zero size for BDAT command
+>>> quit
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> ehlo tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-
+<<< 250-SIZE 52428800
+??? 250-
+<<< 250-8BITMIME
+??? 250-
+<<< 250-PIPELINING
+??? 250-
+<<< 250-CHUNKING
+??? 250 
+<<< 250 HELP
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 88
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250
+<<< 250 88 byte chunk received
+>>> data
+??? 503
+<<< 503 only BDAT permissible after non-LAST BDAT
+>>> RSET
+??? 250
+<<< 250 Reset OK
+>>> EHLO tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-
+<<< 250-SIZE 52428800
+??? 250-
+<<< 250-8BITMIME
+??? 250-
+<<< 250-PIPELINING
+??? 250-
+<<< 250-CHUNKING
+??? 250 
+<<< 250 HELP
+>>> mail from:someone@some.domain
+??? 250
+<<< 250 OK
+>>> rcpt to:CALLER@the.local.host.name
+??? 250
+<<< 250 Accepted
+>>> bdat 88
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250
+<<< 250 88 byte chunk received
+>>> data
+??? 503
+<<< 503 only BDAT permissible after non-LAST BDAT
+>>> data
+??? 503
+<<< 503 only RSET accepted now
+>>> quit
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO tester
+??? 250-
+<<< 250-the.local.host.name Hello tester [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<someone@some.domain>\r\nRCPT TO:<CALLER@the.local.host.name>\r\nBDAT 88 LAST\r\nTo: Susan@random.com\r\nFrom: Sam@random.com\r\nSubject: This is a bodyless test message\r\n
+??? 250
+<<< 250 OK
+??? 250
+<<< 250 Accepted
+??? 250-
+<<< 250- 88 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmbB-0005vi-00
+>>> quit
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
diff --git a/test/stdout/0901 b/test/stdout/0901
new file mode 100644 (file)
index 0000000..12ed5ce
--- /dev/null
@@ -0,0 +1,199 @@
+
+******** SERVER ********
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<a@test.ex>
+250 OK
+BDAT 323 LAST
+250 OK
+QUIT
+225 OK
+Expected EOF read from client
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 good mail cmd
+RCPT TO:<b@test.ex>
+250 acceptable rcpt cmd
+BDAT 323 LAST
+Unxpected EOF read from client
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<c@test.ex>
+250 OK
+BDAT 323 LAST
+250 OK
+
+Comparison failed - bailing out
+Expected: QUIT
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<d@test.ex>
+250 OK
+BDAT 323 LAST
+500 oops
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<e@test.ex>
+250 OK
+BDAT 323 LAST
+400 not right now
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<p@test.ex>
+BDAT 323 LAST
+250 OK mail
+250 OK rcpt
+250 OK bdat
+QUIT
+225 OK
+Expected EOF read from client
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<q@test.ex>
+BDAT 323 LAST
+Unxpected EOF read from client
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<r@test.ex>
+BDAT 323 LAST
+250 OK mail
+250 OK rcpt
+250 OK bdat
+
+Comparison failed - bailing out
+Expected: QUIT
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<s@test.ex>
+BDAT 323 LAST
+550 unacceptable mail-from
+550 rcpt ungood lacking mail-from
+500 bdat ungood lacking mail-from
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<s1@test.ex>
+BDAT 324 LAST
+450 greylisted mail-from
+550 rcpt ungood lacking mail-from
+500 bdat ungood lacking mail-from
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<t@test.ex>
+BDAT 323 LAST
+250 OK mail
+550 no such recipient
+500 oops bdat
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<u@test.ex>
+BDAT 323 LAST
+250 OK mail
+250 OK rcpt
+500 oops bdat
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<v@test.ex>
+BDAT 323 LAST
+250 OK mail
+250 OK rcpt
+400 not right now bdat
+QUIT
+225 OK
+End of script
diff --git a/test/stdout/0902 b/test/stdout/0902
new file mode 100644 (file)
index 0000000..58dba67
--- /dev/null
@@ -0,0 +1,140 @@
+
+******** SERVER ********
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<a@test.ex>
+250 OK
+BDAT 317
+250 OK nonlast bdat
+BDAT 8380 LAST
+250 OK bdat
+QUIT
+225 OK
+Expected EOF read from client
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<d@test.ex>
+250 OK
+BDAT 317
+500 oops bdat-nonlast
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<p@test.ex>
+BDAT 317
+250 OK mail
+250 OK rcpt
+250 OK nonlast bdat
+BDAT 8380 LAST
+250 OK bdat
+QUIT
+225 OK
+Expected EOF read from client
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<s@test.ex>
+BDAT 317
+550 unacceptable mail-from
+550 rcpt ungood lacking mail-from
+500 bdat (nonlast) ungood lacking mail-from
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<t@test.ex>
+BDAT 317
+250 OK mail
+550 no such recipient
+500 oops nonlast bdat - no rcpt
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<t1@test.ex>
+RCPT TO:<t2@test.ex>
+BDAT 301
+250 OK mail
+550 no such recipient
+250 good recipient
+200 OK nonlast bdat
+BDAT 8380 LAST
+250 OK bdat
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<u@test.ex>
+BDAT 317
+250 OK mail
+250 OK rcpt
+500 oops nonlast bdat
+QUIT
+225 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO the.local.host.name
+250-Hello there
+250-PIPELINING
+250 CHUNKING
+MAIL FROM:<>
+RCPT TO:<v@test.ex>
+BDAT 317
+250 OK mail
+250 OK rcpt
+250 OK nonlast bdat
+BDAT 8380 LAST
+500 oops bdat
+QUIT
+225 OK
+End of script
index c6124c6..3f280e0 100644 (file)
@@ -23,7 +23,7 @@ Succeeded in starting TLS
 ??? 214-
 <<< 214-Commands supported:
 ??? 214
-<<< 214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP
+<<< 214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP
 >>> quit
 ??? 221
 <<< 221 myhost.test.ex closing connection
diff --git a/test/stdout/2090 b/test/stdout/2090
new file mode 100644 (file)
index 0000000..e198f12
--- /dev/null
@@ -0,0 +1,110 @@
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> STARTTLS
+??? 220
+<<< 220 TLS go ahead
+Attempting to start TLS
+Succeeded in starting TLS
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<someone@some.domain>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<CALLER@the.local.host.name>
+??? 250
+<<< 250 Accepted
+>>> BDAT 88 LAST
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250-
+<<< 250- 88 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmaX-0005vi-00
+>>> QUIT
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> STARTTLS
+??? 220
+<<< 220 TLS go ahead
+Attempting to start TLS
+Succeeded in starting TLS
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<someone@some.domain>
+>>> RCPT TO:<CALLER@the.local.host.name>
+>>> BDAT 88 LAST
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250
+<<< 250 OK
+??? 250
+<<< 250 Accepted
+??? 250-
+<<< 250- 88 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmaY-0005vi-00
+>>> QUIT
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
index 7643332..55feb8f 100644 (file)
@@ -37,7 +37,7 @@ Succeeded in starting TLS
 ??? 214-
 <<< 214-Commands supported:
 ??? 214
-<<< 214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP
+<<< 214 AUTH HELO EHLO MAIL RCPT DATA BDAT NOOP QUIT RSET HELP
 >>> quit
 ??? 221
 <<< 221 myhost.test.ex closing connection
diff --git a/test/stdout/2190 b/test/stdout/2190
new file mode 100644 (file)
index 0000000..7942a8c
--- /dev/null
@@ -0,0 +1,138 @@
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> STARTTLS
+??? 220
+<<< 220 TLS go ahead
+Attempting to start TLS
+SSL info: before/connect initialization
+SSL info: before/connect initialization
+SSL info: SSLv3 read server hello A
+SSL info: SSLv3 read server certificate A
+SSL info: SSLv3 read server done A
+SSL info: SSLv3 write client key exchange A
+SSL info: SSLv3 write change cipher spec A
+SSL info: SSLv3 write finished A
+SSL info: SSLv3 flush data
+SSL info: SSLv3 read server session ticket A
+SSL info: SSLv3 read finished A
+SSL info: SSL negotiation finished successfully
+SSL info: SSL negotiation finished successfully
+SSL connection using AES256-SHA
+Succeeded in starting TLS
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<someone@some.domain>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<CALLER@the.local.host.name>
+??? 250
+<<< 250 Accepted
+>>> BDAT 88 LAST
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250-
+<<< 250- 88 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmaX-0005vi-00
+>>> QUIT
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> STARTTLS
+??? 220
+<<< 220 TLS go ahead
+Attempting to start TLS
+SSL info: before/connect initialization
+SSL info: before/connect initialization
+SSL info: SSLv3 read server hello A
+SSL info: SSLv3 read server certificate A
+SSL info: SSLv3 read server done A
+SSL info: SSLv3 write client key exchange A
+SSL info: SSLv3 write change cipher spec A
+SSL info: SSLv3 write finished A
+SSL info: SSLv3 flush data
+SSL info: SSLv3 read server session ticket A
+SSL info: SSLv3 read finished A
+SSL info: SSL negotiation finished successfully
+SSL info: SSL negotiation finished successfully
+SSL connection using AES256-SHA
+Succeeded in starting TLS
+>>> EHLO rhu.barb
+??? 250-
+<<< 250-the.local.host.name Hello rhu.barb [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-CHUNKING
+<<< 250-CHUNKING
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<someone@some.domain>
+>>> RCPT TO:<CALLER@the.local.host.name>
+>>> BDAT 88 LAST
+>>> To: Susan@random.com
+>>> From: Sam@random.com
+>>> Subject: This is a bodyless test message
+>>> 
+??? 250
+<<< 250 OK
+??? 250
+<<< 250 Accepted
+??? 250-
+<<< 250- 88 byte chunk, total 88
+??? 250
+<<< 250 OK id=10HmaY-0005vi-00
+>>> QUIT
+??? 221
+<<< 221 the.local.host.name closing connection
+End of script
diff --git a/test/stdout/5591 b/test/stdout/5591
new file mode 100644 (file)
index 0000000..1a65e06
--- /dev/null
@@ -0,0 +1,24 @@
+
+******** SERVER ********
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Server ready
+EHLO the.local.host.name
+250-hiya matey
+250-PRDR
+250-CHUNKING
+250 OK
+MAIL FROM:<> PRDR
+250 OK
+RCPT TO:<usery@the.local.host.name>
+250 OK
+RCPT TO:<userz@the.local.host.name>
+250 OK
+BDAT 317 LAST
+353 prdr responses coming up
+250 first rcpt was good
+250 second rcpt was good
+250 OK, overall
+QUIT
+250 OK
+End of script