#define MT_NOT 1
#define MT_ALL 2
-static uschar cutthrough_response(char, uschar **);
+static uschar cutthrough_response(char, uschar **, int);
+
/*************************************************
transport_rcpt_address(addr,
(addr->transport == NULL)? FALSE :
addr->transport->rcpt_include_affixes)) >= 0 &&
- cutthrough_response('2', &resp) == '2';
+ cutthrough_response('2', &resp, CUTTHROUGH_DATA_TIMEOUT) == '2';
/* This would go horribly wrong if a callout fail was ignored by ACL.
We punt by abandoning cutthrough on a reject, like the
addr->transport);
if (inblock.sock < 0)
{
+ HDEBUG(D_verify) debug_printf("connect: %s\n", strerror(errno));
addr->message = string_sprintf("could not connect to %s [%s]: %s",
host->name, host->address, strerror(errno));
transport_name = NULL;
if (!smtps || (smtps && tls_out.active >= 0))
#endif
{
+#ifdef TCP_QUICKACK
+ (void) setsockopt(inblock.sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
+#endif
if (!(done= smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout)))
goto RESPONSE_FAILED;
: 0;
}
- size_str = peer_offered & PEER_OFFERED_SIZE
+ size_str = options & vopt_is_recipient && peer_offered & PEER_OFFERED_SIZE
? string_sprintf(" SIZE=%d", message_size + ob->size_addition) : US"";
#ifdef SUPPORT_TLS
connection, if the options permit it for this host. */
if (rc != OK)
{
- if (rc == DEFER)
- {
- (void)close(inblock.sock);
+ HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP(close)>>\n");
+ (void)close(inblock.sock);
# ifndef DISABLE_EVENT
- (void) event_raise(addr->transport->event_action,
- US"tcp:close", NULL);
+ (void) event_raise(addr->transport->event_action,
+ US"tcp:close", NULL);
# endif
- if ( ob->tls_tempfail_tryclear
- && !smtps
- && verify_check_given_host(&ob->hosts_require_tls, host) != OK
- )
- {
- log_write(0, LOG_MAIN, "TLS session failure:"
- " delivering unencrypted to %s [%s] (not in hosts_require_tls)",
- host->name, host->address);
- suppress_tls = TRUE;
- goto tls_retry_connection;
- }
+ if ( ob->tls_tempfail_tryclear
+ && !smtps
+ && verify_check_given_host(&ob->hosts_require_tls, host) != OK
+ )
+ {
+ log_write(0, LOG_MAIN, "TLS session failure:"
+ " callout unencrypted to %s [%s] (not in hosts_require_tls)",
+ host->name, host->address);
+ suppress_tls = TRUE;
+ goto tls_retry_connection;
}
/*save_errno = ERRNO_TLSFAILURE;*/
}
else if ( addr->prop.utf8_msg
&& (addr->prop.utf8_downcvt || !(peer_offered & PEER_OFFERED_UTF8))
- && (setflag(addr, af_utf8_downcvt),
- from_address = string_address_utf8_to_alabel(from_address,
- &addr->message),
- addr->message
- ) )
+ && !(setflag(addr, af_utf8_downcvt),
+ from_address = string_address_utf8_to_alabel(from_address,
+ &addr->message)
+ ) )
{
errno = ERRNO_EXPANDFAIL;
setflag(addr, af_verify_nsfail);
#ifdef SUPPORT_TLS
tls_close(FALSE, TRUE);
#endif
+ HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP(close)>>\n");
(void)close(inblock.sock);
#ifndef DISABLE_EVENT
(void) event_raise(addr->transport->event_action,
#ifdef SUPPORT_I18N
/*XXX should the conversion be moved into transport_rcpt_address() ? */
- uschar * dummy_errstr = NULL;
if ( testflag(addr, af_utf8_downcvt)
- && (rcpt = string_address_utf8_to_alabel(rcpt, &dummy_errstr),
- dummy_errstr
- ) )
- {
- errno = ERRNO_EXPANDFAIL;
- *failure_ptr = US"recipient";
- done = FALSE;
- }
+ && !(rcpt = string_address_utf8_to_alabel(rcpt, NULL))
+ )
+ {
+ errno = ERRNO_EXPANDFAIL;
+ *failure_ptr = US"recipient";
+ done = FALSE;
+ }
else
#endif
if (options & vopt_callout_recipsender)
cancel_cutthrough_connection("not usable for cutthrough");
if (send_quit)
+ {
(void) smtp_write_command(&outblock, FALSE, "QUIT\r\n");
+ /* Wait a short time for response, and discard it */
+ smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
+ '2', 1);
+ }
+
#ifdef SUPPORT_TLS
tls_close(FALSE, TRUE);
#endif
+ HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP(close)>>\n");
(void)close(inblock.sock);
#ifndef DISABLE_EVENT
(void) event_raise(addr->transport->event_action, US"tcp:close", NULL);
/* Get and check response from cutthrough target */
static uschar
-cutthrough_response(char expect, uschar ** copy)
+cutthrough_response(char expect, uschar ** copy, int timeout)
{
smtp_inblock inblock;
uschar inbuffer[4096];
inblock.ptrend = inbuffer;
inblock.sock = cutthrough.fd;
/* this relies on (inblock.sock == tls_out.active) */
-if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect, CUTTHROUGH_DATA_TIMEOUT))
+if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect, timeout))
cancel_cutthrough_connection("target timeout on read");
if(copy != NULL)
cutthrough_flush_send();
/* Assume nothing buffered. If it was it gets ignored. */
-return cutthrough_response('3', NULL) == '3';
+return cutthrough_response('3', NULL, CUTTHROUGH_DATA_TIMEOUT) == '3';
}
HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP>> QUIT\n");
_cutthrough_puts(US"QUIT\r\n", 6); /* avoid recursion */
_cutthrough_flush_send();
- /* No wait for response */
+
+ /* Wait a short time for response, and discard it */
+ cutthrough_response('2', NULL, 1);
#ifdef SUPPORT_TLS
tls_close(FALSE, TRUE);
#endif
+ HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP(close)>>\n");
(void)close(cutthrough.fd);
cutthrough.fd = -1;
HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown (%s) ------------\n", why);
)
return cutthrough.addr.message;
-res = cutthrough_response('2', &cutthrough.addr.message);
+res = cutthrough_response('2', &cutthrough.addr.message, CUTTHROUGH_DATA_TIMEOUT);
for (addr = &cutthrough.addr; addr; addr = addr->next)
{
addr->message = cutthrough.addr.message;
to the incoming interface address. If the sender host address is an IPv6
address, the incoming interface address will also be IPv6. */
-host_af = (Ustrchr(sender_host_address, ':') == NULL)? AF_INET : AF_INET6;
-sock = ip_socket(SOCK_STREAM, host_af);
-if (sock < 0) return;
+host_af = Ustrchr(sender_host_address, ':') == NULL ? AF_INET : AF_INET6;
+if ((sock = ip_socket(SOCK_STREAM, host_af)) < 0) return;
if (ip_bind(sock, host_af, interface_address, 0) < 0)
{
goto END_OFF;
}
-if (ip_connect(sock, host_af, sender_host_address, port, rfc1413_query_timeout)
- < 0)
+if (ip_connect(sock, host_af, sender_host_address, port,
+ rfc1413_query_timeout, TRUE) < 0)
{
if (errno == ETIMEDOUT && LOGGING(ident_timeout))
- {
log_write(0, LOG_MAIN, "ident connection to %s timed out",
sender_host_address);
- }
else
- {
DEBUG(D_ident) debug_printf("ident connection to %s failed: %s\n",
sender_host_address, strerror(errno));
- }
goto END_OFF;
}