]> Pileus Git - ~andy/fetchmail/commitdiff
Revised dup-killer code.
authorEric S. Raymond <esr@thyrsus.com>
Fri, 14 Dec 2001 08:37:11 +0000 (08:37 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Fri, 14 Dec 2001 08:37:11 +0000 (08:37 -0000)
svn path=/trunk/; revision=3561

NEWS
fetchmail.h
transact.c

diff --git a/NEWS b/NEWS
index 5b5f010e4db9779b8b924f09533a435d059ba0d8..71d4baeb6e156d97244344b584d8cba521c7dec3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@
 * Documented known IDLE bug in the todo.html file.
 * Sunil Shetye's fix for a timeout/reconnect bug.
 * LMTP fix from Toshiro HIKITA <toshi@sodan.org>.
+* The duplicate-killer doesn't try to operate if we can get an actual
+  recipient address from the trace headers.
 
 fetchmail-5.9.5 (Thu Nov  8 14:14:35 EST 2001), 21162 lines:
 
index 463446275773c0e51f05ffc7b73cddfe51eed598..4ed413e8284f83d464233eccb5b23b4ff98b71e5 100644 (file)
@@ -308,6 +308,7 @@ struct query
     struct idlist *skipped;    /* messages skipped on the mail server */
     struct idlist *oldsaved, *newsaved;
     char *lastid;              /* last Message-ID seen on this connection */
+    char *thisid;              /* Message-ID of current message */
 
     /* internal use -- per-message state */
     int mimemsg;               /* bitmask indicating MIME body-type */
index 4ad9e799c8fd4717dcde5ac275746fed8f709ddc..c6387e3ca32e1134417d9dbdcd40194494e95cc1 100644 (file)
@@ -377,6 +377,11 @@ int readheaders(int sock,
     if (msgblk.headers)
        free(msgblk.headers);
 
+    /* initially, no message ID */
+    if (ctl->thisid)
+       free(ctl->thisid);
+    ctl->thisid = NULL;
+
     msgblk.headers = received_for = delivered_to = NULL;
     from_offs = reply_to_offs = resent_from_offs = app_from_offs = 
        sender_offs = resent_sender_offs = env_offs = -1;
@@ -514,44 +519,9 @@ int readheaders(int sock,
        /* we see an ordinary (non-header, non-message-delimiter line */
        has_nuls = (linelen != strlen(line));
 
-       /*
-        * When mail delivered to a multidrop mailbox on the server is
-        * addressed to multiple people on the client machine, there
-        * will be one copy left in the box for each recipient.  Thus,
-        * if the mail is addressed to N people, each recipient will
-        * get N copies.  This is bad when N > 1.
-        *
-        * Foil this by suppressing all but one copy of a message with
-        * a given Message-ID.  The accept_count test ensures that
-        * multiple pieces of email with the same Message-ID, each
-        * with a *single* addressee (the N == 1 case), won't be 
-        * suppressed.
-        *
-        * Note: This implementation only catches runs of successive
-        * messages with the same ID, but that should be good
-        * enough. A more general implementation would have to store
-        * ever-growing lists of seen message-IDs; in a long-running
-        * daemon this would turn into a memory leak even if the 
-        * implementation were perfect.
-        * 
-        * Don't mess with this code casually.  It would be way too easy
-        * to break it in a way that blackholed mail.  Better to pass
-        * the occasional duplicate than to do that...
-        */
+       /* save the message's ID, we may use it for killing duplicates later */
        if (MULTIDROP(ctl) && !strncasecmp(line, "Message-ID:", 11))
-       {
-           if (ctl->lastid && !strcasecmp(ctl->lastid, line))
-           {
-               if (accept_count > 1)
-                   return(PS_REFUSED);
-           }
-           else
-           {
-               if (ctl->lastid)
-                   free(ctl->lastid);
-               ctl->lastid = xstrdup(line);
-           }
-       }
+           ctl->thisid = xstrdup(line);
 
        /*
         * The University of Washington IMAP server (the reference
@@ -811,7 +781,52 @@ int readheaders(int sock,
        }
     }
 
- process_headers:
+ process_headers:    
+    /*
+     * When mail delivered to a multidrop mailbox on the server is
+     * addressed to multiple people on the client machine, there will
+     * be one copy left in the box for each recipient.  This is not a
+     * problem if we have the actual recipient address to dispatch on
+     * (e.g. because we've mined it out of sendmail trace headers, or
+     * a qmail Delivered-To line, or a declared sender envelope line).
+     *
+     * But if we're mining addressees out of the To/Cc/Bcc fields, and
+     * if the mail is addressed to N people, each recipient will
+     * get N copies.  This is bad when N > 1.
+     *
+     * Foil this by suppressing all but one copy of a message with
+     * a given Message-ID.  The accept_count test ensures that
+     * multiple pieces of email with the same Message-ID, each
+     * with a *single* addressee (the N == 1 case), won't be 
+     * suppressed.
+     *
+     * Note: This implementation only catches runs of successive
+     * messages with the same ID, but that should be good
+     * enough. A more general implementation would have to store
+     * ever-growing lists of seen message-IDs; in a long-running
+     * daemon this would turn into a memory leak even if the 
+     * implementation were perfect.
+     * 
+     * Don't mess with this code casually.  It would be way too easy
+     * to break it in a way that blackholed mail.  Better to pass
+     * the occasional duplicate than to do that...
+     */
+    if (!received_for && env_offs == -1 && !delivered_to)
+    {
+       if (ctl->lastid && ctl->thisid && !strcasecmp(ctl->lastid, ctl->thisid))
+       {
+           if (accept_count > 1)
+               return(PS_REFUSED);
+       }
+       else
+       {
+           if (ctl->lastid)
+               free(ctl->lastid);
+           ctl->lastid = ctl->thisid;
+           ctl->thisid = NULL;
+       }
+    }
+
     /*
      * We want to detect this early in case there are so few headers that the
      * dispatch logic barfs.