]> 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>
Thu, 10 May 2012 15:25:41 +0000 (17:25 +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 1e297d6f19ce6469638a8a1802152e0fbf423b96..11155c9b2f8561f672efb66e811207401aac7cdf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -95,6 +95,11 @@ fetchmail-6.3.22 (not yet released):
   a header request, in the face of message corruption.  fetchmail now treats
   these as temporary errors. Report and Patch by Mikulas Patocka, Red Hat.
 
+* 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 (released 2011-08-21, 26011 LoC):
 
index 25fed3bdb764e1d8dbb2dab5517fa5d3cd62638d..c2917268cedfce70fa9d70f085bad27b7f4f201b 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -438,7 +438,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;
@@ -612,6 +613,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)
@@ -653,7 +655,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)
@@ -714,7 +719,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);
 
@@ -940,7 +948,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 */
@@ -1297,6 +1305,7 @@ is restored."));
            pass = 0;
            do {
                dispatches = 0;
+               transient_errors = 0;
                ++pass;
 
                /* reset timeout, in case we did an IDLE */
@@ -1426,10 +1435,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 93f05f2c6ba7ba7cb392cd587550092944329188..cb87eda5378f258f20955c3524f2f84c6d29cd0e 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -1182,7 +1182,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