Fix too-often retry bug after 4xx with more hosts than hosts_max_retry.
[exim.git] / src / src / deliver.c
index d4051768ea67443f127cc0362aaab493b7c50416..81df0e0832187651fab01a3b29710ef0cf41b42a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/deliver.c,v 1.34 2006/06/30 15:36:08 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
@@ -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)