aboutsummaryrefslogtreecommitdiffstats
path: root/mail/mail-ops.c
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2010-10-27 16:06:57 +0800
committerMilan Crha <mcrha@redhat.com>2010-10-27 16:06:57 +0800
commitd6d0d1050aa72fd757eec127cba605844584dc11 (patch)
tree74d5372fa4f8edf837aa97bf240c31424f8ee99c /mail/mail-ops.c
parent5d812173d0e4e12a74bce2ee137d04b0e56db827 (diff)
downloadgsoc2013-evolution-d6d0d1050aa72fd757eec127cba605844584dc11.tar.gz
gsoc2013-evolution-d6d0d1050aa72fd757eec127cba605844584dc11.tar.zst
gsoc2013-evolution-d6d0d1050aa72fd757eec127cba605844584dc11.zip
Bug #445439 - Delete mail from pop-server when deleted from Inbox/Trash
Diffstat (limited to 'mail/mail-ops.c')
-rw-r--r--mail/mail-ops.c165
1 files changed, 161 insertions, 4 deletions
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index d10473606b..88e327bbf4 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -1659,6 +1659,7 @@ mail_remove_folder (CamelFolder *folder, void (*done) (CamelFolder *folder, gboo
struct _sync_folder_msg {
MailMsg base;
+ EMailSession *session;
CamelFolder *folder;
void (*done) (CamelFolder *folder, gpointer data);
gpointer data;
@@ -1690,7 +1691,10 @@ sync_folder_done (struct _sync_folder_msg *m)
static void
sync_folder_free (struct _sync_folder_msg *m)
{
- g_object_unref ((CamelObject *)m->folder);
+ g_object_unref (m->folder);
+
+ if (m->session)
+ g_object_unref (m->session);
}
static MailMsgInfo sync_folder_info = {
@@ -1829,6 +1833,130 @@ mail_refresh_folder (CamelFolder *folder, void (*done) (CamelFolder *folder, gpo
/* ******************************************************************************** */
+static gboolean
+folder_is_from_source_url (CamelFolder *folder, const gchar *source_url)
+{
+ CamelStore *store;
+ CamelService *service;
+ CamelURL *url;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (folder != NULL, FALSE);
+ g_return_val_if_fail (source_url != NULL, FALSE);
+
+ store = camel_folder_get_parent_store (folder);
+ g_return_val_if_fail (store != NULL, FALSE);
+
+ service = CAMEL_SERVICE (store);
+ g_return_val_if_fail (service != NULL, FALSE);
+ g_return_val_if_fail (service->provider != NULL, FALSE);
+ g_return_val_if_fail (service->provider->url_equal != NULL, FALSE);
+
+ url = camel_url_new (source_url, NULL);
+ g_return_val_if_fail (url != NULL, FALSE);
+
+ res = service->provider->url_equal (service->url, url);
+
+ camel_url_free (url);
+
+ return res;
+}
+
+/* This is because pop3 accounts are hidden under local Inbox, thus whenever an expunge
+ is done on a local trash or Inbox, then also all active pop3 accounts should be expunged. */
+static void
+expunge_pop3_stores (CamelFolder *expunging, EMailSession *session, GCancellable *cancellable, GError **error)
+{
+ GPtrArray *uids;
+ CamelFolder *folder;
+ EAccount *account;
+ EIterator *iter;
+ guint i;
+ GHashTable *expunging_uids = NULL;
+
+ uids = camel_folder_get_uids (expunging);
+ if (!uids)
+ return;
+
+ for (i = 0; i < uids->len; i++) {
+ CamelMessageInfo *info = camel_folder_get_message_info (expunging, uids->pdata[i]);
+
+ if (!info)
+ continue;
+
+ if ((camel_message_info_flags (info) & CAMEL_MESSAGE_DELETED) != 0) {
+ CamelMimeMessage *msg;
+ GError *local_error = NULL;
+
+ /* because the UID in the local store doesn't match with the UID in the pop3 store */
+ msg = camel_folder_get_message_sync (expunging, uids->pdata[i], cancellable, &local_error);
+ if (msg) {
+ const gchar *pop3_uid;
+
+ pop3_uid = camel_medium_get_header (CAMEL_MEDIUM (msg), "X-Evolution-POP3-UID");
+ if (pop3_uid) {
+ gchar *duped = g_strstrip (g_strdup (pop3_uid));
+
+ if (!expunging_uids)
+ expunging_uids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ g_hash_table_insert (expunging_uids, duped, g_strdup (camel_mime_message_get_source (msg)));
+ }
+
+ g_object_unref (msg);
+ }
+
+ if (local_error)
+ g_clear_error (&local_error);
+ }
+
+ camel_folder_free_message_info (expunging, info);
+ }
+
+ camel_folder_free_uids (expunging, uids);
+ uids = NULL;
+
+ if (!expunging_uids)
+ return;
+
+ for (iter = e_list_get_iterator ((EList *)e_get_account_list ());
+ e_iterator_is_valid (iter) && (!error || !*error);
+ e_iterator_next (iter)) {
+ account = (EAccount *) e_iterator_get (iter);
+
+ if (account->enabled && account->source && account->source->url && g_str_has_prefix (account->source->url, "pop://")) {
+ gboolean any_found = FALSE;
+
+ folder = e_mail_session_get_inbox_sync (session, account->source->url, cancellable, error);
+ if (!folder || (error && *error))
+ continue;
+
+ uids = camel_folder_get_uids (folder);
+ if (uids) {
+ for (i = 0; i < uids->len; i++) {
+ /* ensure the ID is from this account, as it's generated by evolution */
+ const gchar *source_url = g_hash_table_lookup (expunging_uids, uids->pdata[i]);
+ if (source_url && folder_is_from_source_url (folder, source_url)) {
+ any_found = TRUE;
+ camel_folder_delete_message (folder, uids->pdata[i]);
+ }
+ }
+ camel_folder_free_uids (folder, uids);
+ }
+
+ if (any_found)
+ camel_folder_synchronize_sync (folder, TRUE, cancellable, error);
+
+ g_object_unref (folder);
+ }
+ }
+
+ if (iter)
+ g_object_unref (iter);
+
+ g_hash_table_destroy (expunging_uids);
+}
+
static gchar *
expunge_folder_desc (struct _sync_folder_msg *m)
{
@@ -1840,7 +1968,30 @@ expunge_folder_exec (struct _sync_folder_msg *m,
GCancellable *cancellable,
GError **error)
{
- camel_folder_expunge_sync (m->folder, cancellable, error);
+ gboolean is_local_inbox_or_trash = m->folder == e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX);
+
+ if (!is_local_inbox_or_trash && e_mail_local_get_store () == camel_folder_get_parent_store (m->folder)) {
+ const gchar *data_dir;
+ CamelFolder *trash;
+ gchar *uri;
+
+ data_dir = mail_session_get_data_dir ();
+ uri = g_strdup_printf ("mbox:%s/local", data_dir);
+ trash = e_mail_session_get_trash_sync (
+ m->session, uri, cancellable, error);
+ g_free (uri);
+
+ is_local_inbox_or_trash = m->folder == trash;
+
+ g_object_unref (trash);
+ }
+
+ /* do this before expunge, to know which messages will be expunged */
+ if (is_local_inbox_or_trash && (!error || !*error))
+ expunge_pop3_stores (m->folder, m->session, cancellable, error);
+
+ if (!error || !*error)
+ camel_folder_expunge_sync (m->folder, cancellable, error);
}
/* we just use the sync stuff where we can, since it would be the same */
@@ -1853,11 +2004,12 @@ static MailMsgInfo expunge_folder_info = {
};
void
-mail_expunge_folder (CamelFolder *folder, void (*done) (CamelFolder *folder, gpointer data), gpointer data)
+mail_expunge_folder (EMailSession *session, CamelFolder *folder, void (*done) (CamelFolder *folder, gpointer data), gpointer data)
{
struct _sync_folder_msg *m;
m = mail_msg_new (&expunge_folder_info);
+ m->session = g_object_ref (session);
m->folder = folder;
g_object_ref (folder);
m->data = data;
@@ -1906,7 +2058,12 @@ empty_trash_exec (struct _empty_trash_msg *m,
}
if (trash) {
- camel_folder_expunge_sync (trash, cancellable, error);
+ /* do this before expunge, to know which messages will be expunged */
+ if (!m->account && (!error || !*error))
+ expunge_pop3_stores (trash, m->session, cancellable, error);
+
+ if (!error || !*error)
+ camel_folder_expunge_sync (trash, cancellable, error);
g_object_unref (trash);
}
}