[evolution] Bug #445439 - Delete mail from pop-server when deleted from Inbox/Trash



commit d6d0d1050aa72fd757eec127cba605844584dc11
Author: Milan Crha <mcrha redhat com>
Date:   Wed Oct 27 10:06:57 2010 +0200

    Bug #445439 - Delete mail from pop-server when deleted from Inbox/Trash

 mail/em-utils.c                          |    5 +-
 mail/em-utils.h                          |    2 +-
 mail/mail-ops.c                          |  165 +++++++++++++++++++++++++++++-
 mail/mail-ops.h                          |    2 +-
 modules/mail/e-mail-shell-view-actions.c |    2 +-
 5 files changed, 167 insertions(+), 9 deletions(-)
---
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 06b1713..779e1a7 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -1337,12 +1337,13 @@ em_utils_message_to_html (CamelMimeMessage *message,
 /**
  * em_utils_expunge_folder:
  * @parent: parent window
+ * @session: #EMailSession
  * @folder: folder to expunge
  *
  * Expunges @folder.
  **/
 void
-em_utils_expunge_folder (GtkWidget *parent, CamelFolder *folder)
+em_utils_expunge_folder (GtkWidget *parent, EMailSession *session, CamelFolder *folder)
 {
 	const gchar *description;
 
@@ -1354,7 +1355,7 @@ em_utils_expunge_folder (GtkWidget *parent, CamelFolder *folder)
 		"mail:ask-expunge", description, NULL))
 		return;
 
-	mail_expunge_folder (folder, NULL, NULL);
+	mail_expunge_folder (session, folder, NULL, NULL);
 }
 
 /**
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 2229d26..698ff3f 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -72,7 +72,7 @@ gchar *em_utils_get_proxy_uri (const gchar *uri);
 /* FIXME: should this have an override charset? */
 gchar *em_utils_message_to_html (CamelMimeMessage *msg, const gchar *credits, guint32 flags, gssize *len, struct _EMFormat *source, const gchar *append, guint32 *validity_found);
 
-void em_utils_expunge_folder (GtkWidget *parent, CamelFolder *folder);
+void em_utils_expunge_folder (GtkWidget *parent, EMailSession *session, CamelFolder *folder);
 void em_utils_empty_trash (GtkWidget *parent, EMailSession *session);
 
 /* returns the folder name portion of an URI */
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index d104736..88e327b 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);
 	}
 }
diff --git a/mail/mail-ops.h b/mail/mail-ops.h
index ea9e9f7..fbcf6bf 100644
--- a/mail/mail-ops.h
+++ b/mail/mail-ops.h
@@ -99,7 +99,7 @@ void mail_refresh_folder (CamelFolder *folder,
 			  void (*done) (CamelFolder *folder, gpointer data),
 			  gpointer data);
 
-void mail_expunge_folder (CamelFolder *folder,
+void mail_expunge_folder (EMailSession *session, CamelFolder *folder,
 			  void (*done) (CamelFolder *folder, gpointer data),
 			  gpointer data);
 
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index d323992..467afa5 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -247,7 +247,7 @@ action_mail_folder_expunge_cb (GtkAction *action,
 	folder = em_folder_tree_get_selected_folder (folder_tree);
 	g_return_if_fail (folder != NULL);
 
-	em_utils_expunge_folder (GTK_WIDGET (shell_window), folder);
+	em_utils_expunge_folder (GTK_WIDGET (shell_window), e_mail_backend_get_session (E_MAIL_BACKEND (e_shell_view_get_shell_backend (shell_view))), folder);
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]