Transport: fix smtp under combo of mua_wrapper and limited max_rcpt
[exim.git] / src / src / transports / smtp.c
index 43b62351358e6d483161422aa7ed019083f25dc8..2f41adbbf322e234d72328ab5007fea27e760561 100644 (file)
@@ -789,7 +789,9 @@ with an address by scanning for the next address whose status is PENDING_DEFER.
 
 while (count-- > 0)
   {
-  while (addr->transport_return != PENDING_DEFER) addr = addr->next;
+  while (addr->transport_return != PENDING_DEFER)
+    if (!(addr = addr->next))
+      return -2;
 
   /* The address was accepted */
   addr->host_used = sx->host;
@@ -1409,7 +1411,7 @@ if (sx->pending_BDAT)
     if (errno == 0 && sx->buffer[0] == '4')
       {
       errno = ERRNO_DATA4XX;   /*XXX does this actually get used? */
-      sx->first_addr->more_errno |=
+      sx->addrlist->more_errno |=
        ((sx->buffer[1] - '0')*10 + sx->buffer[2] - '0') << 8;
       }
     return ERROR;
@@ -1454,9 +1456,7 @@ smtp_setup_conn(smtp_context * sx, BOOL suppress_tls)
 dns_answer tlsa_dnsa;
 #endif
 BOOL pass_message = FALSE;
-
 uschar * message = NULL;
-int save_errno;
 int yield = OK;
 int rc;
 
@@ -1551,14 +1551,13 @@ if (continue_hostname == NULL)
   if (sx->inblock.sock < 0)
     {
     uschar * msg = NULL;
-    int save_errno = errno;
     if (sx->verify)
       {
-      msg = strerror(errno);
+      msg = US strerror(errno);
       HDEBUG(D_verify) debug_printf("connect: %s\n", msg);
       }
     set_errno_nohost(sx->addrlist,
-      save_errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : save_errno,
+      errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
       sx->verify ? string_sprintf("could not connect: %s", msg)
             : NULL,
       DEFER, FALSE);
@@ -2104,13 +2103,13 @@ return OK;
   SEND_FAILED:
     code = '4';
     message = US string_sprintf("send() to %s [%s] failed: %s",
-      sx->host->name, sx->host->address, strerror(save_errno));
+      sx->host->name, sx->host->address, strerror(errno));
     sx->send_quit = FALSE;
     goto FAILED;
 
   /* This label is jumped to directly when a TLS negotiation has failed,
   or was not done for a host for which it is required. Values will be set
-  in message and save_errno, and setting_up will always be true. Treat as
+  in message and errno, and setting_up will always be true. Treat as
   a temporary error. */
 
   EHLOHELO_FAILED:
@@ -2134,7 +2133,6 @@ return OK;
   tried again for a while. */
 
 FAILED:
-  save_errno = errno;
   sx->ok = FALSE;                /* For when reached by GOTO */
 
   yield = code == '5'
@@ -2143,7 +2141,7 @@ FAILED:
 #endif
     ? FAIL : DEFER;
 
-  set_errno(sx->addrlist, save_errno, message, yield, pass_message, sx->host
+  set_errno(sx->addrlist, errno, message, yield, pass_message, sx->host
 #ifdef EXPERIMENTAL_DSN_INFO
            , sx->smtp_greeting, sx->helo_response
 #endif
@@ -2170,7 +2168,7 @@ writing RSET might have failed, or there may be other addresses whose hosts are
 specified in the transports, and therefore not visible at top level, in which
 case continue_more won't get set. */
 
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP(close)>>\n");
+HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
 if (sx->send_quit)
   {
   shutdown(sx->outblock.sock, SHUT_WR);
@@ -2439,7 +2437,8 @@ for (addr = sx->first_addr, address_count = 0;
     ? dsn_support_yes : dsn_support_no;
 
   address_count++;
-  no_flush = pipelining_active && !sx->verify && (!mua_wrapper || addr->next);
+  no_flush = pipelining_active && !sx->verify
+         && (!mua_wrapper || addr->next && address_count < sx->max_rcpt);
 
   build_rcptcmd_options(sx, addr);
 
@@ -2640,13 +2639,15 @@ RCPT. */
 
 if (mua_wrapper)
   {
-  address_item *badaddr;
-  for (badaddr = sx.first_addr; badaddr; badaddr = badaddr->next)
-    if (badaddr->transport_return != PENDING_OK)
+  address_item * a;
+  unsigned cnt;
+
+  for (a = sx.first_addr, cnt = 0; a && cnt < sx.max_rcpt; a = a->next, cnt++)
+    if (a->transport_return != PENDING_OK)
       {
       /*XXX could we find a better errno than 0 here? */
-      set_errno_nohost(addrlist, 0, badaddr->message, FAIL,
-       testflag(badaddr, af_pass_message));
+      set_errno_nohost(addrlist, 0, a->message, FAIL,
+       testflag(a, af_pass_message));
       sx.ok = FALSE;
       break;
       }
@@ -3291,7 +3292,7 @@ writing RSET might have failed, or there may be other addresses whose hosts are
 specified in the transports, and therefore not visible at top level, in which
 case continue_more won't get set. */
 
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP(close)>>\n");
+HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
 if (sx.send_quit)
   {
   shutdown(sx.outblock.sock, SHUT_WR);