Routing: avoid doing the one_time replacement operation when a redirect leaves the...
authorJeremy Harris <jgh146exb@wizmail.org>
Thu, 22 Sep 2016 18:59:48 +0000 (19:59 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Thu, 22 Sep 2016 19:05:17 +0000 (20:05 +0100)
When done, in combination with a defer the retry would see the address as delivered, hence losing mail.

doc/doc-txt/ChangeLog
src/src/deliver.c
src/src/routers/redirect.c

index f2000b5d4498eb4ff7d88e874fee782ff2674eb1..b920d92cc5c7769d8556094e3e21a0a070aae415 100644 (file)
@@ -94,6 +94,11 @@ JH/25 Decoding ACL controls is now done using a binary search; the sourcecode
       takes up less space and should be simpler to maintain.  Merge the ACL
       condition decode tables also, with similar effect.
 
       takes up less space and should be simpler to maintain.  Merge the ACL
       condition decode tables also, with similar effect.
 
+JH/26 Fix problem with one_time used on a redirect router which returned the
+      parent address unchanged.  A retry would see the parent address marked as
+      delivered, so not attempt the (identical) child.  As a result mail would
+      be lost.
+
 
 Exim version 4.87
 -----------------
 
 Exim version 4.87
 -----------------
index dc616a1db8dd5b989618c132f24a294bd17e9daf..72405da390b1db179d88901b749d9d79fd9a519d 100644 (file)
@@ -7867,10 +7867,12 @@ else if (addr_defer != (address_item *)(+1))
         }
 
       /* Didn't find the address already in the list, and did find the
         }
 
       /* Didn't find the address already in the list, and did find the
-      ultimate parent's address in the list. After adding the recipient,
+      ultimate parent's address in the list, and they really are different
+      (i.e. not from an identity-redirect). After adding the recipient,
       update the errors address in the recipients list. */
 
       update the errors address in the recipients list. */
 
-      if (i >= recipients_count && t < recipients_count)
+      if (  i >= recipients_count && t < recipients_count
+         && Ustrcmp(otaddr->address, otaddr->parent->address) != 0)
         {
         DEBUG(D_deliver) debug_printf("one_time: adding %s in place of %s\n",
           otaddr->address, otaddr->parent->address);
         {
         DEBUG(D_deliver) debug_printf("one_time: adding %s in place of %s\n",
           otaddr->address, otaddr->parent->address);
@@ -7885,19 +7887,14 @@ else if (addr_defer != (address_item *)(+1))
     this deferred address or, if there is none, the sender address, is on the
     list of recipients for a warning message. */
 
     this deferred address or, if there is none, the sender address, is on the
     list of recipients for a warning message. */
 
-    if (sender_address[0] != 0)
-      if (addr->prop.errors_address)
-        {
-        if (Ustrstr(recipients, addr->prop.errors_address) == NULL)
-          recipients = string_sprintf("%s%s%s", recipients,
-            (recipients[0] == 0)? "" : ",", addr->prop.errors_address);
-        }
-      else
-        {
-        if (Ustrstr(recipients, sender_address) == NULL)
-          recipients = string_sprintf("%s%s%s", recipients,
-            (recipients[0] == 0)? "" : ",", sender_address);
-        }
+    if (sender_address[0])
+      {
+      uschar * s = addr->prop.errors_address;
+      if (!s) s = sender_address;
+      if (Ustrstr(recipients, s) == NULL)
+       recipients = string_sprintf("%s%s%s", recipients,
+         recipients[0] ? "," : "", s);
+      }
     }
 
   /* Send a warning message if the conditions are right. If the condition check
     }
 
   /* Send a warning message if the conditions are right. If the condition check
index 2434d3cb752f3ae492c57608a6f8c68d4a3b70a0..8aad1d4abd4fa1ac391e3f0f788486f10c567076 100644 (file)
@@ -325,7 +325,7 @@ add_generated(router_instance *rblock, address_item **addr_new,
 redirect_router_options_block *ob =
   (redirect_router_options_block *)(rblock->options_block);
 
 redirect_router_options_block *ob =
   (redirect_router_options_block *)(rblock->options_block);
 
-while (generated != NULL)
+while (generated)
   {
   address_item *parent;
   address_item *next = generated;
   {
   address_item *parent;
   address_item *next = generated;
@@ -347,7 +347,7 @@ while (generated != NULL)
 
   if (ob->one_time && !queue_2stage)
     {
 
   if (ob->one_time && !queue_2stage)
     {
-    for (parent = addr; parent->parent != NULL; parent = parent->parent);
+    for (parent = addr; parent->parent; parent = parent->parent) ;
     next->onetime_parent = parent->address;
     }
 
     next->onetime_parent = parent->address;
     }
 
@@ -358,21 +358,16 @@ while (generated != NULL)
   unless the ancestor was routed by a case-sensitive router. */
 
   if (ob->check_ancestor)
   unless the ancestor was routed by a case-sensitive router. */
 
   if (ob->check_ancestor)
-    {
-    for (parent = addr; parent != NULL; parent = parent->parent)
-      {
-      if (((parent->router != NULL && parent->router->caseful_local_part)?
-           Ustrcmp(next->address, parent->address)
-           :
-           strcmpic(next->address, parent->address)
+    for (parent = addr; parent; parent = parent->parent)
+      if ((parent->router && parent->router->caseful_local_part
+          ? Ustrcmp(next->address, parent->address)
+           : strcmpic(next->address, parent->address)
           ) == 0)
         {
         DEBUG(D_route) debug_printf("generated parent replaced by child\n");
         next->address = string_copy(addr->address);
         break;
         }
           ) == 0)
         {
         DEBUG(D_route) debug_printf("generated parent replaced by child\n");
         next->address = string_copy(addr->address);
         break;
         }
-      }
-    }
 
   /* A user filter may, under some circumstances, set up an errors address.
   If so, we must take care to re-instate it when we copy in the propagated
 
   /* A user filter may, under some circumstances, set up an errors address.
   If so, we must take care to re-instate it when we copy in the propagated