Commit d6d0d105 authored by Milan Crha's avatar Milan Crha
Browse files

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

parent 5d812173
......@@ -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);
}
/**
......
......@@ -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 */
......
......@@ -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);
}
}
......
......@@ -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);
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment