[evolution-ews] Bug #656805 - Read receipt handling doesn't work
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug #656805 - Read receipt handling doesn't work
- Date: Wed, 7 May 2014 10:48:58 +0000 (UTC)
commit fe82898c916d2eaff39e4b7c55a8712c2d5a9914
Author: Milan Crha <mcrha redhat com>
Date: Wed May 7 12:48:19 2014 +0200
Bug #656805 - Read receipt handling doesn't work
src/camel/camel-ews-folder.c | 87 +++++++++++++++++++++++++++++++++++++---
src/camel/camel-ews-summary.h | 3 +-
src/camel/camel-ews-utils.c | 76 +++++++++++++++++++++++++++---------
src/server/e-ews-item.c | 17 ++++++--
src/server/e-ews-item.h | 1 +
src/utils/ews-camel-common.c | 2 +-
6 files changed, 153 insertions(+), 33 deletions(-)
---
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index b22a7ec..0782409 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -145,26 +145,36 @@ ews_folder_get_summary_message_mapi_flags (void)
list = ews_folder_get_summary_followup_mapi_flags ();
+ /* PidTagMessageFlags */
ext_uri = e_ews_extended_field_uri_new ();
ext_uri->prop_tag = g_strdup_printf ("%d", 0x0e07);
ext_uri->prop_type = g_strdup ("Integer");
list = g_slist_append (list, ext_uri);
+ /* PidTagMessageStatus */
ext_uri = e_ews_extended_field_uri_new ();
ext_uri->prop_tag = g_strdup_printf ("%d", 0x0e17);
ext_uri->prop_type = g_strdup ("Integer");
list = g_slist_append (list, ext_uri);
+ /* PidTagIconIndex */
ext_uri = e_ews_extended_field_uri_new ();
ext_uri->prop_tag = g_strdup_printf ("%d", 0x1080);
ext_uri->prop_type = g_strdup ("Integer");
list = g_slist_append (list, ext_uri);
+ /* PidTagLastVerbExecuted */
ext_uri = e_ews_extended_field_uri_new ();
ext_uri->prop_tag = g_strdup_printf ("%d", 0x1081);
ext_uri->prop_type = g_strdup ("Integer");
list = g_slist_append (list, ext_uri);
+ /* PidTagReadReceiptRequested */
+ ext_uri = e_ews_extended_field_uri_new ();
+ ext_uri->prop_tag = g_strdup_printf ("%d", 0x0029);
+ ext_uri->prop_type = g_strdup ("Boolean");
+ list = g_slist_append (list, ext_uri);
+
return list;
}
@@ -930,6 +940,38 @@ msg_update_flags (ESoapMessage *msg,
}
}
+static void
+ews_suppress_read_receipt (ESoapMessage *msg,
+ gpointer user_data)
+{
+ /* the mi_list is owned by the caller */
+ const GSList *mi_list = user_data, *iter;
+ CamelEwsMessageInfo *mi;
+
+ for (iter = mi_list; iter; iter = g_slist_next (iter)) {
+ mi = iter->data;
+ if (!mi || (camel_message_info_flags (mi) & CAMEL_EWS_MESSAGE_MSGFLAG_RN_PENDING) == 0)
+ continue;
+
+ /* There was requested a read-receipt, but it is handled by evolution-ews,
+ thus prevent an automatic send of it by the server */
+ e_soap_message_start_element (msg, "SuppressReadReceipt", NULL, NULL);
+ e_soap_message_start_element (msg, "ReferenceItemId", NULL, NULL);
+ e_soap_message_add_attribute (msg, "Id", mi->info.uid, NULL, NULL);
+ e_soap_message_add_attribute (msg, "ChangeKey", mi->change_key, NULL, NULL);
+ e_soap_message_end_element (msg); /* "ReferenceItemId" */
+ e_soap_message_end_element (msg); /* SuppressReadReceipt */
+
+ mi->info.flags = mi->info.flags & (~CAMEL_EWS_MESSAGE_MSGFLAG_RN_PENDING);
+ mi->info.dirty = TRUE;
+
+ if (!camel_message_info_user_flag ((CamelMessageInfo *) mi, "receipt-handled"))
+ camel_message_info_set_user_flag ((CamelMessageInfo *) mi, "receipt-handled", TRUE);
+
+ camel_folder_summary_touch (mi->info.summary);
+ }
+}
+
static gboolean
ews_sync_mi_flags (CamelFolder *folder,
const GSList *mi_list,
@@ -938,8 +980,9 @@ ews_sync_mi_flags (CamelFolder *folder,
{
CamelEwsStore *ews_store;
EEwsConnection *cnc;
+ const GSList *iter;
GError *local_error = NULL;
- gboolean res;
+ gboolean res = TRUE;
ews_store = (CamelEwsStore *) camel_folder_get_parent_store (folder);
@@ -949,12 +992,42 @@ ews_sync_mi_flags (CamelFolder *folder,
cnc = camel_ews_store_ref_connection (ews_store);
- res = e_ews_connection_update_items_sync (
- cnc, EWS_PRIORITY_LOW,
- "AlwaysOverwrite", "SaveOnly",
- NULL, NULL,
- msg_update_flags, (gpointer) mi_list, NULL,
- cancellable, &local_error);
+ for (iter = mi_list; iter; iter = g_slist_next (iter)) {
+ CamelEwsMessageInfo *mi = iter->data;
+
+ if (mi && (camel_message_info_flags (mi) & CAMEL_EWS_MESSAGE_MSGFLAG_RN_PENDING) != 0)
+ break;
+ }
+
+ /* NULL means all had been checked and none has the flag set */
+ if (iter) {
+ GSList *ids = NULL;
+
+ res = e_ews_connection_create_items_sync (
+ cnc, EWS_PRIORITY_LOW,
+ "SaveOnly", NULL, NULL,
+ ews_suppress_read_receipt, (gpointer) mi_list,
+ &ids, cancellable, &local_error);
+
+ g_slist_free_full (ids, g_object_unref);
+
+ /* ignore this error, it's not a big problem */
+ if (g_error_matches (local_error, EWS_CONNECTION_ERROR,
EWS_CONNECTION_ERROR_READRECEIPTNOTPENDING)) {
+ g_clear_error (&local_error);
+ res = TRUE;
+ }
+ }
+
+ if (res) {
+ res = e_ews_connection_update_items_sync (
+ cnc, EWS_PRIORITY_LOW,
+ "AlwaysOverwrite", "SaveOnly",
+ NULL, NULL,
+ msg_update_flags, (gpointer) mi_list, NULL,
+ cancellable, &local_error);
+ }
+
+ camel_folder_summary_save_to_db (folder->summary, NULL);
if (local_error) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
diff --git a/src/camel/camel-ews-summary.h b/src/camel/camel-ews-summary.h
index eb47a7a..b28d4e1 100644
--- a/src/camel/camel-ews-summary.h
+++ b/src/camel/camel-ews-summary.h
@@ -52,8 +52,7 @@ typedef struct _CamelEwsMessageContentInfo CamelEwsMessageContentInfo;
/* extra summary flags*/
enum {
- CAMEL_EWS_MESSAGE_JUNK = 1 << 17,
- CAMEL_EWS_MESSAGE_NOJUNK = 1 << 18
+ CAMEL_EWS_MESSAGE_MSGFLAG_RN_PENDING = CAMEL_MESSAGE_FOLDER_FLAGGED << 1
};
struct _CamelEwsMessageInfo {
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index 87e9eab..ab1bf1e 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -40,6 +40,8 @@
#define SUBFOLDER_DIR_NAME "subfolders"
#define SUBFOLDER_DIR_NAME_LEN 10
+#define EWS_MAPI_MSGFLAG_RN_PENDING 0x100
+
CamelFolderInfo *
camel_ews_utils_build_folder_info (CamelEwsStore *store,
const gchar *fid)
@@ -418,6 +420,16 @@ ews_utils_rename_label (const gchar *cat,
return cat;
}
+static gboolean
+ews_utils_is_system_user_flag (const gchar *name)
+{
+ if (!name)
+ return FALSE;
+
+ return g_str_equal (name, "receipt-handled") ||
+ g_str_equal (name, "$has-cal");
+}
+
void
ews_utils_replace_server_user_flags (ESoapMessage *msg,
CamelEwsMessageInfo *mi)
@@ -431,14 +443,12 @@ ews_utils_replace_server_user_flags (ESoapMessage *msg,
const gchar *n = ews_utils_rename_label (flag->name, 0);
if (*n == '\0')
continue;
- /* This is a mismatch between evolution flags and
- * exchange categories. Evolution uses a
- * receipt-handled flag for message receipts, which we
- * don't want showing up in the categories, so
- * silently drop it here */
- if (strcmp (n, "receipt-handled") == 0 ||
- strcmp (n, "$has-cal") == 0)
+
+ /* Skip evolution-defined flags which are not supposed to
+ be categories on an Exchange server */
+ if (ews_utils_is_system_user_flag (n))
continue;
+
e_ews_message_write_string_parameter (msg, "String", NULL, n);
}
}
@@ -453,14 +463,16 @@ ews_utils_merge_server_user_flags (EEwsItem *item,
/* transfer camel flags to a list */
for (flag = camel_message_info_user_flags (&mi->info); flag;
- flag = flag->next)
- list = g_slist_append (list, (gchar *) flag->name);
+ flag = flag->next) {
+ if (!ews_utils_is_system_user_flag (flag->name))
+ list = g_slist_prepend (list, (gchar *) flag->name);
+ }
- /* we're transferring from server only, so just dump them */
for (p = list; p; p = p->next) {
- camel_flag_set (&mi->info.user_flags, p->data, 0);
+ /* remove custom user flags */
+ camel_flag_set (&mi->info.user_flags, p->data, FALSE);
}
- //g_slist_foreach (list, (GFunc) g_free, NULL);
+
g_slist_free (list);
/* now transfer over all the categories */
@@ -471,12 +483,12 @@ ews_utils_merge_server_user_flags (EEwsItem *item,
}
}
-static gint
+static guint32
ews_utils_get_server_flags (EEwsItem *item)
{
gboolean flag;
EwsImportance importance;
- gint server_flags = 0;
+ guint32 server_flags = 0, msg_flags;
e_ews_item_is_read (item, &flag);
if (flag)
@@ -500,6 +512,10 @@ ews_utils_get_server_flags (EEwsItem *item)
if (importance == EWS_ITEM_HIGH)
server_flags |= CAMEL_MESSAGE_FLAGGED;
+ msg_flags = e_ews_item_get_message_flags (item);
+ if ((msg_flags & EWS_MAPI_MSGFLAG_RN_PENDING) != 0)
+ server_flags |= CAMEL_EWS_MESSAGE_MSGFLAG_RN_PENDING;
+
/* TODO Update replied flags */
return server_flags;
@@ -707,6 +723,23 @@ camel_ews_utils_update_follow_up_flags (EEwsItem *item,
return changed;
}
+static gboolean
+camel_ews_utils_update_read_receipt_flags (EEwsItem *item,
+ CamelMessageInfo *info,
+ guint32 server_flags,
+ gboolean requests_read_receipt)
+{
+ gboolean changed = FALSE;
+
+ /* PidTagReadReceiptRequested */
+ if ((requests_read_receipt || e_ews_item_get_extended_property_as_boolean (item, NULL, 0x0029, NULL))
&&
+ (server_flags & CAMEL_EWS_MESSAGE_MSGFLAG_RN_PENDING) == 0) {
+ changed = camel_message_info_set_user_flag (info, "receipt-handled", TRUE) || changed;
+ }
+
+ return changed;
+}
+
void
camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder,
GSList *items_updated)
@@ -732,16 +765,18 @@ camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder,
mi = (CamelEwsMessageInfo *)
camel_folder_summary_get (folder->summary, id->id);
if (mi) {
- gint server_flags;
+ guint32 server_flags;
gboolean changed, was_changed;
was_changed = (mi->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
+
server_flags = ews_utils_get_server_flags (item);
ews_utils_merge_server_user_flags (item, mi);
changed = camel_ews_update_message_info_flags (
folder->summary, (CamelMessageInfo *) mi,
server_flags, NULL);
changed = camel_ews_utils_update_follow_up_flags (item, (CamelMessageInfo *) mi) ||
changed;
+ changed = camel_ews_utils_update_read_receipt_flags (item, (CamelMessageInfo *) mi,
server_flags, FALSE) || changed;
if (changed)
camel_folder_change_info_change_uid (ci, mi->info.uid);
@@ -795,7 +830,7 @@ camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
EEwsItemType item_type;
const GSList *to, *cc;
const gchar *msg_headers;
- gboolean has_attachments, found_property;
+ gboolean has_attachments, found_property, message_requests_read_receipt = FALSE;
guint32 server_flags;
if (!item)
@@ -833,8 +868,11 @@ camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
camel_mime_parser_scan_from (parser, FALSE);
g_object_unref (stream);
- if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL))
+ if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
mi = (CamelEwsMessageInfo *) camel_folder_summary_info_new_from_header
(folder->summary, part->headers);
+ if (camel_header_raw_find (&(part->headers), "Disposition-Notification-To",
NULL))
+ message_requests_read_receipt = TRUE;
+ }
g_object_unref (parser);
g_object_unref (part);
@@ -893,9 +931,9 @@ camel_ews_utils_sync_created_items (CamelEwsFolder *ews_folder,
mi->server_flags = server_flags;
camel_ews_utils_update_follow_up_flags (item, (CamelMessageInfo *) mi);
+ camel_ews_utils_update_read_receipt_flags (item, (CamelMessageInfo *) mi, server_flags,
message_requests_read_receipt);
- camel_folder_summary_add (
- folder->summary, (CamelMessageInfo *) mi);
+ camel_folder_summary_add (folder->summary, (CamelMessageInfo *) mi);
/* camel_folder_summary_add() sets folder_flagged flag
* on the message info, but this is a fresh item downloaded
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index dde2cfa..23b5f81 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -554,15 +554,15 @@ parse_extended_property (EEwsItemPrivate *priv,
priv->mapi_icon_index = num_value;
break;
- case 0x1081:
+ case 0x1081: /* PidTagLastVerbExecuted */
priv->mapi_last_verb_executed = num_value;
break;
- case 0xe07:
+ case 0x0e07: /* PidTagMessageFlags */
priv->mapi_message_flags = num_value;
break;
- case 0xe17:
+ case 0x0e17: /* PidTagMessageStatus */
priv->mapi_message_status = num_value;
break;
}
@@ -1451,6 +1451,14 @@ e_ews_item_is_answered (EEwsItem *item,
return TRUE;
}
+guint32
+e_ews_item_get_message_flags (EEwsItem *item)
+{
+ g_return_val_if_fail (E_IS_EWS_ITEM (item), 0);
+
+ return item->priv->mapi_message_flags;
+}
+
const GSList *
e_ews_item_get_to_recipients (EEwsItem *item)
{
@@ -1645,11 +1653,12 @@ e_ews_item_get_extended_property_as_boolean (EEwsItem *item,
if (g_str_equal (value, "true"))
return TRUE;
- if (g_str_equal (value, "true"))
+ if (g_str_equal (value, "false"))
return FALSE;
if (found)
*found = FALSE;
+
return FALSE;
}
diff --git a/src/server/e-ews-item.h b/src/server/e-ews-item.h
index e75fb7a..a7c2948 100644
--- a/src/server/e-ews-item.h
+++ b/src/server/e-ews-item.h
@@ -201,6 +201,7 @@ gboolean e_ews_item_is_forwarded (EEwsItem *item,
gboolean *is_forwarded);
gboolean e_ews_item_is_answered (EEwsItem *item,
gboolean *is_answered);
+guint32 e_ews_item_get_message_flags (EEwsItem *item);
const GSList * e_ews_item_get_to_recipients (EEwsItem *item);
const GSList * e_ews_item_get_cc_recipients (EEwsItem *item);
const GSList * e_ews_item_get_bcc_recipients (EEwsItem *item);
diff --git a/src/utils/ews-camel-common.c b/src/utils/ews-camel-common.c
index 768c3a7..508afe0 100644
--- a/src/utils/ews-camel-common.c
+++ b/src/utils/ews-camel-common.c
@@ -183,7 +183,7 @@ create_mime_message_cb (ESoapMessage *msg,
* property Further crap is that Exchange 2007 assumes when it
* sees this property that you're setting the value to 0
* ... it never checks */
- msgflag = MAPI_MSGFLAG_READ; /* draft or sent is always read */
+ msgflag = MAPI_MSGFLAG_READ; /* draft or sent is always read */
if ((message_camel_flags & CAMEL_MESSAGE_DRAFT) != 0)
msgflag |= MAPI_MSGFLAG_UNSENT;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]