before the lower case letters). Some live in the transport_instance block so as
to be publicly visible; these are flagged with opt_public. */
+#define LOFF(field) OPT_OFF(smtp_transport_options_block, field)
+
optionlist smtp_transport_options[] = {
{ "*expand_multi_domain", opt_stringptr | opt_hidden | opt_public,
- (void *)offsetof(transport_instance, expand_multi_domain) },
+ OPT_OFF(transport_instance, expand_multi_domain) },
{ "*expand_retry_include_ip_address", opt_stringptr | opt_hidden,
- (void *)(offsetof(smtp_transport_options_block, expand_retry_include_ip_address)) },
+ LOFF(expand_retry_include_ip_address) },
{ "address_retry_include_sender", opt_bool,
- (void *)offsetof(smtp_transport_options_block, address_retry_include_sender) },
- { "allow_localhost", opt_bool,
- (void *)offsetof(smtp_transport_options_block, allow_localhost) },
+ LOFF(address_retry_include_sender) },
+ { "allow_localhost", opt_bool, LOFF(allow_localhost) },
#ifdef EXPERIMENTAL_ARC
- { "arc_sign", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, arc_sign) },
-#endif
- { "authenticated_sender", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, authenticated_sender) },
- { "authenticated_sender_force", opt_bool,
- (void *)offsetof(smtp_transport_options_block, authenticated_sender_force) },
- { "command_timeout", opt_time,
- (void *)offsetof(smtp_transport_options_block, command_timeout) },
- { "connect_timeout", opt_time,
- (void *)offsetof(smtp_transport_options_block, connect_timeout) },
+ { "arc_sign", opt_stringptr, LOFF(arc_sign) },
+#endif
+ { "authenticated_sender", opt_stringptr, LOFF(authenticated_sender) },
+ { "authenticated_sender_force", opt_bool, LOFF(authenticated_sender_force) },
+ { "command_timeout", opt_time, LOFF(command_timeout) },
+ { "connect_timeout", opt_time, LOFF(connect_timeout) },
{ "connection_max_messages", opt_int | opt_public,
- (void *)offsetof(transport_instance, connection_max_messages) },
+ OPT_OFF(transport_instance, connection_max_messages) },
# ifdef SUPPORT_DANE
- { "dane_require_tls_ciphers", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dane_require_tls_ciphers) },
+ { "dane_require_tls_ciphers", opt_stringptr, LOFF(dane_require_tls_ciphers) },
# endif
- { "data_timeout", opt_time,
- (void *)offsetof(smtp_transport_options_block, data_timeout) },
- { "delay_after_cutoff", opt_bool,
- (void *)offsetof(smtp_transport_options_block, delay_after_cutoff) },
+ { "data_timeout", opt_time, LOFF(data_timeout) },
+ { "delay_after_cutoff", opt_bool, LOFF(delay_after_cutoff) },
#ifndef DISABLE_DKIM
- { "dkim_canon", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_canon) },
- { "dkim_domain", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_domain) },
- { "dkim_hash", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_hash) },
- { "dkim_identity", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_identity) },
- { "dkim_private_key", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_private_key) },
- { "dkim_selector", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_selector) },
- { "dkim_sign_headers", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_sign_headers) },
- { "dkim_strict", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_strict) },
- { "dkim_timestamps", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dkim.dkim_timestamps) },
-#endif
- { "dns_qualify_single", opt_bool,
- (void *)offsetof(smtp_transport_options_block, dns_qualify_single) },
- { "dns_search_parents", opt_bool,
- (void *)offsetof(smtp_transport_options_block, dns_search_parents) },
- { "dnssec_request_domains", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dnssec.request) },
- { "dnssec_require_domains", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dnssec.require) },
- { "dscp", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, dscp) },
- { "fallback_hosts", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, fallback_hosts) },
- { "final_timeout", opt_time,
- (void *)offsetof(smtp_transport_options_block, final_timeout) },
- { "gethostbyname", opt_bool,
- (void *)offsetof(smtp_transport_options_block, gethostbyname) },
- { "helo_data", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, helo_data) },
- { "hosts", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts) },
- { "hosts_avoid_esmtp", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_avoid_esmtp) },
- { "hosts_avoid_pipelining", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_avoid_pipelining) },
+ { "dkim_canon", opt_stringptr, LOFF(dkim.dkim_canon) },
+ { "dkim_domain", opt_stringptr, LOFF(dkim.dkim_domain) },
+ { "dkim_hash", opt_stringptr, LOFF(dkim.dkim_hash) },
+ { "dkim_identity", opt_stringptr, LOFF(dkim.dkim_identity) },
+ { "dkim_private_key", opt_stringptr, LOFF(dkim.dkim_private_key) },
+ { "dkim_selector", opt_stringptr, LOFF(dkim.dkim_selector) },
+ { "dkim_sign_headers", opt_stringptr, LOFF(dkim.dkim_sign_headers) },
+ { "dkim_strict", opt_stringptr, LOFF(dkim.dkim_strict) },
+ { "dkim_timestamps", opt_stringptr, LOFF(dkim.dkim_timestamps) },
+#endif
+ { "dns_qualify_single", opt_bool, LOFF(dns_qualify_single) },
+ { "dns_search_parents", opt_bool, LOFF(dns_search_parents) },
+ { "dnssec_request_domains", opt_stringptr, LOFF(dnssec.request) },
+ { "dnssec_require_domains", opt_stringptr, LOFF(dnssec.require) },
+ { "dscp", opt_stringptr, LOFF(dscp) },
+ { "fallback_hosts", opt_stringptr, LOFF(fallback_hosts) },
+ { "final_timeout", opt_time, LOFF(final_timeout) },
+ { "gethostbyname", opt_bool, LOFF(gethostbyname) },
+ { "helo_data", opt_stringptr, LOFF(helo_data) },
+ { "hosts", opt_stringptr, LOFF(hosts) },
+ { "hosts_avoid_esmtp", opt_stringptr, LOFF(hosts_avoid_esmtp) },
+ { "hosts_avoid_pipelining", opt_stringptr, LOFF(hosts_avoid_pipelining) },
#ifndef DISABLE_TLS
- { "hosts_avoid_tls", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_avoid_tls) },
+ { "hosts_avoid_tls", opt_stringptr, LOFF(hosts_avoid_tls) },
#endif
- { "hosts_max_try", opt_int,
- (void *)offsetof(smtp_transport_options_block, hosts_max_try) },
- { "hosts_max_try_hardlimit", opt_int,
- (void *)offsetof(smtp_transport_options_block, hosts_max_try_hardlimit) },
+ { "hosts_max_try", opt_int, LOFF(hosts_max_try) },
+ { "hosts_max_try_hardlimit", opt_int, LOFF(hosts_max_try_hardlimit) },
#ifndef DISABLE_TLS
- { "hosts_nopass_tls", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_nopass_tls) },
- { "hosts_noproxy_tls", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_noproxy_tls) },
+ { "hosts_nopass_tls", opt_stringptr, LOFF(hosts_nopass_tls) },
+ { "hosts_noproxy_tls", opt_stringptr, LOFF(hosts_noproxy_tls) },
#endif
- { "hosts_override", opt_bool,
- (void *)offsetof(smtp_transport_options_block, hosts_override) },
+ { "hosts_override", opt_bool, LOFF(hosts_override) },
#ifndef DISABLE_PIPE_CONNECT
- { "hosts_pipe_connect", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_pipe_connect) },
+ { "hosts_pipe_connect", opt_stringptr, LOFF(hosts_pipe_connect) },
#endif
- { "hosts_randomize", opt_bool,
- (void *)offsetof(smtp_transport_options_block, hosts_randomize) },
+ { "hosts_randomize", opt_bool, LOFF(hosts_randomize) },
#if !defined(DISABLE_TLS) && !defined(DISABLE_OCSP)
- { "hosts_request_ocsp", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_request_ocsp) },
+ { "hosts_request_ocsp", opt_stringptr, LOFF(hosts_request_ocsp) },
#endif
- { "hosts_require_auth", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_require_auth) },
+ { "hosts_require_auth", opt_stringptr, LOFF(hosts_require_auth) },
#ifndef DISABLE_TLS
# ifdef SUPPORT_DANE
- { "hosts_require_dane", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_require_dane) },
+ { "hosts_require_dane", opt_stringptr, LOFF(hosts_require_dane) },
# endif
# ifndef DISABLE_OCSP
- { "hosts_require_ocsp", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_require_ocsp) },
+ { "hosts_require_ocsp", opt_stringptr, LOFF(hosts_require_ocsp) },
# endif
- { "hosts_require_tls", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_require_tls) },
+ { "hosts_require_tls", opt_stringptr, LOFF(hosts_require_tls) },
#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) },
+ { "hosts_try_auth", opt_stringptr, LOFF(hosts_try_auth) },
+ { "hosts_try_chunking", opt_stringptr, LOFF(hosts_try_chunking) },
#ifdef SUPPORT_DANE
- { "hosts_try_dane", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_try_dane) },
+ { "hosts_try_dane", opt_stringptr, LOFF(hosts_try_dane) },
#endif
- { "hosts_try_fastopen", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_try_fastopen) },
+ { "hosts_try_fastopen", opt_stringptr, LOFF(hosts_try_fastopen) },
#ifndef DISABLE_PRDR
- { "hosts_try_prdr", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_try_prdr) },
+ { "hosts_try_prdr", opt_stringptr, LOFF(hosts_try_prdr) },
#endif
#ifndef DISABLE_TLS
- { "hosts_verify_avoid_tls", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, hosts_verify_avoid_tls) },
-#endif
- { "interface", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, interface) },
- { "keepalive", opt_bool,
- (void *)offsetof(smtp_transport_options_block, keepalive) },
- { "lmtp_ignore_quota", opt_bool,
- (void *)offsetof(smtp_transport_options_block, lmtp_ignore_quota) },
+ { "hosts_verify_avoid_tls", opt_stringptr, LOFF(hosts_verify_avoid_tls) },
+#endif
+ { "interface", opt_stringptr, LOFF(interface) },
+ { "keepalive", opt_bool, LOFF(keepalive) },
+ { "lmtp_ignore_quota", opt_bool, LOFF(lmtp_ignore_quota) },
{ "max_rcpt", opt_int | opt_public,
- (void *)offsetof(transport_instance, max_addresses) },
+ OPT_OFF(transport_instance, max_addresses) },
{ "multi_domain", opt_expand_bool | opt_public,
- (void *)offsetof(transport_instance, multi_domain) },
- { "port", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, port) },
- { "protocol", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, protocol) },
- { "retry_include_ip_address", opt_expand_bool,
- (void *)offsetof(smtp_transport_options_block, retry_include_ip_address) },
- { "serialize_hosts", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, serialize_hosts) },
- { "size_addition", opt_int,
- (void *)offsetof(smtp_transport_options_block, size_addition) },
+ OPT_OFF(transport_instance, multi_domain) },
+ { "port", opt_stringptr, LOFF(port) },
+ { "protocol", opt_stringptr, LOFF(protocol) },
+ { "retry_include_ip_address", opt_expand_bool, LOFF(retry_include_ip_address) },
+ { "serialize_hosts", opt_stringptr, LOFF(serialize_hosts) },
+ { "size_addition", opt_int, LOFF(size_addition) },
#ifdef SUPPORT_SOCKS
- { "socks_proxy", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, socks_proxy) },
+ { "socks_proxy", opt_stringptr, LOFF(socks_proxy) },
#endif
#ifndef DISABLE_TLS
- { "tls_certificate", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_certificate) },
- { "tls_crl", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_crl) },
- { "tls_dh_min_bits", opt_int,
- (void *)offsetof(smtp_transport_options_block, tls_dh_min_bits) },
- { "tls_privatekey", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_privatekey) },
- { "tls_require_ciphers", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_require_ciphers) },
+ { "tls_certificate", opt_stringptr, LOFF(tls_certificate) },
+ { "tls_crl", opt_stringptr, LOFF(tls_crl) },
+ { "tls_dh_min_bits", opt_int, LOFF(tls_dh_min_bits) },
+ { "tls_privatekey", opt_stringptr, LOFF(tls_privatekey) },
+ { "tls_require_ciphers", opt_stringptr, LOFF(tls_require_ciphers) },
# ifdef EXPERIMENTAL_TLS_RESUME
- { "tls_resumption_hosts", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_resumption_hosts) },
+ { "tls_resumption_hosts", opt_stringptr, LOFF(tls_resumption_hosts) },
# endif
- { "tls_sni", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_sni) },
- { "tls_tempfail_tryclear", opt_bool,
- (void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) },
- { "tls_try_verify_hosts", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_try_verify_hosts) },
- { "tls_verify_cert_hostnames", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block,tls_verify_cert_hostnames)},
- { "tls_verify_certificates", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) },
- { "tls_verify_hosts", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_verify_hosts) },
+ { "tls_sni", opt_stringptr, LOFF(tls_sni) },
+ { "tls_tempfail_tryclear", opt_bool, LOFF(tls_tempfail_tryclear) },
+ { "tls_try_verify_hosts", opt_stringptr, LOFF(tls_try_verify_hosts) },
+ { "tls_verify_cert_hostnames", opt_stringptr, LOFF(tls_verify_cert_hostnames)},
+ { "tls_verify_certificates", opt_stringptr, LOFF(tls_verify_certificates) },
+ { "tls_verify_hosts", opt_stringptr, LOFF(tls_verify_hosts) },
#endif
#ifdef SUPPORT_I18N
- { "utf8_downconvert", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, utf8_downconvert) },
+ { "utf8_downconvert", opt_stringptr, LOFF(utf8_downconvert) },
#endif
};
host if set, mark addrs as having used this host
smtp_greeting from peer
helo_response from peer
+ start points to timestamp of delivery start
If errno_value has the special value ERRNO_CONNECTTIMEOUT, ETIMEDOUT is put in
the errno field, and RTEF_CTOUT is ORed into the more_errno field, to indicate
static void
set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
- BOOL pass_message, host_item * host
+ BOOL pass_message, host_item * host,
#ifdef EXPERIMENTAL_DSN_INFO
- , const uschar * smtp_greeting, const uschar * helo_response
+ const uschar * smtp_greeting, const uschar * helo_response,
#endif
+ struct timeval * start
)
{
int orvalue = 0;
+struct timeval deliver_time;
+
if (errno_value == ERRNO_CONNECTTIMEOUT)
{
errno_value = ETIMEDOUT;
orvalue = RTEF_CTOUT;
}
+timesince(&deliver_time, start);
+
for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return >= PENDING)
{
addr->basic_errno = errno_value;
addr->more_errno |= orvalue;
+ addr->delivery_time = deliver_time;
if (msg)
{
addr->message = msg;
}
static void
-set_errno_nohost(address_item *addrlist, int errno_value, uschar *msg, int rc,
- BOOL pass_message)
+set_errno_nohost(address_item * addrlist, int errno_value, uschar * msg, int rc,
+ BOOL pass_message, struct timeval * start)
{
-set_errno(addrlist, errno_value, msg, rc, pass_message, NULL
+set_errno(addrlist, errno_value, msg, rc, pass_message, NULL,
#ifdef EXPERIMENTAL_DSN_INFO
- , NULL, NULL
+ NULL, NULL,
#endif
- );
+ start);
}
{
uschar *message = string_sprintf("SMTP timeout after RCPT TO:<%s>",
transport_rcpt_address(addr, sx->conn_args.tblock->rcpt_include_affixes));
- set_errno_nohost(sx->first_addr, ETIMEDOUT, message, DEFER, FALSE);
+ set_errno_nohost(sx->first_addr, ETIMEDOUT, message, DEFER, FALSE, &sx->delivery_start);
retry_add_item(addr, addr->address_retry_key, 0);
update_waiting = FALSE;
return -1;
case ERROR:
set_errno_nohost(sx->addrlist, ERRNO_AUTHPROB, string_copy(sx->buffer),
- DEFER, FALSE);
+ DEFER, FALSE, &sx->delivery_start);
return ERROR;
}
return OK;
{
set_errno_nohost(sx->addrlist, ERRNO_AUTHFAIL,
string_sprintf("authentication required but %s", fail_reason), DEFER,
- FALSE);
+ FALSE, &sx->delivery_start);
return DEFER;
}
/* Construct AUTH appendix string for MAIL TO */
/*
Arguments
- buffer to build string
+ sx context for smtp connection
+ p point in sx->buffer to build string
addrlist chain of potential addresses to deliver
- ob transport options
Globals f.smtp_authenticated
client_authenticated_sender
*/
static BOOL
-smtp_mail_auth_str(uschar *buffer, unsigned bufsize, address_item *addrlist,
- smtp_transport_options_block *ob)
+smtp_mail_auth_str(smtp_context * sx, uschar * p, address_item * addrlist)
{
+smtp_transport_options_block * ob = sx->conn_args.ob;
uschar * local_authenticated_sender = authenticated_sender;
#ifdef notdef
- debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n", authenticated_sender, ob->authenticated_sender, f.smtp_authenticated?"Y":"N");
+ debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n",
+ authenticated_sender, ob->authenticated_sender, f.smtp_authenticated?"Y":"N");
#endif
if (ob->authenticated_sender)
{
- uschar *new = expand_string(ob->authenticated_sender);
+ uschar * new = expand_string(ob->authenticated_sender);
if (!new)
{
if (!f.expand_string_forcedfail)
{
uschar *message = string_sprintf("failed to expand "
"authenticated_sender: %s", expand_string_message);
- set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, &sx->delivery_start);
return TRUE;
}
}
- else if (*new) local_authenticated_sender = new;
+ else if (*new)
+ local_authenticated_sender = new;
}
/* Add the authenticated sender address if present */
if ( (f.smtp_authenticated || ob->authenticated_sender_force)
&& local_authenticated_sender)
{
- string_format_nt(buffer, bufsize, " AUTH=%s",
+ string_format_nt(p, sizeof(sx->buffer) - (p-sx->buffer), " AUTH=%s",
auth_xtextencode(local_authenticated_sender,
Ustrlen(local_authenticated_sender)));
client_authenticated_sender = string_copy(local_authenticated_sender);
}
else
- *buffer= 0;
+ *p = 0;
return FALSE;
}
smtp_local_identity(s_compare->current_sender_address, s_compare->tblock);
if (!(new_sender_address = deliver_get_sender_address(message_id)))
- return 0;
+ return FALSE;
message_local_identity =
smtp_local_identity(new_sender_address, s_compare->tblock);
if (sx->smtps)
{
set_errno_nohost(sx->addrlist, ERRNO_TLSFAILURE, US"TLS support not available",
- DEFER, FALSE);
+ DEFER, FALSE, &sx->delivery_start);
return ERROR;
}
#endif
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
rc_to_string(rc)),
- rc, FALSE);
+ rc, FALSE, &sx->delivery_start);
# ifndef DISABLE_EVENT
(void) event_raise(sx->conn_args.tblock->event_action,
US"dane:fail", sx->dane_required
{
set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: %s lookup not DNSSEC", sx->conn_args.host->name),
- FAIL, FALSE);
+ FAIL, FALSE, &sx->delivery_start);
# ifndef DISABLE_EVENT
(void) event_raise(sx->conn_args.tblock->event_action,
US"dane:fail", US"dane-required");
else DEBUG(D_transport)
debug_printf("helo needs $sending_ip_address\n");
+PIPE_CONNECT_RETRY:
if (sx->early_pipe_active)
sx->outblock.conn_args = &sx->conn_args;
else
set_errno_nohost(sx->addrlist,
errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
sx->verify ? US strerror(errno) : NULL,
- DEFER, FALSE);
+ DEFER, FALSE, &sx->delivery_start);
sx->send_quit = FALSE;
return DEFER;
}
{
set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL,
string_sprintf("deferred by smtp:connect event expansion: %s", s),
- DEFER, FALSE);
+ DEFER, FALSE, &sx->delivery_start);
yield = DEFER;
goto SEND_QUIT;
}
{
message = string_sprintf("failed to expand helo_data: %s",
expand_string_message);
- set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
+ set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, &sx->delivery_start);
yield = DEFER;
goto SEND_QUIT;
}
}
sx->inblock.cctx = sx->outblock.cctx = &sx->cctx;
smtp_command = big_buffer;
+ sx->peer_offered = smtp_peer_options;
sx->helo_data = NULL; /* ensure we re-expand ob->helo_data */
/* For a continued connection with TLS being proxied for us, or a
&& cutthrough.is_tls)
)
{
- sx->peer_offered = smtp_peer_options;
sx->pipelining_used = pipelining_active = !!(smtp_peer_options & OPTION_PIPE);
HDEBUG(D_transport) debug_printf("continued connection, %s TLS\n",
continue_proxy_cipher ? "proxied" : "verify conn with");
{
HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
- goto RESPONSE_FAILED;
+ close(sx->cctx.sock);
+ sx->cctx.sock = -1;
+ sx->early_pipe_active = FALSE;
+ goto PIPE_CONNECT_RETRY;
}
#endif
{
uschar *message = string_sprintf("failed to expand helo_data: %s",
expand_string_message);
- set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
+ set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, &sx->delivery_start);
yield = DEFER;
goto SEND_QUIT;
}
{
message = string_sprintf("failed to expand utf8_downconvert: %s",
expand_string_message);
- set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
+ set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, &sx->delivery_start);
yield = DEFER;
goto SEND_QUIT;
}
set_errno_nohost(sx->addrlist,
errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
sx->verify ? US strerror(errno) : NULL,
- DEFER, FALSE);
+ DEFER, FALSE, &sx->delivery_start);
sx->send_quit = FALSE;
return DEFER;
}
#endif
? FAIL : DEFER,
pass_message,
- errno == ECONNREFUSED ? NULL : sx->conn_args.host
+ errno == ECONNREFUSED ? NULL : sx->conn_args.host,
#ifdef EXPERIMENTAL_DSN_INFO
- , sx->smtp_greeting, sx->helo_response
+ sx->smtp_greeting, sx->helo_response,
#endif
- );
+ &sx->delivery_start);
}
otherwise no check - this feature is expected to be used with LMTP and other
cases where non-standard addresses (e.g. without domains) might be required. */
-if (smtp_mail_auth_str(p, sizeof(sx->buffer) - (p-sx->buffer), addrlist, sx->conn_args.ob))
- return ERROR;
-
-return OK;
+return smtp_mail_auth_str(sx, p, addrlist) ? ERROR : OK;
}
{
if (s = string_address_utf8_to_alabel(s, &errstr), errstr)
{
- set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE);
+ set_errno_nohost(sx->addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE, &sx->delivery_start);
*yield = ERROR;
return -4;
}
int rc, i;
close(pfd[1]);
-if ((rc = fork()))
+if ((rc = exim_fork(US"tls proxy")))
{
DEBUG(D_transport) debug_printf("proxy-proc final-pid %d\n", rc);
_exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
/* If continue_hostname is not null, we get here only when continuing to
deliver down an existing channel. The channel was passed as the standard
-input. TLS is never active on a passed channel; the previous process always
-closes it down before passing the connection on.
+input. TLS is never active on a passed channel; the previous process either
+closes it down before passing the connection on, or inserts a TLS-proxy
+process and passes on a cleartext conection.
Otherwise, we have to make a connection to the remote host, and do the
initial protocol exchange.
and there was a problem setting it up; OR helo_data
or add_headers or authenticated_sender is specified
for this transport, and the string failed to expand
+
+ For all non-OK returns the first addr of the list carries the
+ time taken for the attempt.
*/
static int
int yield = OK;
int save_errno;
int rc;
-struct timeval start_delivery_time;
BOOL pass_message = FALSE;
uschar *message = NULL;
uschar new_message_id[MESSAGE_ID_LENGTH + 1];
smtp_context * sx = store_get(sizeof(*sx), TRUE); /* tainted, for the data buffers */
-gettimeofday(&start_delivery_time, NULL);
suppress_tls = suppress_tls; /* stop compiler warning when no TLS support */
*message_defer = FALSE;
sx->helo_data = NULL;
sx->conn_args.tblock = tblock;
/* sx->verify = FALSE; */
+gettimeofday(&sx->delivery_start, NULL);
sx->sync_addr = sx->first_addr = addrlist;
/* Get the channel set up ready for a message (MAIL FROM being the next
SMTP command to send */
if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK)
+ {
+ timesince(&addrlist->delivery_time, &sx->delivery_start);
return rc;
+ }
/* If there is a filter command specified for this transport, we can now
-set it up. This cannot be done until the identify of the host is known. */
+set it up. This cannot be done until the identity of the host is known. */
if (tblock->filter_command)
{
string_sprintf("%.50s transport", tblock->name), NULL))
{
set_errno_nohost(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
- FALSE);
+ FALSE, &sx->delivery_start);
yield = ERROR;
goto SEND_QUIT;
}
if (continue_hostname && continue_sequence == 1)
{
- sx->peer_offered = smtp_peer_options;
/* sx->pending_MAIL = FALSE; */
sx->ok = TRUE;
/* sx->next_addr = NULL; */
{
/*XXX could we find a better errno than 0 here? */
set_errno_nohost(addrlist, 0, a->message, FAIL,
- testflag(a, af_pass_message));
+ testflag(a, af_pass_message), &sx->delivery_start);
sx->ok = FALSE;
break;
}
int len;
uschar * conf = NULL;
- timesince(&delivery_time, &start_delivery_time);
+ timesince(&delivery_time, &sx->delivery_start);
sx->send_rset = FALSE;
pipelining_active = FALSE;
actual host that was used. */
addr->transport_return = OK;
- addr->more_errno = delivery_time.tv_sec;
- addr->delivery_usec = delivery_time.tv_usec;
addr->host_used = host;
+ addr->delivery_time = delivery_time;
addr->special_action = flag;
addr->message = conf;
}
}
- set_errno(addrlist, save_errno, set_message, set_rc, pass_message, host
+ set_errno(addrlist, save_errno, set_message, set_rc, pass_message, host,
#ifdef EXPERIMENTAL_DSN_INFO
- , sx->smtp_greeting, sx->helo_response
+ sx->smtp_greeting, sx->helo_response,
#endif
- );
+ &sx->delivery_start);
}
/* If all has gone well, send_quit will be set TRUE, implying we can end the
socket_fd = pfd[1];
else
set_errno(sx->first_addr, errno, US"internal allocation problem",
- DEFER, FALSE, host
+ DEFER, FALSE, host,
# ifdef EXPERIMENTAL_DSN_INFO
- , sx->smtp_greeting, sx->helo_response
+ sx->smtp_greeting, sx->helo_response,
# endif
- );
+ &sx->delivery_start);
}
else
#endif
#ifndef DISABLE_TLS
if (tls_out.active.sock >= 0)
{
- int pid = fork();
+ int pid = exim_fork(US"tls proxy interproc");
if (pid == 0) /* child; fork again to disconnect totally */
{
testharness_pause_ms(100); /* let parent debug out */
/* If RSET failed and there are addresses left, they get deferred. */
else
- set_errno(sx->first_addr, errno, msg, DEFER, FALSE, host
+ set_errno(sx->first_addr, errno, msg, DEFER, FALSE, host,
#ifdef EXPERIMENTAL_DSN_INFO
- , sx->smtp_greeting, sx->helo_response
+ sx->smtp_greeting, sx->helo_response,
#endif
- );
+ &sx->delivery_start);
}
}
were not in it. We don't want to hold up all SMTP deliveries! Except when
doing a two-stage queue run, don't do this if forcing. */
- if ((!f.deliver_force || f.queue_2stage) && (f.queue_smtp ||
- match_isinlist(addrlist->domain,
- (const uschar **)&queue_smtp_domains, 0,
- &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK))
+ if ( (!f.deliver_force || f.queue_2stage)
+ && ( f.queue_smtp
+ || match_isinlist(addrlist->domain,
+ CUSS &queue_smtp_domains, 0,
+ &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK)
+ )
{
+ DEBUG(D_transport) debug_printf("first-pass routing only\n");
expired = FALSE;
for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return == DEFER)
- addr->message = US"domain matches queue_smtp_domains, or -odqs set";
+ addr->message = US"first-pass only routing due to -odqs, "
+ "queue_smtp_domains or control=queue";
continue; /* With next host */
}
if (f.dont_deliver)
{
- set_errno_nohost(addrlist, 0, NULL, OK, FALSE);
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ set_errno_nohost(addrlist, 0, NULL, OK, FALSE, &now);
for (address_item * addr = addrlist; addr; addr = addr->next)
{
addr->host_used = host;