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 5ff976e72d46811fadb2fb1e4cf5af775b413533..d18dd0ce1f2d5e88e1784336915556cd8fb6c3b4 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 587dc65084331b8370a9e7a75e97493a2b33f8b3..719bedf3179f9e937de9e57eabfa86e77b847d98 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 956a33250e8fd58d8c3b2083ee1f315a71c79e66..eae675753c5c7152b08a6cb1b1588b1729621b02 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 e027a23b3213d227d3c12cf4659e0844eb14e31e..f09d438d5e304dd115b6d7490db86a9f135380e3 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 01770df7338354f74b628d96b310e4ec0a234629..14e0b9d67d76a49f2cda24ed9c0a6975b7998ef3 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 2c141636ed410a74ef10f156e6d1b645f9c481c3..8745a399cb2311a9f901f6a256993bfbeb04e75c 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 4f5a922b4a32cca3331b40040025d9e6664e1b84..9e6f9d34782e69ceb6f6d38f45e51bf9f6ca9017 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 6e42bc3d7d56769c5266652053059d0310939fa6..b2bfca64cb45dbfa24d088340ff0d182729df9d9 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 53abeb5c235447cdf313c4786b7df77686d0566d..c62f16e7d27251ced9ff8628a8f1bf6004af7e3d 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 25ff58eb990824651d43ab243af06334952fc6e3..a1591e2a12c135ca0af00533501f35b4927ebc9d 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 32154792e97ffb9cabb2c394d2ed457423ad7425..6a8ce884152a90924766e1ad2cb566f7760376f8 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 53387011c80892eca22472605a58a88096634b35..8994c6edb8d2b242861987c97be2f6c4a54aca20 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 6b4843175359c95b8b9df7f47ff40b58a404a530..76181b5f1c5387ba836d8b84fc213882d4afd9b1 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 6666c52caea34fc321fc11e0867bd17aaa202b23..ffbc899a5dacc46559e70a60573a18d3491d0f3f 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 c7c6b267440a81b88cf67717e4aeafcfc39f07e1..0774850cae8f77947c2e72a02ecbb136f9c6c8fa 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 c24eb45445a484caabede61d5b084dbf1b27f5cb..242394f95ccc72be30c404888ce7106e64d2f1f2 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 8e0a802400c0ae6268cb80793e883ae91522e8e7..a68c22f298bb82df888c5ecbd24f0b104c3d31a4 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 36a68b92cb78492d39bb0d80f3bcc179d37b60fa..f07cd83cf7e63ae63c9f34ae8090d348faa601f8 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 9624ece6af2a656667b999d8aae937497feec140..0cc981064bc5cf75d1ba9a77a0e79b68d1954bab 100644 (file)
@@ -612,8 +612,7 @@ if (send_data)
   transport_ctx tctx = {
     tblock,
     addrlist,
-    US".",
-    US"..",
+    US".", US"..",
     ob->options
   };
 
index e3d01974a8d7c30fa9ff44c045874dc26324abd2..d3841e05021332fcb26a75b2b8d19136bc992dc7 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 bbfef0632a61181905de5113a62e4770aa67ebe7..52b2b913f4fde5eb99e835ceb27c17189145b727 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 804b9942fd30370c840950ccab7a29a90762039a..d3666ae78850cc7df1d8db85dc6ae7a70be0b621 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 c04b288dc652d3c78c9da1dc906f45812fb9dc8b..d890f5fc60a96d54a4c1c948aec6c06754d75f2e 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 3beafd9dbd57ba71fb7b94ee5e90d96be81c0905..39dddd98f7129da3a4598cfd6120d84b6b781671 100644 (file)
@@ -11,3 +11,4 @@ log_file_path = DIR/spool/log/%slog
 
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+chunking_advertise_hosts =
index e464f963ce239ad446a4bc8367bd8bc0c6b99082..6a23896efb2504b69f90c8cb0332d55bd0dbd7d1 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 e8b4c51d40be0cfec5bf7a99275e7df7d1b3696e..4f6f490d39438e876a9bd5fc8c23b78f368646d5 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 e151e5fbcc28bbfa8ec1bf9ed2ae697ba09b95a3..64c3cf48a66771f9034ce400f5f7749b645a4dac 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 185b06745316b4a07f5cd3db5cd1dc52966b78c9..788f509a95539a4d8dba105e71088ae1f8dec541 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 6c4614499980212fb52952bd1a442a7eaca57bf5..2f0fc25c50d9c0ff38de889bc757d04a0343ce1e 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 90506c3cd3cc21fc13e12ff9d69eb65c74af814e..08255f8a12f05d0ee8da0ccc9ea203c1cd20e224 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bca921eaf62aa7903bee35af2e9dfe495d1f3e38 100644 (file)
@@ -0,0 +1 @@
+support PRDR
index 4f217237631d651ec2163dbdf43e54c3e1457cc7..1abd3f49a6cd0e204d3499fae5e798e1b2606d5a 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 9f1632db51524fc9ea370791c456b43f198d2e09..8137d877729917192db5473a69bb237778eb7dfc 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 3c6551479c7e341a7fe2d0b8f167e83aa21827c1..55e71933218cf017e414cbce43d2531e2caf3f01 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 b261277c6526a19f83e04af45f72d20bf283067f..7c3fb0d3f88e76fba32642e6f531ea8e46cd6868 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 c50f93612c83c21a79b2a6dd170ca21521baa9fd..dcfc4286c60ca420f1813cf3c703e01119fc736c 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 1fb29be98b45e966b852d8027aee57ff73e8cfb4..c46c66aa198a4de92f49b2d50413395a102fa055 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 c5a40d7ba5481592914edc0ef1c8c01c2f101a95..d9ea2bf81f21b05f40f2331d5c2e1757fa7fa626 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 b578cce97989f375f33198c91a958a03acb7e211..97cbca9dae1a711a9802e9e89a265cbfe0de2475 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 5a69cc1cca7e04d8fdb5e0a87d4363ede4c0d3be..9c30eedecc03d58ce0b7fc746f7bda4a6615c6cf 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 4fa53882e115aface41d86779e1ecc5684ceff69..7df430b70af080e69e40a9681ad49cb9bd9ccf1f 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 9b8717fde48822d2e0054d950ee168729d4fac13..dac2ea6e76f44cb3519c0455d6e07a18c2d0c8c8 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 cc6b08b27d5a55323ac692b50d295edf54be8239..598ed62ed2bf545ab11c3603b10335f3ebf7288c 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 2eabbaa6f1bc609b165f00634d38d6741f69489f..5f97d4e09eb97099acc672f020d668aecf181e85 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 63ba003cd490a660595f39559a214da04cdc5ec3..1906cbd2d21079bbb2b72f71ef227f3cc8bd651d 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 1f4f5116e4f915c643bb5e3d9d0877afc7b7b5e6..7f2ad50638f388b23994e99baedb369ca5014279 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 9825070c49e0b11e06106689df879a6449192ba4..864b2eaa102ffdf6e0fc20a7c1289ef4cd2bee27 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 363c8dfd119d0f442a13ad9427f85ef7e5951b6e..8344d34a6e1678f55fd66fa64521894d915170b4 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 a892e736d6a8a8c3874919d9212bad7644296610..c5a8b3e54de067cdf84adf9921885fd4224f11ba 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 7615889c882d59f93c81d91d24a3b370cba1bd4f..6aea66ac5bd66c8eb55a8e02407f739296f7abbf 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 1eba140494987b7b5321649d174ad42d600aa5a9..d25ef58ad60ccd29e20afa557983e15a6d547d40 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 6eda31374d146d0e1861700ff5608a5ce672f4b0..541d08d5a4f1e5049007cca2b1ec73da3e3ddccb 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 8c6fb8b25825e72dd54a9b03b6c420fb1e5f9676..3f53a120af786e1b61471715046f0368ef662621 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 2a6c3d5aaa0b854291119de7601cb3ae0d49819a..36fbdb42561d59ade878d73dff918f42d049aa6c 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 61225ae7dbf5d2f8bb5615863c4ce161fe291487..9f4a5e0877b3d8faea434701034ac07dd99b23c1 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 b6f85233822bc56a92bdf98ff48660a076606f34..e1ed340c0e10d46fd67bb320755be521dfe71a5f 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 b088f32f103fa99db592f0e523af7958a1024dcd..292f09133e712763968197a0bac1792825342704 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 837941d171f1a35ad8e13a20dd6cceae2c36f0cf..fe3ed4429cf82a23c0705138df9d0957d8f45f10 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 a1d4d32678a8e8e57b599d8a53531164a2b2d449..623b99864b1596737db5be3aad6204098beb1665 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 7e931992ca51aacded06b0700207a90a7b777622..418ddc4bac84f504ce3769dd0a11e52ca13beaa6 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 d6efce012e62d1b90677a0269248a57846fa2482..12cd05b78b734b92e11a1c1940ea65cb3d3b188e 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 c6124c698ffb4024915bd83b29c19a3cbce2fd66..3f280e0d54295a2f6577294dab7a8495262d24db 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 76433323a50f0a6c9256cbd8a37b26b70ddd1783..55feb8f4192acc0d703bac10f81e9292cc9df191 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