dovecot-2.1: imapc: Added support for fetching GUID from remote ...

dovecot at dovecot.org dovecot at dovecot.org
Mon Dec 12 08:45:44 EET 2011


details:   http://hg.dovecot.org/dovecot-2.1/rev/0bdbb8d99492
changeset: 13855:0bdbb8d99492
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Dec 12 08:45:32 2011 +0200
description:
imapc: Added support for fetching GUID from remote server, if supported.
Currently this is only done for GMail.

diffstat:

 src/lib-storage/index/imapc/imapc-mail-fetch.c |  34 +++++++++++++++-
 src/lib-storage/index/imapc/imapc-mail.c       |  51 +++++++++++++++++++++++++-
 src/lib-storage/index/imapc/imapc-storage.c    |  16 ++++++++
 src/lib-storage/index/imapc/imapc-storage.h    |   2 +
 4 files changed, 99 insertions(+), 4 deletions(-)

diffs (194 lines):

diff -r 31810fed489d -r 0bdbb8d99492 src/lib-storage/index/imapc/imapc-mail-fetch.c
--- a/src/lib-storage/index/imapc/imapc-mail-fetch.c	Mon Dec 12 08:41:50 2011 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c	Mon Dec 12 08:45:32 2011 +0200
@@ -95,6 +95,11 @@
 	str_printfa(str, "UID FETCH %u (", _mail->uid);
 	if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0)
 		str_append(str, "INTERNALDATE ");
+	if ((fields & MAIL_FETCH_GUID) != 0) {
+		str_append(str, mbox->guid_fetch_field_name);
+		str_append_c(str, ' ');
+	}
+
 	if ((fields & MAIL_FETCH_STREAM_BODY) != 0)
 		str_append(str, "BODY.PEEK[] ");
 	else if ((fields & MAIL_FETCH_STREAM_HEADER) != 0)
@@ -152,6 +157,9 @@
 	if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0 &&
 	    data->received_date == (time_t)-1)
 		fields |= MAIL_FETCH_RECEIVED_DATE;
+	if ((data->wanted_fields & MAIL_FETCH_GUID) != 0 &&
+	    data->guid == NULL && mbox->guid_fetch_field_name != NULL)
+		fields |= MAIL_FETCH_GUID;
 
 	if (data->stream == NULL && data->access_part != 0) {
 		if ((data->access_part & (READ_BODY | PARSE_BODY)) != 0)
@@ -173,6 +181,11 @@
 			return FALSE;
 		fields &= ~MAIL_FETCH_RECEIVED_DATE;
 	}
+	if ((fields & MAIL_FETCH_GUID) != 0) {
+		if (imail->imail.data.guid == NULL)
+			return FALSE;
+		fields &= ~MAIL_FETCH_GUID;
+	}
 	if ((fields & (MAIL_FETCH_STREAM_HEADER |
 		       MAIL_FETCH_STREAM_BODY)) != 0) {
 		if (imail->imail.data.stream == NULL)
@@ -186,10 +199,18 @@
 int imapc_mail_fetch(struct mail *_mail, enum mail_fetch_field fields)
 {
 	struct imapc_mail *imail = (struct imapc_mail *)_mail;
-	struct imapc_storage *storage =
-		(struct imapc_storage *)_mail->box->storage;
+	struct imapc_mailbox *mbox =
+		(struct imapc_mailbox *)_mail->box;
 	int ret;
 
+	if ((fields & MAIL_FETCH_GUID) != 0 &&
+	    mbox->guid_fetch_field_name == NULL) {
+		mail_storage_set_error(_mail->box->storage,
+			MAIL_ERROR_NOTPOSSIBLE,
+			"Message GUID not available in this server");
+		return -1;
+	}
+
 	T_BEGIN {
 		ret = imapc_mail_send_fetch(_mail, fields);
 	} T_END;
@@ -200,7 +221,7 @@
 	   or until all FETCH replies have been received (i.e. some FETCHes
 	   failed) */
 	while (!imapc_mail_have_fields(imail, fields) && imail->fetch_count > 0)
-		imapc_storage_run(storage);
+		imapc_storage_run(mbox->storage);
 	return 0;
 }
 
@@ -356,6 +377,13 @@
 			    imap_parse_datetime(value, &t, &tz))
 				mail->imail.data.received_date = t;
 			match = TRUE;
+		} else if (strcasecmp(key, "X-GM-MSGID") == 0 ||
+			   strcasecmp(key, "X-GUID") == 0) {
+			if (imap_arg_get_astring(&args[i+1], &value)) {
+				mail->imail.data.guid =
+					p_strdup(mail->imail.mail.pool, value);
+			}
+			match = TRUE;
 		}
 	}
 	if (!match) {
diff -r 31810fed489d -r 0bdbb8d99492 src/lib-storage/index/imapc/imapc-mail.c
--- a/src/lib-storage/index/imapc/imapc-mail.c	Mon Dec 12 08:41:50 2011 +0200
+++ b/src/lib-storage/index/imapc/imapc-mail.c	Mon Dec 12 08:45:32 2011 +0200
@@ -267,6 +267,55 @@
 		buffer_free(&mail->body);
 }
 
+static int imapc_mail_get_guid(struct mail *_mail, const char **value_r)
+{
+	struct index_mail *imail = (struct index_mail *)_mail;
+	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
+	const enum index_cache_field cache_idx =
+		imail->ibox->cache_fields[MAIL_CACHE_GUID].idx;
+	string_t *str;
+
+	if (imail->data.guid != NULL) {
+		*value_r = imail->data.guid;
+		return 0;
+	}
+
+	str = str_new(imail->data_pool, 64);
+	if (mail_cache_lookup_field(_mail->transaction->cache_view,
+				    str, imail->mail.mail.seq, cache_idx) > 0) {
+		*value_r = str_c(str);
+		return 0;
+	}
+
+	/* GUID not in cache, fetch it */
+	if (imapc_mail_fetch(_mail, MAIL_FETCH_GUID) < 0)
+		return -1;
+	if (imail->data.guid == NULL) {
+		imapc_mail_failed(_mail, mbox->guid_fetch_field_name);
+		return -1;
+	}
+
+	index_mail_cache_add_idx(imail, cache_idx,
+				 imail->data.guid, strlen(imail->data.guid)+1);
+	*value_r = imail->data.guid;
+	return 0;
+}
+
+static int
+imapc_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
+		       const char **value_r)
+{
+	switch (field) {
+	case MAIL_FETCH_GUID:
+		*value_r = "";
+		return imapc_mail_get_guid(_mail, value_r);
+	default:
+		break;
+	}
+
+	return index_mail_get_special(_mail, field, value_r);
+}
+
 struct mail_vfuncs imapc_mail_vfuncs = {
 	imapc_mail_close,
 	index_mail_free,
@@ -291,7 +340,7 @@
 	index_mail_get_headers,
 	index_mail_get_header_stream,
 	imapc_mail_get_stream,
-	index_mail_get_special,
+	imapc_mail_get_special,
 	index_mail_get_real_mail,
 	index_mail_update_flags,
 	index_mail_update_keywords,
diff -r 31810fed489d -r 0bdbb8d99492 src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c	Mon Dec 12 08:41:50 2011 +0200
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Mon Dec 12 08:45:32 2011 +0200
@@ -410,6 +410,20 @@
 	imapc_client_stop(ctx->mbox->storage->client);
 }
 
+static void imapc_mailbox_get_extensions(struct imapc_mailbox *mbox)
+{
+	enum imapc_capability capa =
+		imapc_client_get_capabilities(mbox->storage->client);
+
+	if (mbox->guid_fetch_field_name == NULL) {
+		/* see if we can get message GUIDs somehow */
+		if ((capa & IMAPC_CAPABILITY_X_GM_EXT_1) != 0) {
+			/* GMail */
+			mbox->guid_fetch_field_name = "X-GM-MSGID";
+		}
+	}
+}
+
 int imapc_mailbox_select(struct imapc_mailbox *mbox)
 {
 	struct imapc_command *cmd;
@@ -422,6 +436,8 @@
 	imapc_client_mailbox_set_reopen_cb(mbox->client_box,
 					   imapc_mailbox_reopen, mbox);
 
+	imapc_mailbox_get_extensions(mbox);
+
 	mbox->selecting = TRUE;
 	ctx.mbox = mbox;
 	ctx.ret = -2;
diff -r 31810fed489d -r 0bdbb8d99492 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h	Mon Dec 12 08:41:50 2011 +0200
+++ b/src/lib-storage/index/imapc/imapc-storage.h	Mon Dec 12 08:45:32 2011 +0200
@@ -83,6 +83,8 @@
 	uint32_t prev_skipped_rseq, prev_skipped_uid;
 	struct imapc_sync_context *sync_ctx;
 
+	const char *guid_fetch_field_name;
+
 	unsigned int selecting:1;
 	unsigned int syncing:1;
 	unsigned int initial_sync_done:1;


More information about the dovecot-cvs mailing list