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)
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)
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)
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;
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;
}
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) {
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,
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,
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;
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;