Fix too-often retry bug after 4xx with more hosts than hosts_max_retry.
[exim.git] / src / src / deliver.c
index 4d3882520f0c83c37df52ded5f188d5473e83307..81df0e0832187651fab01a3b29710ef0cf41b42a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/deliver.c,v 1.33 2006/06/30 14:14:46 ph10 Exp $ */
+/* $Cambridge: exim/src/src/deliver.c,v 1.37 2006/10/30 16:41:04 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1433,10 +1433,10 @@ int rc = OK;
 int size_limit;
 
 deliver_set_expansions(addr);
-size_limit = expand_string_integer(tp->message_size_limit);
+size_limit = expand_string_integer(tp->message_size_limit, TRUE);
 deliver_set_expansions(NULL);
 
-if (size_limit < 0)
+if (expand_string_message != NULL)
   {
   rc = DEFER;
   if (size_limit == -1)
@@ -2328,8 +2328,13 @@ while (addr_local != NULL)
                 retry_record->more_errno);
 
             DEBUG(D_deliver|D_retry)
+              {
               debug_printf("retry time not reached for %s: "
                 "checking ultimate address timeout\n", addr2->address);
+              debug_printf("  now=%d first_failed=%d next_try=%d expired=%d\n",
+                (int)now, (int)retry_record->first_failed,
+                (int)retry_record->next_try, retry_record->expired);
+              }
 
             if (retry != NULL && retry->rules != NULL)
               {
@@ -2338,9 +2343,8 @@ while (addr_local != NULL)
                    last_rule->next != NULL;
                    last_rule = last_rule->next);
               DEBUG(D_deliver|D_retry)
-                debug_printf("now=%d received_time=%d diff=%d timeout=%d\n",
-                  (int)now, received_time, (int)now - received_time,
-                  last_rule->timeout);
+                debug_printf("  received_time=%d diff=%d timeout=%d\n",
+                  received_time, (int)now - received_time, last_rule->timeout);
               if (now - received_time > last_rule->timeout) ok = TRUE;
               }
             else
@@ -4372,13 +4376,13 @@ while (*s != 0)
 /* This function was introduced when the test for duplicate addresses that are
 not pipes, files, or autoreplies was moved from the middle of routing to when
 routing was complete. That was to fix obscure cases when the routing history
-affects the subsequent routing of identical addresses.
+affects the subsequent routing of identical addresses. This function is called
+after routing, to check that the final routed addresses are not duplicates.
 
-This function is called after routing, to check that the final routed addresses
-are not duplicates. If we detect a duplicate, we remember what it is a
-duplicate of. Note that pipe, file, and autoreply de-duplication is handled
-during routing, so we must leave such "addresses" alone here, as otherwise they
-will incorrectly be discarded.
+If we detect a duplicate, we remember what it is a duplicate of. Note that
+pipe, file, and autoreply de-duplication is handled during routing, so we must
+leave such "addresses" alone here, as otherwise they will incorrectly be
+discarded.
 
 Argument:     address of list anchor
 Returns:      nothing
@@ -5499,19 +5503,29 @@ while (addr_new != NULL)           /* Loop until all addresses dealt with */
       (void)post_process_one(addr, DEFER, LOG_MAIN, DTYPE_ROUTER, 0);
       }
 
-    /* If queue_running, defer routing unless no retry data or we've
-    passed the next retry time, or this message is forced. However,
-    if the retry time has expired, allow the routing attempt.
-    If it fails again, the address will be failed. This ensures that
+    /* If we are in a queue run, defer routing unless there is no retry data or
+    we've passed the next retry time, or this message is forced. In other
+    words, ignore retry data when not in a queue run.
+
+    However, if the domain retry time has expired, always allow the routing
+    attempt. If it fails again, the address will be failed. This ensures that
     each address is routed at least once, even after long-term routing
     failures.
 
     If there is an address retry, check that too; just wait for the next
     retry time. This helps with the case when the temporary error on the
     address was really message-specific rather than address specific, since
-    it allows other messages through. */
+    it allows other messages through.
+
+    We also wait for the next retry time if this is a message sent down an
+    existing SMTP connection (even though that will be forced). Otherwise there
+    will be far too many attempts for an address that gets a 4xx error. In
+    fact, after such an error, we should not get here because, the host should
+    not be remembered as one this message needs. However, there was a bug that
+    used to cause this to  happen, so it is best to be on the safe side. */
 
-    else if (!deliver_force && queue_running &&
+    else if (((queue_running && !deliver_force) || continue_hostname != NULL)
+            &&
             ((domain_retry_record != NULL &&
               now < domain_retry_record->next_try &&
               !domain_retry_record->expired)