changeset 19653:9a021ef4841a

imapc: Don't use fetch-fix-broken-mails for OK and NO [SERVERBUG] FETCH replies Hopefully no servers are actually returning OK without returning a FETCH reply. If they are, maybe we need another workaround.. In any case Yahoo IMAP sometimes loses state and starts returning OK without FETCH replies to all UID FETCH requests (and BADs to FETCHes). It also may return NO [UNAVAILABLE] for both permanent and temporary FETCH failures, so we can't do anything with that. I added NO [SERVERBUG] because that's what Dovecot responds to temporary failures. I'm not sure how useful that check is though.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 27 Jan 2016 15:16:18 +0200
parents ebc657852018
children ff56bb2c713c
files src/lib-storage/index/imapc/imapc-mail-fetch.c src/lib-storage/index/imapc/imapc-mail.c src/lib-storage/index/imapc/imapc-mail.h
diffstat 3 files changed, 35 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/imapc/imapc-mail-fetch.c	Wed Jan 27 10:17:44 2016 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c	Wed Jan 27 15:16:18 2016 +0200
@@ -10,10 +10,41 @@
 #include "imap-arg.h"
 #include "imap-date.h"
 #include "imap-quote.h"
+#include "imap-resp-code.h"
 #include "imapc-client.h"
 #include "imapc-mail.h"
 #include "imapc-storage.h"
 
+static void imapc_mail_set_failure(struct imapc_mail *mail,
+				   const struct imapc_command_reply *reply)
+{
+	struct imapc_mailbox *mbox =
+		(struct imapc_mailbox *)mail->imail.mail.mail.box;
+
+	switch (reply->state) {
+	case IMAPC_COMMAND_STATE_OK:
+		break;
+	case IMAPC_COMMAND_STATE_NO:
+		if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_FETCH_FIX_BROKEN_MAILS)) {
+			/* fetch-fix-broken-mails feature disabled -
+			   fail any mails with missing replies */
+			break;
+		}
+		if (reply->resp_text_key != NULL &&
+		    strcasecmp(reply->resp_text_key, IMAP_RESP_CODE_SERVERBUG) == 0) {
+			/* this is a temporary error, retrying should work. */
+		} else {
+			/* hopefully this is a permanent failure */
+			mail->fetch_ignore_if_missing = TRUE;
+		}
+		break;
+	case IMAPC_COMMAND_STATE_BAD:
+	case IMAPC_COMMAND_STATE_DISCONNECTED:
+		mail->fetch_failed = TRUE;
+		break;
+	}
+}
+
 static void
 imapc_mail_fetch_callback(const struct imapc_command_reply *reply,
 			  void *context)
@@ -28,9 +59,7 @@
 		struct imapc_mail *mail = *mailp;
 
 		i_assert(mail->fetch_count > 0);
-		if (reply->state != IMAPC_COMMAND_STATE_OK &&
-		    reply->state != IMAPC_COMMAND_STATE_NO)
-			mail->fetch_failed = TRUE;
+		imapc_mail_set_failure(mail, reply);
 		if (--mail->fetch_count == 0)
 			mail->fetching_fields = 0;
 		pool_unref(&mail->imail.mail.pool);
--- a/src/lib-storage/index/imapc/imapc-mail.c	Wed Jan 27 10:17:44 2016 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail.c	Wed Jan 27 15:16:18 2016 +0200
@@ -61,6 +61,7 @@
 
 static int imapc_mail_failed(struct mail *mail, const char *field)
 {
+	struct imapc_mail *imail = (struct imapc_mail *)mail;
 	struct imapc_mailbox *mbox = (struct imapc_mailbox *)mail->box;
 	bool fix_broken_mail = FALSE;
 
@@ -81,7 +82,7 @@
 		   versions failed to return any data for messages in Calendars
 		   mailbox. This seems to be fixed in newer versions.
 		   */
-		fix_broken_mail = IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_FETCH_FIX_BROKEN_MAILS);
+		fix_broken_mail = imail->fetch_ignore_if_missing;
 		mail_storage_set_critical(mail->box->storage,
 			"imapc: Remote server didn't send %s for UID %u in %s%s",
 			field, mail->uid, mail->box->vname,
--- a/src/lib-storage/index/imapc/imapc-mail.h	Wed Jan 27 10:17:44 2016 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail.h	Wed Jan 27 15:16:18 2016 +0200
@@ -20,6 +20,7 @@
 	bool header_fetched;
 	bool body_fetched;
 	bool header_list_fetched;
+	bool fetch_ignore_if_missing;
 	bool fetch_failed;
 };