I18N: support IDNA2008. Bug 1911
[exim.git] / src / src / transports / smtp.c
index c6443978630ffb4f8e1bcdc018de8d17e92f402e..527142967e9eacf824202c4573bdf9663288bfdd 100644 (file)
@@ -124,6 +124,8 @@ optionlist smtp_transport_options[] = {
   { "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) },
@@ -209,6 +211,7 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   NULL,                /* hosts_try_dane */
   NULL,                /* hosts_require_dane */
 #endif
+  NULL,                /* hosts_try_fastopen */
 #ifndef DISABLE_PRDR
   US"*",               /* hosts_try_prdr */
 #endif
@@ -282,11 +285,11 @@ static uschar *rf_names[] = { US"NEVER", US"SUCCESS", US"FAILURE", US"DELAY" };
 
 /* Local statics */
 
-static uschar *smtp_command;   /* Points to last cmd for error messages */
-static uschar *mail_command;   /* Points to MAIL cmd for error messages */
-static BOOL    update_waiting; /* TRUE to update the "wait" database */
-static BOOL    pipelining_active; /* current transaction is in pipe mode */
-static int     off = 0;       /* for use by setsockopt */
+static uschar *smtp_command;           /* Points to last cmd for error messages */
+static uschar *mail_command;           /* Points to MAIL cmd for error messages */
+static uschar *data_command = US"";    /* Points to DATA cmd for error messages */
+static BOOL    update_waiting;         /* TRUE to update the "wait" database */
+static BOOL    pipelining_active;      /* current transaction is in pipe mode */
 
 
 /*************************************************
@@ -1388,10 +1391,14 @@ 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;
+  if (flags & tc_chunk_last)
+    data_command = string_copy(big_buffer);  /* Save for later error message */
+  }
 
 prev_cmd_count = cmd_count += tctx->cmd_count;
 
@@ -1586,6 +1593,7 @@ lflags.dane_required = verify_check_given_host(&ob->hosts_require_dane, host) ==
 
 *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. */
@@ -2171,10 +2179,10 @@ set it up. This cannot be done until the identify of the host is known. */
 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
@@ -2421,17 +2429,14 @@ for (addr = first_addr;
   rcpt_addr = transport_rcpt_address(addr, tblock->rcpt_include_affixes);
 
 #ifdef SUPPORT_I18N
-  {
-  uschar * dummy_errstr;
   if (  testflag(addrlist, af_utf8_downcvt)
-     && (rcpt_addr = string_address_utf8_to_alabel(rcpt_addr, &dummy_errstr),
-        dummy_errstr
-     )  )
+     && !(rcpt_addr = string_address_utf8_to_alabel(rcpt_addr, NULL))
+     )
     {
+    /*XXX could we use a per-address errstr here? Not fail the whole send? */
     errno = ERRNO_EXPANDFAIL;
     goto SEND_FAILED;
     }
-  }
 #endif
 
   count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s%s\r\n",
@@ -2509,6 +2514,7 @@ if (  !(peer_offered & PEER_OFFERED_CHUNKING)
     default: goto RESPONSE_FAILED;       /* I/O error, or any MAIL/DATA error */
     }
   pipelining_active = FALSE;
+  data_command = string_copy(big_buffer);  /* Save for later error message */
   }
 
 /* If there were no good recipients (but otherwise there have been no
@@ -2732,7 +2738,7 @@ else
 #else
            "LMTP error after %s: %s",
 #endif
-            big_buffer, string_printing(buffer));
+            data_command, string_printing(buffer));
           setflag(addr, af_pass_message);   /* Allow message to go to user */
           if (buffer[0] == '5')
             addr->transport_return = FAIL;
@@ -3165,8 +3171,9 @@ HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP(close)>>\n");
 if (lflags.send_quit)
   {
   shutdown(outblock.sock, SHUT_WR);
-  for (rc = 16; read(inblock.sock, inbuffer, sizeof(inbuffer)) > 0 && rc > 0;)
-    rc--;                              /* drain socket */
+  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);