dovecot-2.2: imapc: Implemented imapc_features=gmail-pop3 that a...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jan 20 19:56:19 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/df92d09acc63
changeset: 18187:df92d09acc63
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jan 20 21:54:58 2015 +0200
description:
imapc: Implemented imapc_features=gmail-pop3 that also migrates pop3_deleted_flag.
This also caused gmail-pop3-uidl feature to be renamed to simply gmail-pop3,
which includes both the features.

diffstat:

 src/lib-storage/index/imapc/imapc-mail.c     |   2 +-
 src/lib-storage/index/imapc/imapc-mailbox.c  |  76 ++++++++++++++++++++++++++++
 src/lib-storage/index/imapc/imapc-settings.c |   8 ++-
 src/lib-storage/index/imapc/imapc-settings.h |   4 +-
 src/lib-storage/index/imapc/imapc-storage.h  |   1 +
 src/lib-storage/index/imapc/imapc-sync.c     |  45 ++++++++++++----
 6 files changed, 120 insertions(+), 16 deletions(-)

diffs (266 lines):

diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-mail.c
--- a/src/lib-storage/index/imapc/imapc-mail.c	Tue Jan 20 21:49:04 2015 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail.c	Tue Jan 20 21:54:58 2015 +0200
@@ -476,7 +476,7 @@
 		*value_r = "";
 		return imapc_mail_get_guid(_mail, value_r);
 	case MAIL_FETCH_UIDL_BACKEND:
-		if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_POP3_UIDL))
+		if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_POP3))
 			break;
 		if (imapc_mail_get_guid(_mail, value_r) < 0)
 			return -1;
diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-mailbox.c
--- a/src/lib-storage/index/imapc/imapc-mailbox.c	Tue Jan 20 21:49:04 2015 +0200
+++ b/src/lib-storage/index/imapc/imapc-mailbox.c	Tue Jan 20 21:54:58 2015 +0200
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "imap-arg.h"
+#include "imap-seqset.h"
 #include "imap-util.h"
 #include "imapc-client.h"
 #include "imapc-mail.h"
@@ -422,6 +423,79 @@
 }
 
 static void
+imapc_untagged_esearch_gmail_pop3(const struct imap_arg *args,
+				  struct imapc_mailbox *mbox)
+{
+	struct imapc_msgmap *msgmap;
+	const char *atom;
+	struct seq_range_iter iter;
+	ARRAY_TYPE(seq_range) rseqs;
+	unsigned int n;
+	uint32_t rseq, lseq, uid;
+	ARRAY_TYPE(keyword_indexes) keywords;
+	struct mail_keywords *kw;
+	unsigned int pop3_deleted_kw_idx;
+
+	i_free_and_null(mbox->sync_gmail_pop3_search_tag);
+
+	/* It should contain ALL <seqset>  */
+	t_array_init(&rseqs, 64);
+	if (!imap_arg_atom_equals(&args[0], "ALL") ||
+	    !imap_arg_get_atom(&args[1], &atom) ||
+	    imap_seq_set_parse(atom, &rseqs) < 0) {
+		i_error("Invalid gmail-pop3 ESEARCH reply");
+		return;
+	}
+
+	mail_index_keyword_lookup_or_create(mbox->box.index,
+		mbox->storage->set->pop3_deleted_flag, &pop3_deleted_kw_idx);
+
+	t_array_init(&keywords, 1);
+	array_append(&keywords, &pop3_deleted_kw_idx, 1);
+	kw = mail_index_keywords_create_from_indexes(mbox->box.index, &keywords);
+
+	msgmap = imapc_client_mailbox_get_msgmap(mbox->client_box);
+	seq_range_array_iter_init(&iter, &rseqs); n = 0;
+	while (seq_range_array_iter_nth(&iter, n++, &rseq)) {
+		if (rseq > imapc_msgmap_count(msgmap)) {
+			/* we haven't even seen this message yet */
+			break;
+		}
+		uid = imapc_msgmap_rseq_to_uid(msgmap, rseq);
+		if (!mail_index_lookup_seq(mbox->delayed_sync_view,
+					   uid, &lseq))
+			continue;
+
+		/* add the pop3_deleted_flag */
+		mail_index_update_keywords(mbox->delayed_sync_trans,
+					   lseq, MODIFY_ADD, kw);
+	}
+	mail_index_keywords_unref(&kw);
+}
+
+static void imapc_untagged_esearch(const struct imapc_untagged_reply *reply,
+				   struct imapc_mailbox *mbox)
+{
+	const struct imap_arg *tag_list;
+	const char *str;
+
+	if (mbox == NULL || !imap_arg_get_list(reply->args, &tag_list))
+		return;
+
+	/* ESEARCH begins with (TAG <tag>) */
+	if (!imap_arg_atom_equals(&tag_list[0], "TAG") ||
+	    !imap_arg_get_string(&tag_list[1], &str) ||
+	    tag_list[2].type != IMAP_ARG_EOL)
+		return;
+
+	/* for now the only ESEARCH reply that we have is for getting GMail's
+	   list of hidden POP3 messages. */
+	if (mbox->sync_gmail_pop3_search_tag != NULL &&
+	    strcmp(mbox->sync_gmail_pop3_search_tag, str) == 0)
+		imapc_untagged_esearch_gmail_pop3(reply->args+1, mbox);
+}
+
+static void
 imapc_resp_text_uidvalidity(const struct imapc_untagged_reply *reply,
 			    struct imapc_mailbox *mbox)
 {
@@ -512,6 +586,8 @@
 					imapc_untagged_fetch);
 	imapc_mailbox_register_untagged(mbox, "EXPUNGE",
 					imapc_untagged_expunge);
+	imapc_mailbox_register_untagged(mbox, "ESEARCH",
+					imapc_untagged_esearch);
 	imapc_mailbox_register_resp_text(mbox, "UIDVALIDITY",
 					 imapc_resp_text_uidvalidity);
 	imapc_mailbox_register_resp_text(mbox, "UIDNEXT",
diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-settings.c
--- a/src/lib-storage/index/imapc/imapc-settings.c	Tue Jan 20 21:49:04 2015 +0200
+++ b/src/lib-storage/index/imapc/imapc-settings.c	Tue Jan 20 21:54:58 2015 +0200
@@ -30,6 +30,8 @@
 	DEF(SET_STR, imapc_list_prefix),
 	DEF(SET_TIME, imapc_max_idle_time),
 
+	DEF(SET_STR, pop3_deleted_flag),
+
 	SETTING_DEFINE_LIST_END
 };
 
@@ -48,7 +50,9 @@
 	.imapc_features = "",
 	.imapc_rawlog_dir = "",
 	.imapc_list_prefix = "",
-	.imapc_max_idle_time = 60*29
+	.imapc_max_idle_time = 60*29,
+
+	.pop3_deleted_flag = ""
 };
 
 static const struct setting_parser_info imapc_setting_parser_info = {
@@ -81,7 +85,7 @@
 	{ "guid-forced", IMAPC_FEATURE_GUID_FORCED },
 	{ "fetch-headers", IMAPC_FEATURE_FETCH_HEADERS },
 	{ "gmail-labels-keyword", IMAPC_FEATURE_GMAIL_LABELS_KEYWORD },
-	{ "gmail-pop3-uidl", IMAPC_FEATURE_GMAIL_POP3_UIDL },
+	{ "gmail-pop3", IMAPC_FEATURE_GMAIL_POP3 },
 	{ NULL, 0 }
 };
 
diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-settings.h
--- a/src/lib-storage/index/imapc/imapc-settings.h	Tue Jan 20 21:49:04 2015 +0200
+++ b/src/lib-storage/index/imapc/imapc-settings.h	Tue Jan 20 21:54:58 2015 +0200
@@ -7,7 +7,7 @@
 	IMAPC_FEATURE_GUID_FORCED		= 0x02,
 	IMAPC_FEATURE_FETCH_HEADERS		= 0x04,
 	IMAPC_FEATURE_GMAIL_LABELS_KEYWORD	= 0x08,
-	IMAPC_FEATURE_GMAIL_POP3_UIDL		= 0x10
+	IMAPC_FEATURE_GMAIL_POP3		= 0x10
 };
 /* </settings checks> */
 
@@ -28,6 +28,8 @@
 	const char *imapc_list_prefix;
 	unsigned int imapc_max_idle_time;
 
+	const char *pop3_deleted_flag;
+
 	enum imapc_features parsed_features;
 };
 
diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h	Tue Jan 20 21:49:04 2015 +0200
+++ b/src/lib-storage/index/imapc/imapc-storage.h	Tue Jan 20 21:54:58 2015 +0200
@@ -110,6 +110,7 @@
 	uint32_t sync_next_rseq;
 	uint32_t exists_count;
 	uint32_t min_append_uid;
+	char *sync_gmail_pop3_search_tag;
 
 	/* keep the previous fetched message body cached,
 	   mainly for partial IMAP fetches */
diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-sync.c
--- a/src/lib-storage/index/imapc/imapc-sync.c	Tue Jan 20 21:49:04 2015 +0200
+++ b/src/lib-storage/index/imapc/imapc-sync.c	Tue Jan 20 21:54:58 2015 +0200
@@ -38,7 +38,8 @@
 		imapc_client_stop(ctx->mbox->storage->client->client);
 }
 
-static void imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd_str)
+static struct imapc_command *
+imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd_str)
 {
 	struct imapc_command *cmd;
 
@@ -47,6 +48,7 @@
 				       imapc_sync_callback, ctx);
 	imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
 	imapc_command_send(cmd, cmd_str);
+	return cmd;
 }
 
 static void
@@ -273,6 +275,28 @@
 	}
 }
 
+static void
+imapc_sync_send_commands(struct imapc_sync_context *ctx, uint32_t first_uid)
+{
+	string_t *cmd = t_str_new(64);
+
+	str_printfa(cmd, "UID FETCH %u:* (FLAGS", first_uid);
+	if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD))
+		str_append(cmd, " X-GM-LABELS");
+	str_append_c(cmd, ')');
+	imapc_sync_cmd(ctx, str_c(cmd));
+
+	if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_POP3) &&
+	    ctx->mbox->storage->set->pop3_deleted_flag[0] != '\0') {
+		struct imapc_command *cmd;
+
+		cmd = imapc_sync_cmd(ctx, "SEARCH RETURN (ALL) X-GM-RAW \"in:^pop\"");
+		i_free(ctx->mbox->sync_gmail_pop3_search_tag);
+		ctx->mbox->sync_gmail_pop3_search_tag =
+			i_strdup(imapc_command_get_tag(cmd));
+	}
+}
+
 static void imapc_sync_index(struct imapc_sync_context *ctx)
 {
 	struct imapc_mailbox *mbox = ctx->mbox;
@@ -316,13 +340,7 @@
 		/* we'll resync existing messages' flags and add new messages.
 		   adding new messages requires sync locking to avoid
 		   duplicates. */
-		string_t *cmd = t_str_new(64);
-
-		str_printfa(cmd, "UID FETCH %u:* (FLAGS", mbox->sync_fetch_first_uid);
-		if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD))
-			str_append(cmd, " X-GM-LABELS");
-		str_append_c(cmd, ')');
-		imapc_sync_cmd(ctx, str_c(cmd));
+		imapc_sync_send_commands(ctx, mbox->sync_fetch_first_uid);
 		mbox->sync_fetch_first_uid = 0;
 	}
 
@@ -357,10 +375,7 @@
 	mbox->sync_next_lseq = 1;
 	mbox->sync_next_rseq = 1;
 
-	if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD))
-		imapc_sync_cmd(ctx, "UID FETCH 1:* FLAGS");
-	else
-		imapc_sync_cmd(ctx, "UID FETCH 1:* (FLAGS X-GM-LABELS)");
+	imapc_sync_send_commands(ctx, 1);
 }
 
 static int
@@ -427,6 +442,12 @@
 	} else {
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
 	}
+	if (ctx->mbox->sync_gmail_pop3_search_tag != NULL) {
+		mail_storage_set_critical(&ctx->mbox->storage->storage,
+			"gmail-pop3 search not successful");
+		i_free_and_null(ctx->mbox->sync_gmail_pop3_search_tag);
+		ret = -1;
+	}
 	ctx->mbox->syncing = FALSE;
 	ctx->mbox->sync_ctx = NULL;
 


More information about the dovecot-cvs mailing list