]> Pileus Git - ~andy/fetchmail/commitdiff
fetchmail workaround for a bug in Microsoft Exchange
authorSunil Shetye <sunilshetye@rocketmail.com>
Wed, 9 May 2012 08:10:12 +0000 (13:40 +0530)
committerMatthias Andree <matthias.andree@gmx.de>
Tue, 15 May 2012 06:45:20 +0000 (08:45 +0200)
treat missing header in response to a FETCH command as a transient error
(Reported by John Connett)

if there are too many transient errors, log it.

NEWS
driver.c
imap.c
tunable.h

diff --git a/NEWS b/NEWS
index cd7ce1855308e9891bd9b10c3093564e21f28737..172223e67869b9d664b8d1036f51c0ba6e5b8385 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -123,6 +123,12 @@ NOTE THIS IS AN ALPHA RELEASE THAT HAS NOT BEEN THOROUGHLY TESTED!
   offered by the server before we resort to sending the password as clear text.
 
 --------------------------------------------------------------------------------
+fetchmail-6.3.22 (not yet released):
+* Some servers, notably Microsoft Exchange, return "A0009 OK FETCH completed."
+  without any header in response to a header request for meeting reminder
+  messages (with a "meeting.ics" attachment). fetchmail now treats these as
+  transient errors.  Report by John Connett, Patch by Sunil Shetye.
+
 
 fetchmail-6.3.21 (not yet released):
 
index a665e652fea6b81a62539a2d6944eb16382c5cb4..a6a18754efd550628d292c444ffa767bcb5a5752 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -352,7 +352,8 @@ static int eat_trailer(int sock, struct query *ctl)
 
 static int fetch_messages(int mailserver_socket, struct query *ctl, 
                          int count, int **msgsizes, int maxfetch,
-                         int *fetches, int *dispatches, int *deletions)
+                         int *fetches, int *dispatches, int *deletions,
+                         int *transient_errors)
 /* fetch messages in lockstep mode */
 {
     flag force_retrieval;
@@ -526,6 +527,7 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
                             GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
                             ctl->remotename, ctl->server.truename, num,
                             msgsize);
+               (*transient_errors)++;
                continue;
            }
            else if (err != 0)
@@ -567,7 +569,10 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
            if (err == PS_RETAINED)
                suppress_forward = suppress_delete = retained = TRUE;
            else if (err == PS_TRANSIENT)
+           {
                suppress_delete = suppress_forward = TRUE;
+               (*transient_errors)++;
+           }
            else if (err == PS_REFUSED)
                suppress_forward = TRUE;
            else if (err)
@@ -664,7 +669,10 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
                              len);
 
                if (err == PS_TRANSIENT)
+               {
                    suppress_delete = suppress_forward = TRUE;
+                   (*transient_errors)++;
+               }
                else if (err)
                    return(err);
 
@@ -890,7 +898,7 @@ static int do_session(
        /* sigsetjmp returned zero -> normal operation */
        char buf[MSGBUFSIZE+1], *realhost;
        int count, newm, bytes;
-       int fetches, dispatches, oldphase;
+       int fetches, dispatches, transient_errors, oldphase;
        struct idlist *idp;
 
        /* execute pre-initialization command, if any */
@@ -1235,6 +1243,7 @@ is restored."));
            pass = 0;
            do {
                dispatches = 0;
+               transient_errors = 0;
                ++pass;
 
                /* reset timeout, in case we did an IDLE */
@@ -1364,10 +1373,20 @@ is restored."));
                    err = fetch_messages(mailserver_socket, ctl, 
                                         count, &msgsizes,
                                         maxfetch,
-                                        &fetches, &dispatches, &deletions);
+                                        &fetches, &dispatches, &deletions,
+                                        &transient_errors);
                    if (err != PS_SUCCESS && err != PS_MAXFETCH)
                        goto cleanUp;
 
+                   if (transient_errors > MAX_TRANSIENT_ERRORS)
+                   {
+                       if (outlevel > O_SILENT)
+                       {
+                           report(stderr, GT_("Too many mails skipped (%d > %d) due to transient errors for %s\n"),
+                                   transient_errors, MAX_TRANSIENT_ERRORS, buf);
+                       }
+                   }
+
                    if (!check_only && ctl->skipped
                        && run.poll_interval > 0 && !nodetach)
                    {
diff --git a/imap.c b/imap.c
index a181b1dbaf4da4916b11ba75356a2528497fc450..4db2988072d21673691f5d40634eb2ee8b1f4db9 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -1145,7 +1145,7 @@ static int imap_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
        /* an unexpected tagged response */
        if (outlevel > O_SILENT)
            report(stderr, GT_("Incorrect FETCH response: %s.\n"), buf);
-       return(PS_ERROR);
+       return(PS_TRANSIENT);
     }
     return(ok);
 }
index 6202e7bd44a0658205708adf86143e7bc3b41427..fddeaf9b0079c41be2c0a616ae0b35c8db0b727e 100644 (file)
--- a/tunable.h
+++ b/tunable.h
@@ -21,3 +21,6 @@
 
 /* default skipped message warning interval in seconds */
 #define WARNING_INTERVAL       3600
+
+/* maximum transient errors to accept */
+#define MAX_TRANSIENT_ERRORS   20