[exim] Re: Bug in Exim - duplicating messages

Top Page
Delete this message
Reply to this message
Author: Russell Stuart
Date:  
To: exim-users
Subject: [exim] Re: Bug in Exim - duplicating messages
On Sat, 2005-02-26 at 15:55, Russell Stuart wrote:
> > The conditions trigger the bug are:
> >
> > 1.  A new address is added with a redirect router with the unseen
> >     directive.

> >
> > 2. There is a retry record pending for new address.
> >
> > 3.  The new address is moved to the front of deliver.c's delivery
> >     queue by another re-direct router.

> >
> > 4.  A "control = queue_only" is in effect (perhaps - not sure about
> >     this one).

> >
> > 5. The original address can be successfully delivered to.
> >
> > If all these conditions are met, then each time a queue running
> > comes along, it will create a duplicate email to original
> > address. This will happen until the retry record expires.
>
>
> Here is a patch that fixes the problem:
>


Well, it did fix the original problem, but it also introduced a new
one. Hopefully the patch below does the job properly. No doubt
others will review this code - if you find a problem let me know as
I have deployed it!

BTW, the trigger for the bug is simpler than what I described above.
The trigger is:

1.  A message with several recipients that can be batched through
    a local transport (any local transport).


2.  The first message on the deliver.c queue has a retry item
    outstanding.


In that case, every queue runner that comes along will do a
delivery to remaining recipients on that local transport,
regardless of whether a delivery has been done to that
recipient or not. This will continue until the retry item
expires.

Debian users can find a version of exim with the bug fixed here:
http://www.lubemobile.com.au/ras/debian/sarge/exim4

diff -Nur exim4-4.44.keep/src/deliver.c exim4-4.44/src/deliver.c
--- exim4-4.44.keep/src/deliver.c    2005-02-27 08:35:12.000000000 +1000
+++ exim4-4.44/src/deliver.c    2005-02-27 09:54:29.000000000 +1000
@@ -2081,6 +2081,21 @@
          (addr->host_list != NULL && next->host_list != NULL &&
           Ustrcmp(addr->host_list->name, next->host_list->name) == 0));


+      /* Ensure it hasn't been delivered */
+      if (ok)
+    {
+    (void)string_format(big_buffer, big_buffer_size, "%s/%s",
+      next->unique + (testflag(next, af_homonym)? 3:0),
+      next->transport->name);
+    if (tree_search(tree_nonrecipients, big_buffer) != 0)
+      {
+      ok = 0;
+      DEBUG(D_deliver|D_transport)
+        debug_printf("Can't batch %s as it has been delivered\n",
+        big_buffer);
+      }
+    }
+
       /* If the transport has a batch_id setting, batch_id will be non-NULL
       from the expansion outside the loop. Expand for this address and compare.
       Expansion failure makes this address ineligible for batching. */