{ "hosts_try_dane", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_dane) },
#endif
+ { "hosts_try_fastopen", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, hosts_try_fastopen) },
#ifndef DISABLE_PRDR
{ "hosts_try_prdr", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_prdr) },
NULL, /* hosts_try_dane */
NULL, /* hosts_require_dane */
#endif
+ NULL, /* hosts_try_fastopen */
#ifndef DISABLE_PRDR
US"*", /* hosts_try_prdr */
#endif
static void
write_logs(address_item *addr, host_item *host)
{
-uschar * message = string_sprintf("H=%s [%s]", host->name, host->address);
+uschar * message = LOGGING(outgoing_port)
+ ? string_sprintf("H=%s [%s]:%d", host->name, host->address,
+ host->port == PORT_NONE ? 25 : host->port)
+ : string_sprintf("H=%s [%s]", host->name, host->address);
-if (LOGGING(outgoing_port))
- message = string_sprintf("%s:%d", message,
- host->port == PORT_NONE ? 25 : host->port);
if (addr->message)
{
message = string_sprintf("%s: %s", message, addr->message);
BOOL send_quit:1;
BOOL setting_up:1;
BOOL esmtp:1;
+ BOOL esmtp_sent:1;
BOOL pending_MAIL:1;
#ifndef DISABLE_PRDR
BOOL prdr_active:1;
lflags.send_quit = TRUE;
lflags.setting_up = TRUE;
lflags.esmtp = TRUE;
-lflags.pending_MAIL;
-#ifndef DISABLE_PRDR
-lflags.prdr_active;
-#endif
+lflags.esmtp_sent = FALSE;
#ifdef SUPPORT_I18N
lflags.utf8_needed = FALSE;
#endif
*message_defer = FALSE;
smtp_command = US"initial connection";
+buffer[0] = '\0';
if (max_rcpt == 0) max_rcpt = 999999;
/* Set up the buffer for reading SMTP response packets. */
if (!lflags.smtps)
{
- BOOL good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
+ BOOL good_response;
+
+#ifdef TCP_QUICKACK
+ (void) setsockopt(inblock.sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
+#endif
+ good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
'2', ob->command_timeout);
#ifdef EXPERIMENTAL_DSN_INFO
smtp_greeting = string_copy(buffer);
/* Now check if the helo_data expansion went well, and sign off cleanly if
it didn't. */
- if (helo_data == NULL)
+ if (!helo_data)
{
uschar *message = string_sprintf("failed to expand helo_data: %s",
expand_string_message);
if (smtp_write_command(&outblock, FALSE, "%s %s\r\n",
lflags.lmtp ? "LHLO" : "EHLO", helo_data) < 0)
goto SEND_FAILED;
+ lflags.esmtp_sent = TRUE;
if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
ob->command_timeout))
{
if (!lflags.esmtp)
{
BOOL good_response;
+ int n = sizeof(buffer);
+ uschar * rsp = buffer;
+
+ if (lflags.esmtp_sent && (n = Ustrlen(buffer)) < sizeof(buffer)/2)
+ { rsp = buffer + n + 1; n = sizeof(buffer) - n; }
if (smtp_write_command(&outblock, FALSE, "HELO %s\r\n", helo_data) < 0)
goto SEND_FAILED;
- good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
+ good_response = smtp_read_response(&inblock, rsp, n,
'2', ob->command_timeout);
#ifdef EXPERIMENTAL_DSN_INFO
- helo_response = string_copy(buffer);
+ helo_response = string_copy(rsp);
#endif
- if (!good_response) goto RESPONSE_FAILED;
+ if (!good_response)
+ {
+ /* Handle special logging for a closed connection after HELO
+ when had previously sent EHLO */
+
+ if (rsp != buffer && rsp[0] == 0 && (errno == 0 || errno == ECONNRESET))
+ {
+ message = NULL;
+ lflags.send_quit = FALSE;
+ save_errno = ERRNO_SMTPCLOSED;
+ message = string_sprintf("Remote host closed connection "
+ "in response to %s (EHLO response was: %s)",
+ smtp_command, buffer);
+ goto FAILED;
+ }
+ Ustrncpy(buffer, rsp, sizeof(buffer)/2);
+ goto RESPONSE_FAILED;
+ }
}
peer_offered = smtp_peer_options = 0;
if (rc != OK)
{
# ifdef EXPERIMENTAL_DANE
- if (rc == DEFER && lflags.dane)
- {
- log_write(0, LOG_MAIN,
+ if (lflags.dane) log_write(0, LOG_MAIN,
"DANE attempt failed; no TLS connection to %s [%s]",
host->name, host->address);
- }
# endif
save_errno = ERRNO_TLSFAILURE;
if (tblock->filter_command != NULL)
{
BOOL rc;
- uschar buffer[64];
- sprintf(CS buffer, "%.50s transport", tblock->name);
+ uschar fbuf[64];
+ sprintf(CS fbuf, "%.50s transport", tblock->name);
rc = transport_set_up_command(&transport_filter_argv, tblock->filter_command,
- TRUE, DEFER, addrlist, buffer, NULL);
+ TRUE, DEFER, addrlist, fbuf, NULL);
transport_filter_timeout = tblock->filter_timeout;
/* On failure, copy the error to all addresses, abandon the SMTP call, and
case continue_more won't get set. */
HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP(close)>>\n");
+if (lflags.send_quit)
+ {
+ shutdown(outblock.sock, SHUT_WR);
+ if (fcntl(inblock.sock, F_SETFL, O_NONBLOCK) == 0)
+ for (rc = 16; read(inblock.sock, inbuffer, sizeof(inbuffer)) > 0 && rc > 0;)
+ rc--; /* drain socket */
+ }
(void)close(inblock.sock);
#ifndef DISABLE_EVENT