aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--imap.c44
2 files changed, 37 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index 1d426ae6..8389e4fc 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,10 @@ fetchmail 6.3.3 (not yet released):
Fixes Debian Bug#354661, reported by Keith Hellman.
* The manual page now suggests -- before the addresses in the sendmail MDA
example.
+* Handle other clients concurrently accessing IMAP mailboxes better.
+ Fetchmail quits the poll if the EXPUNGE count does not match expectations, and
+ servers not updating RECENT counts after EXPUNGE are handled in a better way.
+ (Patch by Sunil Shetye.)
fetchmail 6.3.2 (released 2006-01-22):
diff --git a/imap.c b/imap.c
index 68e87eb8..cc534c01 100644
--- a/imap.c
+++ b/imap.c
@@ -43,7 +43,7 @@ static int expunged = 0;
static unsigned int *unseen_messages;
/* for "IMAP> EXPUNGE" */
-static int recentcount_ok = 0;
+static int actual_deletions = 0;
/* for "IMAP> IDLE" */
static int saved_timeout = 0;
@@ -114,7 +114,6 @@ static int imap_ok(int sock, char *argbuf)
}
else if (strstr(buf, " RECENT"))
{
- recentcount_ok = 1;
recentcount = atoi(buf+2);
}
else if (strstr(buf, " EXPUNGE"))
@@ -122,9 +121,18 @@ static int imap_ok(int sock, char *argbuf)
/* the response "* 10 EXPUNGE" means that the currently
* tenth (i.e. only one) message has been deleted */
if (atoi(buf+2) > 0)
- count--;
- if (count < 0)
- count = 0;
+ {
+ if (count > 0)
+ count--;
+ /* Some servers do not report RECENT after an EXPUNGE.
+ * For such servers, assume that the mail being
+ * expunged is a recent one. For other servers, we
+ * should get an updated RECENT report later and this
+ * assumption will have no effect. */
+ if (recentcount > 0)
+ recentcount--;
+ actual_deletions++;
+ }
}
else if (strstr(buf, " PREAUTH"))
{
@@ -577,15 +585,26 @@ static int internal_expunge(int sock)
{
int ok;
- recentcount_ok = 0;
+ actual_deletions = 0;
if ((ok = gen_transact(sock, "EXPUNGE")))
return(ok);
- /* some servers do not report RECENT after an EXPUNGE. in this case,
- * the previous value of recentcount is just ignored. */
- if (!recentcount_ok)
- recentcount = 0;
+ /* if there is a mismatch between the number of mails which should
+ * have been expunged and the number of mails actually expunged,
+ * another email client may be deleting mails. Quit here,
+ * otherwise fetchmail gets out-of-sync with the imap server,
+ * reports the wrong size to the SMTP server on MAIL FROM: and
+ * triggers a "message ... was not the expected length" error on
+ * every subsequent mail */
+ if (deletions > 0 && deletions != actual_deletions)
+ {
+ report(stderr,
+ GT_("mail expunge mismatch (%d actual != %d expected)\n"),
+ actual_deletions, deletions);
+ deletions = 0;
+ return(PS_ERROR);
+ }
expunged += deletions;
deletions = 0;
@@ -1131,7 +1150,10 @@ static int imap_delete(int sock, struct query *ctl, int number)
* the next session.
*/
if (NUM_NONZERO(expunge_period) && (deletions % expunge_period) == 0)
- internal_expunge(sock);
+ {
+ if ((ok = internal_expunge(sock)))
+ return(ok);
+ }
return(PS_SUCCESS);
}