Upgrade appendfile so that it is capable of handling quotas that are
[exim.git] / src / src / transports / smtp.c
index a756f81db7fa8b208d64ce3d8deb72acc03d6dd5..69b1c1965bed1544d4b78b631077245f90e6f7f6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.5 2005/01/11 15:51:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.11 2005/04/28 13:06:32 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -35,6 +35,20 @@ optionlist smtp_transport_options[] = {
       (void *)offsetof(smtp_transport_options_block, data_timeout) },
   { "delay_after_cutoff", opt_bool,
       (void *)offsetof(smtp_transport_options_block, delay_after_cutoff) },
       (void *)offsetof(smtp_transport_options_block, data_timeout) },
   { "delay_after_cutoff", opt_bool,
       (void *)offsetof(smtp_transport_options_block, delay_after_cutoff) },
+#ifdef EXPERIMENTAL_DOMAINKEYS
+  { "dk_canon", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, dk_canon) },
+  { "dk_domain", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, dk_domain) },
+  { "dk_headers", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, dk_headers) },
+  { "dk_private_key", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, dk_private_key) },
+  { "dk_selector", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, dk_selector) },
+  { "dk_strict", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, dk_strict) },
+#endif
   { "dns_qualify_single",   opt_bool,
       (void *)offsetof(smtp_transport_options_block, dns_qualify_single) },
   { "dns_search_parents",   opt_bool,
   { "dns_qualify_single",   opt_bool,
       (void *)offsetof(smtp_transport_options_block, dns_qualify_single) },
   { "dns_search_parents",   opt_bool,
@@ -140,7 +154,7 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   10*60,               /* final timeout */
   1024,                /* size_addition */
   5,                   /* hosts_max_try */
   10*60,               /* final timeout */
   1024,                /* size_addition */
   5,                   /* hosts_max_try */
-  50,                  /* hosts_max_try_hardlimit */ 
+  50,                  /* hosts_max_try_hardlimit */
   FALSE,               /* allow_localhost */
   FALSE,               /* gethostbyname */
   TRUE,                /* dns_qualify_single */
   FALSE,               /* allow_localhost */
   FALSE,               /* gethostbyname */
   TRUE,                /* dns_qualify_single */
@@ -158,6 +172,14 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   NULL,                /* tls_verify_certificates */
   TRUE                 /* tls_tempfail_tryclear */
   #endif
   NULL,                /* tls_verify_certificates */
   TRUE                 /* tls_tempfail_tryclear */
   #endif
+  #ifdef EXPERIMENTAL_DOMAINKEYS
+ ,NULL,                /* dk_canon */
+  NULL,                /* dk_domain */
+  NULL,                /* dk_headers */
+  NULL,                /* dk_private_key */
+  NULL,                /* dk_selector */
+  NULL                 /* dk_strict */
+  #endif
 };
 
 
 };
 
 
@@ -291,10 +313,11 @@ host_build_hostlist(&(ob->fallback_hostlist), ob->fallback_hosts, FALSE);
 status means that an address is not currently being processed.
 
 Arguments:
 status means that an address is not currently being processed.
 
 Arguments:
-  addrlist     points to a chain of addresses
-  errno_value  to put in each address's errno field
-  msg          to put in each address's message field
-  rc           to put in each address's transport_return field
+  addrlist       points to a chain of addresses
+  errno_value    to put in each address's errno field
+  msg            to put in each address's message field
+  rc             to put in each address's transport_return field
+  pass_message   if TRUE, set the "pass message" flag in the address
 
 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
 
 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
@@ -304,7 +327,8 @@ Returns:       nothing
 */
 
 static
 */
 
 static
-void set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc)
+void set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
+  BOOL pass_message)
 {
 address_item *addr;
 int orvalue = 0;
 {
 address_item *addr;
 int orvalue = 0;
@@ -318,7 +342,11 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
   if (addr->transport_return < PENDING) continue;
   addr->basic_errno = errno_value;
   addr->more_errno |= orvalue;
   if (addr->transport_return < PENDING) continue;
   addr->basic_errno = errno_value;
   addr->more_errno |= orvalue;
-  if (msg != NULL) addr->message = msg;
+  if (msg != NULL)
+    {
+    addr->message = msg;
+    if (pass_message) setflag(addr, af_pass_message);
+    }
   addr->transport_return = rc;
   }
 }
   addr->transport_return = rc;
   }
 }
@@ -336,18 +364,19 @@ the yield variable. If no response was actually read, a suitable digit is
 chosen.
 
 Arguments:
 chosen.
 
 Arguments:
-  host         the current host, to get its name for messages
-  errno_value  pointer to the errno value
-  more_errno   from the top address for use with ERRNO_FILTER_FAIL
-  buffer       the SMTP response buffer
-  yield        where to put a one-digit SMTP response code
-  message      where to put an errror message
-
-Returns:       TRUE if an SMTP "QUIT" command should be sent, else FALSE
+  host           the current host, to get its name for messages
+  errno_value    pointer to the errno value
+  more_errno     from the top address for use with ERRNO_FILTER_FAIL
+  buffer         the SMTP response buffer
+  yield          where to put a one-digit SMTP response code
+  message        where to put an errror message
+  pass_message   set TRUE if message is an SMTP response
+
+Returns:         TRUE if an SMTP "QUIT" command should be sent, else FALSE
 */
 
 static BOOL check_response(host_item *host, int *errno_value, int more_errno,
 */
 
 static BOOL check_response(host_item *host, int *errno_value, int more_errno,
-  uschar *buffer, int *yield, uschar **message)
+  uschar *buffer, int *yield, uschar **message, BOOL *pass_message)
 {
 uschar *pl = US"";
 
 {
 uschar *pl = US"";
 
@@ -393,7 +422,7 @@ end the DATA. */
 if (*errno_value == ERRNO_FILTER_FAIL)
   {
   *message = US string_sprintf("transport filter process failed (%d)%s",
 if (*errno_value == ERRNO_FILTER_FAIL)
   {
   *message = US string_sprintf("transport filter process failed (%d)%s",
-    more_errno, 
+    more_errno,
     (more_errno == EX_EXECFAILED)? ": unable to execute command" : "");
   return FALSE;
   }
     (more_errno == EX_EXECFAILED)? ": unable to execute command" : "");
   return FALSE;
   }
@@ -422,8 +451,9 @@ if (*errno_value == ERRNO_WRITEINCOMPLETE)
 if (buffer[0] != 0)
   {
   uschar *s = string_printing(buffer);
 if (buffer[0] != 0)
   {
   uschar *s = string_printing(buffer);
-  *message = US string_sprintf("SMTP error from remote mailer after %s%s: "
+  *message = US string_sprintf("SMTP error from remote mail server after %s%s: "
     "host %s [%s]: %s", pl, smtp_command, host->name, host->address, s);
     "host %s [%s]: %s", pl, smtp_command, host->name, host->address, s);
+  *pass_message = TRUE;
   *yield = buffer[0];
   return TRUE;
   }
   *yield = buffer[0];
   return TRUE;
   }
@@ -601,7 +631,7 @@ while (count-- > 0)
     uschar *message = string_sprintf("SMTP timeout while connected to %s [%s] "
       "after RCPT TO:<%s>", host->name, host->address,
       transport_rcpt_address(addr, include_affixes));
     uschar *message = string_sprintf("SMTP timeout while connected to %s [%s] "
       "after RCPT TO:<%s>", host->name, host->address,
       transport_rcpt_address(addr, include_affixes));
-    set_errno(addrlist, save_errno, message, DEFER);
+    set_errno(addrlist, save_errno, message, DEFER, FALSE);
     retry_add_item(addr, addr->address_retry_key, 0);
     host->update_waiting = FALSE;
     return -1;
     retry_add_item(addr, addr->address_retry_key, 0);
     host->update_waiting = FALSE;
     return -1;
@@ -624,9 +654,10 @@ while (count-- > 0)
   else
     {
     addr->message =
   else
     {
     addr->message =
-      string_sprintf("SMTP error from remote mailer after RCPT TO:<%s>: "
+      string_sprintf("SMTP error from remote mail server after RCPT TO:<%s>: "
         "host %s [%s]: %s", transport_rcpt_address(addr, include_affixes),
         host->name, host->address, string_printing(buffer));
         "host %s [%s]: %s", transport_rcpt_address(addr, include_affixes),
         host->name, host->address, string_printing(buffer));
+    setflag(addr, af_pass_message);
     deliver_msglog("%s %s\n", tod_stamp(tod_log), addr->message);
 
     /* The response was 5xx */
     deliver_msglog("%s %s\n", tod_stamp(tod_log), addr->message);
 
     /* The response was 5xx */
@@ -677,8 +708,9 @@ if (pending_DATA != 0 &&
   {
   int code;
   uschar *msg;
   {
   int code;
   uschar *msg;
+  BOOL pass_message;
   if (pending_DATA > 0 || (yield & 1) != 0) return -3;
   if (pending_DATA > 0 || (yield & 1) != 0) return -3;
-  (void)check_response(host, &errno, 0, buffer, &code, &msg);
+  (void)check_response(host, &errno, 0, buffer, &code, &msg, &pass_message);
   DEBUG(D_transport) debug_printf("%s\nerror for DATA ignored: pipelining "
     "is in use and there were no good recipients\n", msg);
   }
   DEBUG(D_transport) debug_printf("%s\nerror for DATA ignored: pipelining "
     "is in use and there were no good recipients\n", msg);
   }
@@ -760,6 +792,7 @@ BOOL setting_up = TRUE;
 BOOL completed_address = FALSE;
 BOOL esmtp = TRUE;
 BOOL pending_MAIL;
 BOOL completed_address = FALSE;
 BOOL esmtp = TRUE;
 BOOL pending_MAIL;
+BOOL pass_message = FALSE;
 smtp_inblock inblock;
 smtp_outblock outblock;
 int max_rcpt = tblock->max_addresses;
 smtp_inblock inblock;
 smtp_outblock outblock;
 int max_rcpt = tblock->max_addresses;
@@ -800,7 +833,7 @@ if (helo_data == NULL)
   {
   uschar *message = string_sprintf("failed to expand helo_data: %s",
     expand_string_message);
   {
   uschar *message = string_sprintf("failed to expand helo_data: %s",
     expand_string_message);
-  set_errno(addrlist, 0, message, DEFER);
+  set_errno(addrlist, 0, message, DEFER, FALSE);
   return ERROR;
   }
 
   return ERROR;
   }
 
@@ -820,7 +853,7 @@ if (ob->authenticated_sender != NULL)
       {
       uschar *message = string_sprintf("failed to expand "
         "authenticated_sender: %s", expand_string_message);
       {
       uschar *message = string_sprintf("failed to expand "
         "authenticated_sender: %s", expand_string_message);
-      set_errno(addrlist, 0, message, DEFER);
+      set_errno(addrlist, 0, message, DEFER, FALSE);
       return ERROR;
       }
     }
       return ERROR;
       }
     }
@@ -839,7 +872,7 @@ if (continue_hostname == NULL)
   if (inblock.sock < 0)
     {
     set_errno(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno,
   if (inblock.sock < 0)
     {
     set_errno(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno,
-      NULL, DEFER);
+      NULL, DEFER, FALSE);
     return DEFER;
     }
 
     return DEFER;
     }
 
@@ -998,8 +1031,11 @@ if (tls_offered && !suppress_tls &&
 
     for (addr = addrlist; addr != NULL; addr = addr->next)
       {
 
     for (addr = addrlist; addr != NULL; addr = addr->next)
       {
-      addr->cipher = tls_cipher;
-      addr->peerdn = tls_peerdn;
+      if (addr->transport_return == PENDING_DEFER)
+        {
+        addr->cipher = tls_cipher;
+        addr->peerdn = tls_peerdn;
+        }
       }
     }
   }
       }
     }
   }
@@ -1161,7 +1197,7 @@ if (continue_hostname == NULL
 
             case ERROR:
             yield = ERROR;
 
             case ERROR:
             yield = ERROR;
-            set_errno(addrlist, 0, string_copy(buffer), DEFER);
+            set_errno(addrlist, 0, string_copy(buffer), DEFER, FALSE);
             goto SEND_QUIT;
             }
 
             goto SEND_QUIT;
             }
 
@@ -1177,7 +1213,8 @@ if (continue_hostname == NULL
     {
     yield = DEFER;
     set_errno(addrlist, ERRNO_AUTHFAIL,
     {
     yield = DEFER;
     set_errno(addrlist, ERRNO_AUTHFAIL,
-      string_sprintf("authentication required but %s", fail_reason), DEFER);
+      string_sprintf("authentication required but %s", fail_reason), DEFER,
+      FALSE);
     goto SEND_QUIT;
     }
   }
     goto SEND_QUIT;
     }
   }
@@ -1203,7 +1240,8 @@ if (tblock->filter_command != NULL)
 
   if (!rc)
     {
 
   if (!rc)
     {
-    set_errno(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER);
+    set_errno(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
+      FALSE);
     yield = ERROR;
     goto SEND_QUIT;
     }
     yield = ERROR;
     goto SEND_QUIT;
     }
@@ -1343,7 +1381,8 @@ if (mua_wrapper)
     }
   if (badaddr != NULL)
     {
     }
   if (badaddr != NULL)
     {
-    set_errno(addrlist, 0, badaddr->message, FAIL);
+    set_errno(addrlist, 0, badaddr->message, FAIL,
+      testflag(badaddr, af_pass_message));
     ok = FALSE;
     }
   }
     ok = FALSE;
     }
   }
@@ -1394,6 +1433,23 @@ if (!ok) ok = TRUE; else
   DEBUG(D_transport|D_v)
     debug_printf("  SMTP>> writing message and terminating \".\"\n");
   transport_count = 0;
   DEBUG(D_transport|D_v)
     debug_printf("  SMTP>> writing message and terminating \".\"\n");
   transport_count = 0;
+#ifdef EXPERIMENTAL_DOMAINKEYS
+  if ( (ob->dk_private_key != NULL) && (ob->dk_selector != NULL) )
+    ok = dk_transport_write_message(addrlist, inblock.sock,
+      topt_use_crlf | topt_end_dot | topt_escape_headers |
+        (tblock->body_only? topt_no_headers : 0) |
+        (tblock->headers_only? topt_no_body : 0) |
+        (tblock->return_path_add? topt_add_return_path : 0) |
+        (tblock->delivery_date_add? topt_add_delivery_date : 0) |
+        (tblock->envelope_to_add? topt_add_envelope_to : 0),
+      0,            /* No size limit */
+      tblock->add_headers, tblock->remove_headers,
+      US".", US"..",    /* Escaping strings */
+      tblock->rewrite_rules, tblock->rewrite_existflags,
+      ob->dk_private_key, ob->dk_domain, ob->dk_selector,
+      ob->dk_canon, ob->dk_headers, ob->dk_strict);
+  else
+#endif
   ok = transport_write_message(addrlist, inblock.sock,
     topt_use_crlf | topt_end_dot | topt_escape_headers |
       (tblock->body_only? topt_no_headers : 0) |
   ok = transport_write_message(addrlist, inblock.sock,
     topt_use_crlf | topt_end_dot | topt_escape_headers |
       (tblock->body_only? topt_no_headers : 0) |
@@ -1555,7 +1611,7 @@ if (!ok)
   save_errno = errno;
   message = NULL;
   send_quit = check_response(host, &save_errno, addrlist->more_errno,
   save_errno = errno;
   message = NULL;
   send_quit = check_response(host, &save_errno, addrlist->more_errno,
-    buffer, &code, &message);
+    buffer, &code, &message, &pass_message);
   goto FAILED;
 
   SEND_FAILED:
   goto FAILED;
 
   SEND_FAILED:
@@ -1590,11 +1646,11 @@ if (!ok)
     {
     if (code == '5')
       {
     {
     if (code == '5')
       {
-      set_errno(addrlist, save_errno, message, FAIL);
+      set_errno(addrlist, save_errno, message, FAIL, pass_message);
       }
     else
       {
       }
     else
       {
-      set_errno(addrlist, save_errno, message, DEFER);
+      set_errno(addrlist, save_errno, message, DEFER, pass_message);
       yield = DEFER;
       }
     }
       yield = DEFER;
       }
     }
@@ -1620,7 +1676,7 @@ if (!ok)
     {
     yield = (save_errno == ERRNO_CHHEADER_FAIL ||
              save_errno == ERRNO_FILTER_FAIL)? ERROR : DEFER;
     {
     yield = (save_errno == ERRNO_CHHEADER_FAIL ||
              save_errno == ERRNO_FILTER_FAIL)? ERROR : DEFER;
-    set_errno(addrlist, save_errno, message, DEFER);
+    set_errno(addrlist, save_errno, message, DEFER, pass_message);
     }
 
   /* Otherwise we have a message-specific error response from the remote
     }
 
   /* Otherwise we have a message-specific error response from the remote
@@ -1641,7 +1697,8 @@ if (!ok)
     {
     if (mua_wrapper) code = '5';  /* Force hard failure in wrapper mode */
 
     {
     if (mua_wrapper) code = '5';  /* Force hard failure in wrapper mode */
 
-    set_errno(addrlist, save_errno, message, (code == '5')? FAIL : DEFER);
+    set_errno(addrlist, save_errno, message, (code == '5')? FAIL : DEFER,
+      pass_message);
 
     /* If there's an errno, the message contains just the identity of
     the host. */
 
     /* If there's an errno, the message contains just the identity of
     the host. */
@@ -1705,6 +1762,7 @@ if (completed_address && ok && send_quit)
         ))
     {
     uschar *msg;
         ))
     {
     uschar *msg;
+    BOOL pass_message;
 
     if (send_rset)
       {
 
     if (send_rset)
       {
@@ -1718,7 +1776,8 @@ if (completed_address && ok && send_quit)
                   ob->command_timeout)))
         {
         int code;
                   ob->command_timeout)))
         {
         int code;
-        send_quit = check_response(host, &errno, 0, buffer, &code, &msg);
+        send_quit = check_response(host, &errno, 0, buffer, &code, &msg,
+          &pass_message);
         if (!send_quit)
           {
           DEBUG(D_transport) debug_printf("%s\n", msg);
         if (!send_quit)
           {
           DEBUG(D_transport) debug_printf("%s\n", msg);
@@ -1764,7 +1823,7 @@ if (completed_address && ok && send_quit)
 
     /* If RSET failed and there are addresses left, they get deferred. */
 
 
     /* If RSET failed and there are addresses left, they get deferred. */
 
-    else set_errno(first_addr, errno, msg, DEFER);
+    else set_errno(first_addr, errno, msg, DEFER, FALSE);
     }
   }
 
     }
   }
 
@@ -1929,7 +1988,7 @@ int hosts_looked_up = 0;
 int hosts_retry = 0;
 int hosts_serial = 0;
 int hosts_total = 0;
 int hosts_retry = 0;
 int hosts_serial = 0;
 int hosts_total = 0;
-int total_hosts_tried = 0; 
+int total_hosts_tried = 0;
 address_item *addr;
 BOOL expired = TRUE;
 BOOL continuing = continue_hostname != NULL;
 address_item *addr;
 BOOL expired = TRUE;
 BOOL continuing = continue_hostname != NULL;
@@ -2096,8 +2155,8 @@ if (Ustrcmp(pistring, ":25") == 0) pistring = US"";
 .  If there are any addresses whose status is still DEFER, carry on to the
    next host/IPaddress, unless we have tried the number of hosts given
    by hosts_max_try or hosts_max_try_hardlimit; otherwise return. Note that
 .  If there are any addresses whose status is still DEFER, carry on to the
    next host/IPaddress, unless we have tried the number of hosts given
    by hosts_max_try or hosts_max_try_hardlimit; otherwise return. Note that
-   there is some fancy logic for hosts_max_try that means its limit can be 
-   overstepped in some circumstances. 
+   there is some fancy logic for hosts_max_try that means its limit can be
+   overstepped in some circumstances.
 
 If we get to the end of the list, all hosts have deferred at least one address,
 or not reached their retry times. If delay_after_cutoff is unset, it requests a
 
 If we get to the end of the list, all hosts have deferred at least one address,
 or not reached their retry times. If delay_after_cutoff is unset, it requests a
@@ -2114,7 +2173,7 @@ for (cutoff_retry = 0; expired &&
   int unexpired_hosts_tried = 0;
 
   for (host = hostlist;
   int unexpired_hosts_tried = 0;
 
   for (host = hostlist;
-       host != NULL && 
+       host != NULL &&
          unexpired_hosts_tried < ob->hosts_max_try &&
          total_hosts_tried < ob->hosts_max_try_hardlimit;
        host = nexthost)
          unexpired_hosts_tried < ob->hosts_max_try &&
          total_hosts_tried < ob->hosts_max_try_hardlimit;
        host = nexthost)
@@ -2134,7 +2193,8 @@ for (cutoff_retry = 0; expired &&
     uschar *serialize_key = NULL;
 
     /* Default next host is next host. :-) But this can vary if the
     uschar *serialize_key = NULL;
 
     /* Default next host is next host. :-) But this can vary if the
-    hosts_max_try limit is hit (see below). */
+    hosts_max_try limit is hit (see below). It may also be reset if a host
+    address is looked up here (in case the host was multihomed). */
 
     nexthost = host->next;
 
 
     nexthost = host->next;
 
@@ -2244,6 +2304,11 @@ for (cutoff_retry = 0; expired &&
       continue;      /* With next host */
       }
 
       continue;      /* With next host */
       }
 
+    /* Reset the default next host in case a multihomed host whose addresses
+    are not looked up till just above added to the host list. */
+
+    nexthost = host->next;
+
     /* If queue_smtp is set (-odqs or the first part of a 2-stage run), or the
     domain is in queue_smtp_domains, we don't actually want to attempt any
     deliveries. When doing a queue run, queue_smtp_domains is always unset. If
     /* If queue_smtp is set (-odqs or the first part of a 2-stage run), or the
     domain is in queue_smtp_domains, we don't actually want to attempt any
     deliveries. When doing a queue run, queue_smtp_domains is always unset. If
@@ -2401,7 +2466,7 @@ for (cutoff_retry = 0; expired &&
     if (dont_deliver)
       {
       host_item *host2;
     if (dont_deliver)
       {
       host_item *host2;
-      set_errno(addrlist, 0, NULL, OK);
+      set_errno(addrlist, 0, NULL, OK, FALSE);
       for (addr = addrlist; addr != NULL; addr = addr->next)
         {
         addr->host_used = host;
       for (addr = addrlist; addr != NULL; addr = addr->next)
         {
         addr->host_used = host;
@@ -2421,9 +2486,9 @@ for (cutoff_retry = 0; expired &&
 
     /* This is for real. If the host is expired, we don't count it for
     hosts_max_retry. This ensures that all hosts must expire before an address
 
     /* This is for real. If the host is expired, we don't count it for
     hosts_max_retry. This ensures that all hosts must expire before an address
-    is timed out, unless hosts_max_try_hardlimit (which protects against 
+    is timed out, unless hosts_max_try_hardlimit (which protects against
     lunatic DNS configurations) is reached.
     lunatic DNS configurations) is reached.
-    
+
     If the host is not expired and we are about to hit the hosts_max_retry
     limit, check to see if there is a subsequent hosts with a different MX
     value. If so, make that the next host, and don't count this one. This is a
     If the host is not expired and we are about to hit the hosts_max_retry
     limit, check to see if there is a subsequent hosts with a different MX
     value. If so, make that the next host, and don't count this one. This is a
@@ -2686,7 +2751,7 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
   because of hosts_max_try or hosts_max_try_hardlimit. In the former case, this
   means we need to behave as if some hosts were skipped because their retry
   time had not come. Specifically, this prevents the address from timing out.
   because of hosts_max_try or hosts_max_try_hardlimit. In the former case, this
   means we need to behave as if some hosts were skipped because their retry
   time had not come. Specifically, this prevents the address from timing out.
-  However, if we have hit hosts_max_try_hardlimit, we want to behave as if all 
+  However, if we have hit hosts_max_try_hardlimit, we want to behave as if all
   hosts were tried. */
 
   if (host != NULL)
   hosts were tried. */
 
   if (host != NULL)
@@ -2698,11 +2763,11 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
           "hosts were tried\n");
       }
     else
           "hosts were tried\n");
       }
     else
-      {       
+      {
       DEBUG(D_transport)
         debug_printf("hosts_max_try limit caused some hosts to be skipped\n");
       setflag(addr, af_retry_skipped);
       DEBUG(D_transport)
         debug_printf("hosts_max_try limit caused some hosts to be skipped\n");
       setflag(addr, af_retry_skipped);
-      } 
+      }
     }
 
   if (queue_smtp)    /* no deliveries attempted */
     }
 
   if (queue_smtp)    /* no deliveries attempted */