aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--driver.c25
-rw-r--r--imap.c2
-rw-r--r--tunable.h3
4 files changed, 31 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 1e297d6f..11155c9b 100644
--- 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):
diff --git a/driver.c b/driver.c
index 25fed3bd..c2917268 100644
--- 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 93f05f2c..cb87eda5 100644
--- 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);
}
diff --git a/tunable.h b/tunable.h
index 6202e7bd..fddeaf9b 100644
--- 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