From: Jeremy Harris Date: Sun, 4 Sep 2016 13:54:18 +0000 (+0100) Subject: Cutthrough: option to reflect 4xx errors from target to initiator X-Git-Tag: exim-4_88_RC1~14 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/ff5929e3b91747e2ecb600711d17a7d0e21749ad Cutthrough: option to reflect 4xx errors from target to initiator --- diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 622e5272d..4ebeaa0c6 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -13003,8 +13003,7 @@ or external command, as described above. It is also used during a .vitem &$verify_mode$& .vindex "&$verify_mode$&" -While a router or transport is being run in verify mode -or for cutthrough delivery, +While a router or transport is being run in verify mode or for cutthrough delivery, contains "S" for sender-verification or "R" for recipient-verification. Otherwise, empty. @@ -28802,7 +28801,7 @@ Notice that we put back the lower cased version afterwards, assuming that is what is wanted for subsequent tests. -.vitem &*control&~=&~cutthrough_delivery*& +.vitem &*control&~=&~cutthrough_delivery/*&<&'options'&> .cindex "&ACL;" "cutthrough routing" .cindex "cutthrough" "requesting" This option requests delivery be attempted while the item is being received. @@ -28842,11 +28841,20 @@ It is not supported for messages received with the SMTP PRDR option in use. Should the ultimate destination system positively accept or reject the mail, a corresponding indication is given to the source system and nothing is queued. -If there is a temporary error the item is queued for later delivery in the -usual fashion. If the item is successfully delivered in cutthrough mode +If the item is successfully delivered in cutthrough mode the delivery log lines are tagged with ">>" rather than "=>" and appear before the acceptance "<=" line. +.new +If there is a temporary error the item is queued for later delivery in the +usual fashion. +This behaviour can be adjusted by appending the option &*defer=*&<&'value'&> +to the control; the default value is &"spool"& and the alternate value +&"pass"& copies an SMTP defer response from the target back to the initiator +and does not queue the message. +Note that this is independent of any receipient verify conditions in the ACL. +.wen + Delivery in this mode avoids the generation of a bounce mail to a (possibly faked) sender when the destination system is doing content-scan based rejection. diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 20af1a28f..33b726536 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -43,6 +43,10 @@ Version 4.88 11. Integer values for options can take a "G" multiplier. +12. defer=pass option for the ACL control cutthrough_delivery, to reflect 4xx + returns from the target back to the initiator, rather than spooling the + message. + Version 4.87 ------------ diff --git a/src/src/acl.c b/src/src/acl.c index 492e9bf17..eff698b34 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -744,7 +744,7 @@ static control_def controls_list[] = { { US"fakereject", CONTROL_FAKEREJECT, TRUE }, { US"submission", CONTROL_SUBMISSION, TRUE }, { US"suppress_local_fixups", CONTROL_SUPPRESS_LOCAL_FIXUPS, FALSE }, - { US"cutthrough_delivery", CONTROL_CUTTHROUGH_DELIVERY, FALSE }, + { US"cutthrough_delivery", CONTROL_CUTTHROUGH_DELIVERY, TRUE }, #ifdef SUPPORT_I18N { US"utf8_downconvert", CONTROL_UTF8_DOWNCONVERT, TRUE } #endif @@ -3398,7 +3398,23 @@ for (; cb != NULL; cb = cb->next) *log_msgptr = US"fakereject"; else { - if (rcpt_count == 1) cutthrough.delivery = TRUE; + if (rcpt_count == 1) + { + cutthrough.delivery = TRUE; + while (*p == '/') + { + const uschar * pp = p+1; + if (Ustrncmp(pp, "defer=", 6) == 0) + { + pp += 6; + if (Ustrncmp(pp, "pass", 4) == 0) cutthrough.defer_pass = TRUE; + /* else if (Ustrncmp(pp, "spool") == 0) ; default */ + } + else + while (*pp && *pp != '/') pp++; + p = pp; + } + } break; } *log_msgptr = string_sprintf("\"control=%s\" on %s item", @@ -4502,32 +4518,50 @@ If temp-reject, close the conn (and keep the spooled copy). If conn-failure, no action (and keep the spooled copy). */ switch (where) -{ -case ACL_WHERE_RCPT: + { + case ACL_WHERE_RCPT: #ifndef DISABLE_PRDR -case ACL_WHERE_PRDR: + case ACL_WHERE_PRDR: #endif - if (host_checking_callout) /* -bhc mode */ - cancel_cutthrough_connection("host-checking mode"); - else if (rc == OK && cutthrough.delivery && rcpt_count > cutthrough.nrcpt) - rc = open_cutthrough_connection(addr); - break; + if (host_checking_callout) /* -bhc mode */ + cancel_cutthrough_connection("host-checking mode"); + + else if ( rc == OK + && cutthrough.delivery + && rcpt_count > cutthrough.nrcpt + && (rc = open_cutthrough_connection(addr)) == DEFER + ) + if (cutthrough.defer_pass) + { + uschar * s = addr->message; + /* Horrid kludge to recover target's SMTP message */ + while (*s) s++; + do --s; while (!isdigit(*s)); + if (*--s && isdigit(*s) && *--s && isdigit(*s)) *user_msgptr = s; + acl_temp_details = TRUE; + } + else + { + HDEBUG(D_acl) debug_printf("cutthrough defer; will spool\n"); + rc = OK; + } + break; -case ACL_WHERE_PREDATA: - if (rc == OK) - cutthrough_predata(); - else - cancel_cutthrough_connection("predata acl not ok"); - break; + case ACL_WHERE_PREDATA: + if (rc == OK) + cutthrough_predata(); + else + cancel_cutthrough_connection("predata acl not ok"); + break; -case ACL_WHERE_QUIT: -case ACL_WHERE_NOTQUIT: - cancel_cutthrough_connection("quit or notquit"); - break; + case ACL_WHERE_QUIT: + case ACL_WHERE_NOTQUIT: + cancel_cutthrough_connection("quit or notquit"); + break; -default: - break; -} + default: + break; + } deliver_domain = deliver_localpart = deliver_address_data = sender_address_data = NULL; diff --git a/src/src/globals.c b/src/src/globals.c index 9e6f9d347..8d2010273 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -532,6 +532,7 @@ uschar *continue_transport = NULL; uschar *csa_status = NULL; cut_t cutthrough = { FALSE, /* delivery: when to attempt */ + FALSE, /* on defer: spool locally */ -1, /* fd: open connection */ 0, /* nrcpt: number of addresses */ }; diff --git a/src/src/globals.h b/src/src/globals.h index b2bfca64c..0faf713bf 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -301,7 +301,8 @@ extern uschar *continue_transport; /* Transport for continued delivery */ extern uschar *csa_status; /* Client SMTP Authorization result */ typedef struct { - BOOL delivery; /* When to attempt */ + unsigned delivery:1; /* When to attempt */ + unsigned defer_pass:1; /* Pass 4xx to caller rather than spoolling */ int fd; /* Open connection */ int nrcpt; /* Count of addresses */ uschar * interface; /* (address of) */ diff --git a/src/src/receive.c b/src/src/receive.c index 4d30419f0..51ce2844e 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -4052,7 +4052,8 @@ for this message. */ Send dot onward. If accepted, wipe the spooled files, log as delivered and accept the sender's dot (below). If rejected: copy response to sender, wipe the spooled files, log approriately. - If temp-reject: accept to sender, keep the spooled files. + If temp-reject: normally accept to sender, keep the spooled file - unless defer=pass + in which case pass temp-reject back to initiator and dump the files. Having the normal spool files lets us do data-filtering, and store/forward on temp-reject. @@ -4068,13 +4069,17 @@ if(cutthrough.fd >= 0) cutthrough_done = ACCEPTED; break; /* message_id needed for SMTP accept below */ + case '4': /* Temp-reject. Keep spoolfiles and accept, unless defer-pass mode. + ... for which, pass back the exact error */ + if (cutthrough.defer_pass) smtp_reply = string_copy_malloc(msg); + /*FALLTRHOUGH*/ + default: /* Unknown response, or error. Treat as temp-reject. */ - case '4': /* Temp-reject. Keep spoolfiles and accept. */ cutthrough_done = TMP_REJ; /* Avoid the usual immediate delivery attempt */ break; /* message_id needed for SMTP accept below */ case '5': /* Perm-reject. Do the same to the source. Dump any spoolfiles */ - smtp_reply= msg; /* Pass on the exact error */ + smtp_reply = string_copy_malloc(msg); /* Pass on the exact error */ cutthrough_done = PERM_REJ; break; } @@ -4188,27 +4193,37 @@ if (smtp_input) /* smtp_reply is set non-empty */ else if (smtp_reply[0] != 0) - { if (fake_response != OK && (smtp_reply[0] == '2')) smtp_respond((fake_response == DEFER)? US"450" : US"550", 3, TRUE, fake_response_text); else smtp_printf("%.1024s\r\n", smtp_reply); - } switch (cutthrough_done) { - case ACCEPTED: log_write(0, LOG_MAIN, "Completed");/* Delivery was done */ + case ACCEPTED: + log_write(0, LOG_MAIN, "Completed");/* Delivery was done */ case PERM_REJ: - { /* Delete spool files */ - Uunlink(spool_fname(US"input", message_subdir, message_id, US"-D")); - Uunlink(spool_fname(US"input", message_subdir, message_id, US"-H")); - Uunlink(spool_fname(US"msglog", message_subdir, message_id, US"")); - } - case TMP_REJ: message_id[0] = 0; /* Prevent a delivery from starting */ - default:break; + /* Delete spool files */ + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-D")); + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-H")); + Uunlink(spool_fname(US"msglog", message_subdir, message_id, US"")); + message_id[0] = 0; /* Prevent a delivery from starting */ + break; + + case TMP_REJ: + if (cutthrough.defer_pass) + { + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-D")); + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-H")); + Uunlink(spool_fname(US"msglog", message_subdir, message_id, US"")); + } + message_id[0] = 0; /* Prevent a delivery from starting */ + default: + break; } cutthrough.delivery = FALSE; + cutthrough.defer_pass = FALSE; } /* For batched SMTP, generate an error message on failure, and do diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 597b88e38..387affaf3 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -2961,8 +2961,9 @@ if (lognl != NULL) *lognl = 0; always a 5xx one - see comments at the start of this function. If the original rc was FAIL_DROP we drop the connection and yield 2. */ -if (rc == FAIL) smtp_respond(smtp_code, codelen, TRUE, (user_msg == NULL)? - US"Administrative prohibition" : user_msg); +if (rc == FAIL) + smtp_respond(smtp_code, codelen, TRUE, + user_msg ? user_msg : US"Administrative prohibition"); /* Send temporary failure response to the command. Don't give any details, unless acl_temp_details is set. This is TRUE for a callout defer, a "defer" @@ -2973,21 +2974,19 @@ interactions between temp_details and return_error_details. One day it should be re-implemented in a tidier fashion. */ else - { - if (acl_temp_details && user_msg != NULL) + if (acl_temp_details && user_msg) { - if (smtp_return_error_details && - sender_verified_failed != NULL && - sender_verified_failed->message != NULL) - { + if ( smtp_return_error_details + && sender_verified_failed + && sender_verified_failed->message + ) smtp_respond(smtp_code, codelen, FALSE, sender_verified_failed->message); - } + smtp_respond(smtp_code, codelen, TRUE, user_msg); } else smtp_respond(smtp_code, codelen, TRUE, US"Temporary local problem - please try later"); - } /* Log the incident to the logs that are specified by log_reject_target (default main, reject). This can be empty to suppress logging of rejections. If diff --git a/src/src/verify.c b/src/src/verify.c index d890f5fc6..865a01d07 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -226,7 +226,7 @@ else if ((dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE)) == NULL) /* If a cache database is available see if we can avoid the need to do an actual callout by making use of previously-obtained data. */ -if (dbm_file != NULL) +if (dbm_file) { dbdata_callout_cache_address *cache_address_record; dbdata_callout_cache *cache_record = get_callout_cache_record(dbm_file, @@ -237,7 +237,7 @@ if (dbm_file != NULL) /* If an unexpired cache record was found for this domain, see if the callout process can be short-circuited. */ - if (cache_record != NULL) + if (cache_record) { /* In most cases, if an early command (up to and including MAIL FROM:<>) was rejected, there is no point carrying on. The callout fails. However, if @@ -297,7 +297,7 @@ if (dbm_file != NULL) but has not been done before, we are going to have to do a callout, so skip remaining cache processing. */ - if (pm_mailfrom != NULL) + if (pm_mailfrom) { if (cache_record->postmaster_result == ccache_reject) { @@ -343,7 +343,7 @@ if (dbm_file != NULL) callout_cache_positive_expire, callout_cache_negative_expire); - if (cache_address_record != NULL) + if (cache_address_record) { if (cache_address_record->result == ccache_accept) { @@ -404,7 +404,7 @@ else and cause the client to time out. So in this case we forgo the PIPELINING optimization. */ - if (smtp_out != NULL && !disable_callout_flush) mac_smtp_fflush(); + if (smtp_out && !disable_callout_flush) mac_smtp_fflush(); /* cutthrough-multi: if a nonfirst rcpt has the same routing as the first, and we are holding a cutthrough conn open, we can just append the rcpt to @@ -516,7 +516,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. /* Now make connections to the hosts and do real callouts. The list of hosts is passed in as an argument. */ - for (host = host_list; host != NULL && !done; host = host->next) + for (host = host_list; host && !done; host = host->next) { smtp_inblock inblock; smtp_outblock outblock; @@ -544,7 +544,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. /* Skip this host if we don't have an IP address for it. */ - if (host->address == NULL) + if (!host->address) { DEBUG(D_verify) debug_printf("no IP address for host name %s: skipping\n", host->name); @@ -561,7 +561,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. /* Set IPv4 or IPv6 */ - host_af = (Ustrchr(host->address, ':') == NULL)? AF_INET:AF_INET6; + host_af = Ustrchr(host->address, ':') == NULL ? AF_INET : AF_INET6; /* Expand and interpret the interface and port strings. The latter will not be used if there is a host-specific port (e.g. from a manualroute router). @@ -659,10 +659,10 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. /* Expand the helo_data string to find the host name to use. */ - if (tf->helo_data != NULL) + if (tf->helo_data) { - uschar *s = expand_string(tf->helo_data); - if (s == NULL) + uschar * s = expand_string(tf->helo_data); + if (!s) log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: failed to expand transport's " "helo_data value for callout: %s", addr->address, expand_string_message); @@ -1299,8 +1299,9 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. { /* Ensure no cutthrough on multiple address verifies */ if (options & vopt_callout_recipsender) - cancel_cutthrough_connection("multiple verify calls"); - if (send_quit) (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n"); + cancel_cutthrough_connection("not usable for cutthrough"); + if (send_quit) + (void) smtp_write_command(&outblock, FALSE, "QUIT\r\n"); #ifdef SUPPORT_TLS tls_close(FALSE, TRUE); @@ -1353,9 +1354,9 @@ if (done) if ( !(options & vopt_callout_no_cache) && new_address_record.result != ccache_unknown) { - if (dbm_file == NULL) + if (!dbm_file) dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE); - if (dbm_file == NULL) + if (!dbm_file) { HDEBUG(D_verify) debug_printf("no callout cache available\n"); } @@ -1376,22 +1377,24 @@ it alone if supplying details. Otherwise, give a generic response. */ else /* !done */ { - uschar *dullmsg = string_sprintf("Could not complete %s verify callout", + uschar * dullmsg = string_sprintf("Could not complete %s verify callout", options & vopt_is_recipient ? "recipient" : "sender"); yield = DEFER; - if (host_list->next != NULL || addr->message == NULL) addr->message = dullmsg; + if (host_list->next || !addr->message) + addr->message = dullmsg; - addr->user_message = (!smtp_return_error_details)? dullmsg : - string_sprintf("%s for <%s>.\n" + addr->user_message = smtp_return_error_details + ? string_sprintf("%s for <%s>.\n" "The mail server(s) for the domain may be temporarily unreachable, or\n" "they may be permanently unreachable from this server. In the latter case,\n%s", dullmsg, addr->address, options & vopt_is_recipient - ? "the address will never be accepted." + ? "the address will never be accepted." : "you need to change the address or create an MX record for its domain\n" "if it is supposed to be generally accessible from the Internet.\n" - "Talk to your mail administrator for details."); + "Talk to your mail administrator for details.") + : dullmsg; /* Force a specific error code */ @@ -1401,7 +1404,7 @@ else /* !done */ /* Come here from within the cache-reading code on fast-track exit. */ END_CALLOUT: -if (dbm_file != NULL) dbfn_close(dbm_file); +if (dbm_file) dbfn_close(dbm_file); return yield; } @@ -1423,10 +1426,12 @@ get rewritten. */ addr2 = *addr; HDEBUG(D_acl) debug_printf("----------- %s cutthrough setup ------------\n", rcpt_count > 1 ? "more" : "start"); -rc= verify_address(&addr2, NULL, +rc = verify_address(&addr2, NULL, vopt_is_recipient | vopt_callout_recipsender | vopt_callout_no_cache, CUTTHROUGH_CMD_TIMEOUT, -1, -1, NULL, NULL, NULL); +addr->message = addr2.message; +addr->user_message = addr2.user_message; HDEBUG(D_acl) debug_printf("----------- end cutthrough setup ------------\n"); return rc; } diff --git a/test/confs/5400 b/test/confs/5400 index f87f985fd..9be13fea6 100644 --- a/test/confs/5400 +++ b/test/confs/5400 @@ -1,10 +1,17 @@ # Exim test configuration 5400 +# any options on the cutthrough_delivery contol +CONTROL= + +# optional verify-callout +OPT= + .include DIR/aux-var/std_conf_prefix primary_hostname = myhost.test.ex log_selector = +received_recipients +queue_only # ----- Main settings ----- @@ -18,7 +25,9 @@ acl_smtp_rcpt = ar begin acl ar: - accept control = cutthrough_delivery + accept + control = cutthrough_deliveryCONTROL + OPT logwrite = rcpt for $local_part@$domain # ----- Routers ----- diff --git a/test/confs/5405 b/test/confs/5405 new file mode 120000 index 000000000..8f6811b7e --- /dev/null +++ b/test/confs/5405 @@ -0,0 +1 @@ +5400 \ No newline at end of file diff --git a/test/log/5405 b/test/log/5405 new file mode 100644 index 000000000..ae3ad767d --- /dev/null +++ b/test/log/5405 @@ -0,0 +1,23 @@ +1999-03-02 09:44:33 rcpt for usera@domain.com +1999-03-02 09:44:33 10HmaX-0005vi-00 >> usera@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK" +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for usera@domain.com +1999-03-02 09:44:33 10HmaX-0005vi-00 Completed +1999-03-02 09:44:33 rcpt for userb@domain.com +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userb@domain.com +1999-03-02 09:44:33 rcpt for userc@domain.com +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userc@domain.com +1999-03-02 09:44:33 rcpt for userd@domain.com +1999-03-02 09:44:33 U=CALLER F= temporarily rejected RCPT +1999-03-02 09:44:33 rcpt for usere@domain.com +1999-03-02 09:44:33 10HmbA-0005vi-00 U=CALLER usere@domain.com F= tmp-reject from cutthrough after DATA: R=all T=smtp H=127.0.0.1 [127.0.0.1] C="459 content reject" +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for usere@domain.com +1999-03-02 09:44:33 rcpt for userf@domain.com +1999-03-02 09:44:33 10HmbB-0005vi-00 U=CALLER userf@domain.com F= tmp-reject from cutthrough after DATA: R=all T=smtp H=127.0.0.1 [127.0.0.1] C="459 content reject" +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userf@domain.com +1999-03-02 09:44:33 rcpt for userg@domain.com +1999-03-02 09:44:33 10HmbC-0005vi-00 U=CALLER userg@domain.com F= tmp-reject from cutthrough after DATA: R=all T=smtp H=127.0.0.1 [127.0.0.1] C="459 content reject" +1999-03-02 09:44:33 rcpt for userh@domain.com +1999-03-02 09:44:33 10HmbD-0005vi-00 >> userh@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK" +1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userh@domain.com +1999-03-02 09:44:33 10HmbD-0005vi-00 Completed +1999-03-02 09:44:33 U=CALLER F= temporarily rejected RCPT : response to "RCPT TO:" from 127.0.0.1 [127.0.0.1] was: 450 not right now diff --git a/test/rejectlog/5405 b/test/rejectlog/5405 new file mode 100644 index 000000000..7df2e1018 --- /dev/null +++ b/test/rejectlog/5405 @@ -0,0 +1,2 @@ +1999-03-02 09:44:33 U=CALLER F= temporarily rejected RCPT +1999-03-02 09:44:33 U=CALLER F= temporarily rejected RCPT : response to "RCPT TO:" from 127.0.0.1 [127.0.0.1] was: 450 not right now diff --git a/test/scripts/5400-cutthrough/5405 b/test/scripts/5400-cutthrough/5405 new file mode 100644 index 000000000..2e7a33388 --- /dev/null +++ b/test/scripts/5400-cutthrough/5405 @@ -0,0 +1,228 @@ +# cutthrough_delivery tmp-rejects +need_ipv4 +munge loopback +# +# basic operation. Should deliver in cutthrough mode. +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 Recipient OK +DATA +354 Send data +. +250 OK +QUIT +250 OK +**** +exim -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +###################################################### +# RCPT-time +# +# temp-reject (at RCPT), default. Should spool msg. +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +**** +exim -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# temp-reject (at RCPT), option "spool". Should spool msg (again). +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +**** +exim -DCONTROL=/defer=spool -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# temp-reject (at RCPT), option "pass". Should tmp-rej source, at RCPT. +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +**** +exim -DCONTROL=/defer=pass -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +QUIT +**** +######################################################### +# DATA-time +# +# +# temp-reject (at DATA-dot), default. Should spool msg. +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 good rcpt +DATA +354 Send data +. +459 content reject +QUIT +250 OK +**** +exim -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# temp-reject (at DATA-dot), option "spool". Should spool msg (again). +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 good rcpt +DATA +354 Send data +. +459 content reject +QUIT +250 OK +**** +exim -DCONTROL=/defer=spool -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# temp-reject (at DATA-dot), option "pass". Should tmp-rej source, at DATA. +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 good rcpt +DATA +354 Send data +. +459 content reject +QUIT +250 OK +**** +exim -DCONTROL=/defer=pass -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +######################################################### +#, Now using a conn opened by a recipient verify +# +# basic operation. Should deliver in cutthrough mode. +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 Recipient OK +DATA +354 Send data +. +250 OK +QUIT +250 OK +**** +exim -DOPT=verify=recipient/callout=use_sender -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# temp-reject (at RCPT), default. Should tmp-rej, due to the r-verify +server PORT_S +220 ESMTP +EHLO +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +**** +exim -DOPT=verify=recipient/callout=use_sender -bs +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +no_msglog_check diff --git a/test/stdout/5405 b/test/stdout/5405 new file mode 100644 index 000000000..14bfdabdd --- /dev/null +++ b/test/stdout/5405 @@ -0,0 +1,280 @@ +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmaX-0005vi-00 +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmaY-0005vi-00 +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmaZ-0005vi-00 +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +450 not right now +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmbA-0005vi-00 +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmbB-0005vi-00 +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +459 content reject +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmbD-0005vi-00 +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at myhost.test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +451 Could not complete recipient verify callout +503-All RCPT commands were rejected with this error: +503-Could not complete recipient verify callout +503 Valid RCPT command must precede DATA +500 unrecognized command +500 unrecognized command +221 myhost.test.ex closing connection + +******** SERVER ******** +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 Recipient OK +DATA +354 Send data +Received: from CALLER (helo=myhost.test.ex) + by myhost.test.ex with local-esmtp (Exim x.yz) + (envelope-from ) + id 10HmaX-0005vi-00 + for usera@domain.com; Tue, 2 Mar 1999 09:44:33 +0000 +Message-Id: +From: CALLER_NAME +Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-hdr-rtr-new: +++ + +. +250 OK +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 good rcpt +DATA +354 Send data +Received: from CALLER (helo=myhost.test.ex) + by myhost.test.ex with local-esmtp (Exim x.yz) + (envelope-from ) + id 10HmbA-0005vi-00 + for usere@domain.com; Tue, 2 Mar 1999 09:44:33 +0000 +Message-Id: +From: CALLER_NAME +Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-hdr-rtr-new: +++ + +. +459 content reject +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 good rcpt +DATA +354 Send data +Received: from CALLER (helo=myhost.test.ex) + by myhost.test.ex with local-esmtp (Exim x.yz) + (envelope-from ) + id 10HmbB-0005vi-00 + for userf@domain.com; Tue, 2 Mar 1999 09:44:33 +0000 +Message-Id: +From: CALLER_NAME +Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-hdr-rtr-new: +++ + +. +459 content reject +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 good rcpt +DATA +354 Send data +Received: from CALLER (helo=myhost.test.ex) + by myhost.test.ex with local-esmtp (Exim x.yz) + (envelope-from ) + id 10HmbC-0005vi-00 + for userg@domain.com; Tue, 2 Mar 1999 09:44:33 +0000 +Message-Id: +From: CALLER_NAME +Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-hdr-rtr-new: +++ + +. +459 content reject +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +250 Recipient OK +DATA +354 Send data +Received: from CALLER (helo=myhost.test.ex) + by myhost.test.ex with local-esmtp (Exim x.yz) + (envelope-from ) + id 10HmbD-0005vi-00 + for userh@domain.com; Tue, 2 Mar 1999 09:44:33 +0000 +Message-Id: +From: CALLER_NAME +Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-hdr-rtr-new: +++ + +. +250 OK +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 ESMTP +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 Sender OK +RCPT TO: +450 not right now +QUIT +250 OK +End of script