1385 lines
36 KiB
C
1385 lines
36 KiB
C
/*
|
|
* e-mail-backend.c
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Authors:
|
|
* Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
|
|
*
|
|
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
|
* Copyright (C) 2009 Intel Corporation
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "e-mail-backend.h"
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <glib/gstdio.h>
|
|
#include <glib/gi18n-lib.h>
|
|
|
|
#include <shell/e-shell.h>
|
|
|
|
#include <mail/e-mail-migrate.h>
|
|
#include <mail/e-mail-ui-session.h>
|
|
#include <mail/em-event.h>
|
|
#include <mail/em-folder-tree-model.h>
|
|
#include <mail/em-utils.h>
|
|
#include <mail/mail-autofilter.h>
|
|
#include <mail/mail-send-recv.h>
|
|
#include <mail/mail-vfolder-ui.h>
|
|
|
|
#define E_MAIL_BACKEND_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE \
|
|
((obj), E_TYPE_MAIL_BACKEND, EMailBackendPrivate))
|
|
|
|
#define E_MAIL_BACKEND_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE \
|
|
((obj), E_TYPE_MAIL_BACKEND, EMailBackendPrivate))
|
|
|
|
#define QUIT_POLL_INTERVAL 1 /* seconds */
|
|
|
|
struct _EMailBackendPrivate {
|
|
EMailSession *session;
|
|
GHashTable *jobs;
|
|
EMailSendAccountOverride *send_account_override;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_SESSION,
|
|
PROP_SEND_ACCOUNT_OVERRIDE
|
|
};
|
|
|
|
G_DEFINE_ABSTRACT_TYPE (
|
|
EMailBackend,
|
|
e_mail_backend,
|
|
E_TYPE_SHELL_BACKEND)
|
|
|
|
static const gchar *
|
|
mail_shell_backend_get_data_dir (EShellBackend *backend)
|
|
{
|
|
return mail_session_get_data_dir ();
|
|
}
|
|
|
|
static const gchar *
|
|
mail_shell_backend_get_config_dir (EShellBackend *backend)
|
|
{
|
|
return mail_session_get_config_dir ();
|
|
}
|
|
|
|
static gchar *
|
|
mail_backend_uri_to_evname (const gchar *uri,
|
|
const gchar *prefix)
|
|
{
|
|
const gchar *data_dir;
|
|
gchar *basename;
|
|
gchar *filename;
|
|
gchar *safe;
|
|
|
|
/* Converts a folder URI to a GalView filename. */
|
|
|
|
data_dir = mail_session_get_data_dir ();
|
|
|
|
safe = g_strdup (uri);
|
|
e_filename_make_safe (safe);
|
|
basename = g_strdup_printf ("%s%s.xml", prefix, safe);
|
|
filename = g_build_filename (data_dir, basename, NULL);
|
|
g_free (basename);
|
|
g_free (safe);
|
|
|
|
return filename;
|
|
}
|
|
|
|
static gboolean
|
|
mail_backend_any_store_requires_downsync (EMailAccountStore *account_store)
|
|
{
|
|
GQueue queue = G_QUEUE_INIT;
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (account_store), FALSE);
|
|
|
|
e_mail_account_store_queue_enabled_services (account_store, &queue);
|
|
|
|
while (!g_queue_is_empty (&queue)) {
|
|
CamelService *service;
|
|
CamelOfflineStore *offline_store;
|
|
|
|
service = g_queue_pop_head (&queue);
|
|
|
|
if (!CAMEL_IS_OFFLINE_STORE (service))
|
|
continue;
|
|
|
|
offline_store = CAMEL_OFFLINE_STORE (service);
|
|
|
|
if (camel_offline_store_requires_downsync (offline_store))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* Callback for various asynchronous CamelStore operations where
|
|
* the EActivity's reference count is used as a counting semaphore. */
|
|
static void
|
|
mail_backend_store_operation_done_cb (CamelStore *store,
|
|
GAsyncResult *result,
|
|
EActivity *activity)
|
|
{
|
|
/* FIXME Not checking result for error. To fix this, we need
|
|
* separate callbacks to call different finish functions
|
|
* and then submit an EAlert on error. */
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
static void
|
|
mail_backend_local_trash_expunge_done_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder = CAMEL_FOLDER (source_object);
|
|
EActivity *activity = user_data;
|
|
GError *local_error = NULL;
|
|
|
|
e_mail_folder_expunge_finish (folder, result, &local_error);
|
|
|
|
if (local_error != NULL) {
|
|
g_warning (
|
|
"%s: Failed to expunge local trash: %s",
|
|
G_STRFUNC, local_error->message);
|
|
g_error_free (local_error);
|
|
}
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
static void
|
|
mail_backend_set_session_offline_cb (gpointer user_data,
|
|
GObject *object)
|
|
{
|
|
CamelSession *session = user_data;
|
|
|
|
g_return_if_fail (CAMEL_IS_SESSION (session));
|
|
|
|
camel_session_set_online (session, FALSE);
|
|
g_object_unref (session);
|
|
}
|
|
|
|
static void
|
|
mail_backend_prepare_for_offline_cb (EShell *shell,
|
|
EActivity *activity,
|
|
EMailBackend *backend)
|
|
{
|
|
GtkWindow *window;
|
|
EMailSession *session;
|
|
EMailAccountStore *account_store;
|
|
EShellBackend *shell_backend;
|
|
GQueue queue = G_QUEUE_INIT;
|
|
|
|
shell_backend = E_SHELL_BACKEND (backend);
|
|
|
|
window = e_shell_get_active_window (shell);
|
|
session = e_mail_backend_get_session (backend);
|
|
account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
|
|
|
|
if (!e_shell_get_network_available (shell)) {
|
|
camel_session_set_online (CAMEL_SESSION (session), FALSE);
|
|
camel_operation_cancel_all ();
|
|
}
|
|
|
|
if (e_shell_backend_is_started (shell_backend)) {
|
|
gboolean ask_to_synchronize;
|
|
gboolean synchronize = FALSE;
|
|
GCancellable *cancellable;
|
|
|
|
ask_to_synchronize =
|
|
e_shell_get_network_available (shell) &&
|
|
mail_backend_any_store_requires_downsync (account_store);
|
|
|
|
if (ask_to_synchronize) {
|
|
synchronize = em_utils_prompt_user (
|
|
window, NULL, "mail:ask-quick-offline", NULL);
|
|
}
|
|
|
|
if (!synchronize) {
|
|
e_shell_backend_cancel_all (shell_backend);
|
|
camel_session_set_online (CAMEL_SESSION (session), FALSE);
|
|
}
|
|
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
if (!cancellable) {
|
|
cancellable = camel_operation_new ();
|
|
e_activity_set_cancellable (activity, cancellable);
|
|
g_object_unref (cancellable);
|
|
} else {
|
|
/* Maybe the cancellable just got cancelled when the above
|
|
camel_operation_cancel_all() had been called, but we want
|
|
it alive for the following "go-offline" operation, thus reset it. */
|
|
g_cancellable_reset (cancellable);
|
|
}
|
|
|
|
e_shell_backend_add_activity (shell_backend, activity);
|
|
}
|
|
|
|
g_object_weak_ref (
|
|
G_OBJECT (activity),
|
|
mail_backend_set_session_offline_cb,
|
|
g_object_ref (session));
|
|
|
|
e_mail_account_store_queue_enabled_services (account_store, &queue);
|
|
while (!g_queue_is_empty (&queue)) {
|
|
CamelService *service;
|
|
|
|
service = g_queue_pop_head (&queue);
|
|
|
|
if (!CAMEL_IS_STORE (service))
|
|
continue;
|
|
|
|
e_mail_store_go_offline (
|
|
CAMEL_STORE (service), G_PRIORITY_DEFAULT,
|
|
e_activity_get_cancellable (activity),
|
|
(GAsyncReadyCallback) mail_backend_store_operation_done_cb,
|
|
g_object_ref (activity));
|
|
}
|
|
}
|
|
|
|
static void
|
|
mail_backend_prepare_for_online_cb (EShell *shell,
|
|
EActivity *activity,
|
|
EMailBackend *backend)
|
|
{
|
|
EMailSession *session;
|
|
EMailAccountStore *account_store;
|
|
GQueue queue = G_QUEUE_INIT;
|
|
|
|
if (e_shell_backend_is_started (E_SHELL_BACKEND (backend))) {
|
|
if (!e_activity_get_cancellable (activity)) {
|
|
GCancellable *cancellable;
|
|
|
|
cancellable = camel_operation_new ();
|
|
e_activity_set_cancellable (activity, cancellable);
|
|
g_object_unref (cancellable);
|
|
}
|
|
|
|
e_shell_backend_add_activity (E_SHELL_BACKEND (backend), activity);
|
|
}
|
|
|
|
session = e_mail_backend_get_session (backend);
|
|
account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
|
|
|
|
camel_session_set_online (CAMEL_SESSION (session), TRUE);
|
|
|
|
e_mail_account_store_queue_enabled_services (account_store, &queue);
|
|
while (!g_queue_is_empty (&queue)) {
|
|
CamelService *service;
|
|
|
|
service = g_queue_pop_head (&queue);
|
|
if (service == NULL)
|
|
continue;
|
|
|
|
if (CAMEL_IS_STORE (service))
|
|
e_mail_store_go_online (
|
|
CAMEL_STORE (service), G_PRIORITY_DEFAULT,
|
|
e_activity_get_cancellable (activity),
|
|
(GAsyncReadyCallback) mail_backend_store_operation_done_cb,
|
|
g_object_ref (activity));
|
|
}
|
|
}
|
|
|
|
/* Helper for mail_backend_prepare_for_quit_cb() */
|
|
static void
|
|
mail_backend_delete_junk (CamelService *service,
|
|
EMailBackend *backend)
|
|
{
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
guint32 flags;
|
|
guint32 mask;
|
|
guint ii;
|
|
|
|
/* FIXME camel_store_get_junk_folder_sync() may block. */
|
|
folder = camel_store_get_junk_folder_sync (
|
|
CAMEL_STORE (service), NULL, NULL);
|
|
if (folder == NULL)
|
|
return;
|
|
|
|
uids = camel_folder_get_uids (folder);
|
|
flags = mask = CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN;
|
|
|
|
camel_folder_freeze (folder);
|
|
|
|
for (ii = 0; ii < uids->len; ii++) {
|
|
const gchar *uid = uids->pdata[ii];
|
|
camel_folder_set_message_flags (folder, uid, flags, mask);
|
|
}
|
|
|
|
camel_folder_thaw (folder);
|
|
|
|
camel_folder_free_uids (folder, uids);
|
|
g_object_unref (folder);
|
|
}
|
|
|
|
/* Helper for mail_backend_prepare_for_quit_cb() */
|
|
static gboolean
|
|
mail_backend_poll_to_quit (gpointer user_data)
|
|
{
|
|
return mail_msg_active ();
|
|
}
|
|
|
|
static gboolean
|
|
mail_backend_service_is_enabled (ESourceRegistry *registry,
|
|
CamelService *service)
|
|
{
|
|
const gchar *uid;
|
|
ESource *source;
|
|
gboolean enabled;
|
|
|
|
g_return_val_if_fail (registry != NULL, FALSE);
|
|
g_return_val_if_fail (service != NULL, FALSE);
|
|
|
|
uid = camel_service_get_uid (service);
|
|
g_return_val_if_fail (uid != NULL, FALSE);
|
|
|
|
source = e_source_registry_ref_source (registry, uid);
|
|
if (!source)
|
|
return FALSE;
|
|
|
|
enabled = e_source_registry_check_enabled (registry, source);
|
|
g_object_unref (source);
|
|
|
|
return enabled;
|
|
}
|
|
|
|
static void
|
|
mail_backend_prepare_for_quit_cb (EShell *shell,
|
|
EActivity *activity,
|
|
EMailBackend *backend)
|
|
{
|
|
EMailSession *session;
|
|
ESourceRegistry *registry;
|
|
GList *list, *link;
|
|
GCancellable *cancellable;
|
|
gboolean delete_junk;
|
|
gboolean empty_trash;
|
|
|
|
session = e_mail_backend_get_session (backend);
|
|
registry = e_shell_get_registry (shell);
|
|
|
|
delete_junk = e_mail_backend_delete_junk_policy_decision (backend);
|
|
empty_trash = e_mail_backend_empty_trash_policy_decision (backend);
|
|
|
|
camel_application_is_exiting = TRUE;
|
|
|
|
camel_operation_cancel_all ();
|
|
mail_vfolder_shutdown ();
|
|
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
if (cancellable) {
|
|
/* Maybe the cancellable just got cancelled when the above
|
|
camel_operation_cancel_all() had been called, but we want
|
|
it alive for the following operations, thus reset it. */
|
|
g_cancellable_reset (cancellable);
|
|
}
|
|
|
|
list = camel_session_list_services (CAMEL_SESSION (session));
|
|
|
|
if (delete_junk) {
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
CamelService *service;
|
|
|
|
service = CAMEL_SERVICE (link->data);
|
|
|
|
if (!CAMEL_IS_STORE (service) ||
|
|
!mail_backend_service_is_enabled (registry, service))
|
|
continue;
|
|
|
|
mail_backend_delete_junk (service, backend);
|
|
}
|
|
}
|
|
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
CamelService *service;
|
|
gboolean store_is_local;
|
|
const gchar *uid;
|
|
|
|
service = CAMEL_SERVICE (link->data);
|
|
|
|
if (!CAMEL_IS_STORE (service))
|
|
continue;
|
|
|
|
if (!mail_backend_service_is_enabled (registry, service))
|
|
continue;
|
|
|
|
uid = camel_service_get_uid (service);
|
|
store_is_local = g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID);
|
|
|
|
if (empty_trash && store_is_local) {
|
|
/* local trash requires special handling,
|
|
* due to POP3's "delete-expunged" option */
|
|
CamelFolder *local_trash;
|
|
|
|
/* This should be lightning-fast since
|
|
* it's just the local trash folder. */
|
|
local_trash = camel_store_get_trash_folder_sync (
|
|
CAMEL_STORE (service), cancellable, NULL);
|
|
|
|
if (local_trash != NULL) {
|
|
e_mail_folder_expunge (
|
|
local_trash,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_backend_local_trash_expunge_done_cb,
|
|
g_object_ref (activity));
|
|
|
|
g_object_unref (local_trash);
|
|
}
|
|
} else {
|
|
/* FIXME Not passing a GCancellable. */
|
|
/* FIXME This operation should be queued. */
|
|
camel_store_synchronize (
|
|
CAMEL_STORE (service),
|
|
empty_trash, G_PRIORITY_DEFAULT,
|
|
NULL, (GAsyncReadyCallback)
|
|
mail_backend_store_operation_done_cb,
|
|
g_object_ref (activity));
|
|
}
|
|
}
|
|
|
|
g_list_free_full (list, (GDestroyNotify) g_object_unref);
|
|
|
|
/* Now we poll until all activities are actually cancelled or finished.
|
|
* Reffing the activity delays quitting; the reference count
|
|
* acts like a counting semaphore. */
|
|
if (mail_msg_active ()) {
|
|
e_named_timeout_add_seconds_full (
|
|
G_PRIORITY_DEFAULT,
|
|
QUIT_POLL_INTERVAL,
|
|
mail_backend_poll_to_quit,
|
|
g_object_ref (activity),
|
|
(GDestroyNotify) g_object_unref);
|
|
}
|
|
}
|
|
|
|
static void
|
|
mail_backend_quit_requested_cb (EShell *shell,
|
|
EShellQuitReason reason,
|
|
EShellBackend *mail_shell_backend)
|
|
{
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
CamelFolder *folder;
|
|
GtkWindow *window;
|
|
gint response;
|
|
|
|
window = e_shell_get_active_window (shell);
|
|
|
|
/* We can quit immediately if offline. */
|
|
if (!e_shell_get_online (shell))
|
|
return;
|
|
|
|
/* Or if another Evolution process asked us to. */
|
|
if (reason == E_SHELL_QUIT_REMOTE_REQUEST)
|
|
return;
|
|
|
|
if (!e_shell_backend_is_started (mail_shell_backend))
|
|
return;
|
|
|
|
/* Check Outbox for any unsent messages. */
|
|
|
|
backend = E_MAIL_BACKEND (mail_shell_backend);
|
|
session = e_mail_backend_get_session (backend);
|
|
|
|
folder = e_mail_session_get_local_folder (
|
|
session, E_MAIL_LOCAL_FOLDER_OUTBOX);
|
|
if (folder == NULL)
|
|
return;
|
|
|
|
if (camel_folder_summary_get_visible_count (folder->summary) == 0)
|
|
return;
|
|
|
|
response = e_alert_run_dialog_for_args (
|
|
window, "mail:exit-unsaved", NULL);
|
|
|
|
if (response == GTK_RESPONSE_YES)
|
|
return;
|
|
|
|
e_shell_cancel_quit (shell);
|
|
}
|
|
|
|
static void
|
|
mail_backend_folder_deleted_cb (MailFolderCache *folder_cache,
|
|
CamelStore *store,
|
|
const gchar *folder_name,
|
|
EMailBackend *backend)
|
|
{
|
|
EShell *shell;
|
|
CamelStoreClass *class;
|
|
ESourceRegistry *registry;
|
|
EShellBackend *shell_backend;
|
|
EMailSession *session;
|
|
EAlertSink *alert_sink;
|
|
GList *list, *link;
|
|
const gchar *extension_name;
|
|
const gchar *local_drafts_folder_uri;
|
|
const gchar *local_sent_folder_uri;
|
|
gchar *uri;
|
|
|
|
/* Check whether the deleted folder was a designated Drafts or
|
|
* Sent folder for any mail account, and if so revert the setting
|
|
* to the equivalent local folder, which is always present. */
|
|
|
|
shell_backend = E_SHELL_BACKEND (backend);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
registry = e_shell_get_registry (shell);
|
|
|
|
class = CAMEL_STORE_GET_CLASS (store);
|
|
g_return_if_fail (class->equal_folder_name != NULL);
|
|
|
|
session = e_mail_backend_get_session (backend);
|
|
alert_sink = e_mail_backend_get_alert_sink (backend);
|
|
|
|
local_drafts_folder_uri =
|
|
e_mail_session_get_local_folder_uri (
|
|
session, E_MAIL_LOCAL_FOLDER_DRAFTS);
|
|
|
|
local_sent_folder_uri =
|
|
e_mail_session_get_local_folder_uri (
|
|
session, E_MAIL_LOCAL_FOLDER_SENT);
|
|
|
|
uri = e_mail_folder_uri_build (store, folder_name);
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
|
|
list = e_source_registry_list_sources (registry, extension_name);
|
|
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
ESource *source = E_SOURCE (link->data);
|
|
ESourceExtension *extension;
|
|
const gchar *drafts_folder_uri;
|
|
|
|
extension = e_source_get_extension (source, extension_name);
|
|
|
|
drafts_folder_uri =
|
|
e_source_mail_composition_get_drafts_folder (
|
|
E_SOURCE_MAIL_COMPOSITION (extension));
|
|
|
|
if (!drafts_folder_uri)
|
|
continue;
|
|
|
|
if (class->equal_folder_name (drafts_folder_uri, uri)) {
|
|
GError *error = NULL;
|
|
|
|
e_source_mail_composition_set_drafts_folder (
|
|
E_SOURCE_MAIL_COMPOSITION (extension),
|
|
local_drafts_folder_uri);
|
|
|
|
/* FIXME This is a blocking D-Bus method call. */
|
|
if (!e_source_write_sync (source, NULL, &error)) {
|
|
g_warning ("%s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free_full (list, (GDestroyNotify) g_object_unref);
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
|
|
list = e_source_registry_list_sources (registry, extension_name);
|
|
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
ESource *source = E_SOURCE (link->data);
|
|
ESourceExtension *extension;
|
|
const gchar *sent_folder_uri;
|
|
|
|
extension = e_source_get_extension (source, extension_name);
|
|
|
|
sent_folder_uri =
|
|
e_source_mail_submission_get_sent_folder (
|
|
E_SOURCE_MAIL_SUBMISSION (extension));
|
|
|
|
if (sent_folder_uri == NULL)
|
|
continue;
|
|
|
|
if (class->equal_folder_name (sent_folder_uri, uri)) {
|
|
GError *error = NULL;
|
|
|
|
e_source_mail_submission_set_sent_folder (
|
|
E_SOURCE_MAIL_SUBMISSION (extension),
|
|
local_sent_folder_uri);
|
|
|
|
/* FIXME This is a blocking D-Bus method call. */
|
|
if (!e_source_write_sync (source, NULL, &error)) {
|
|
g_warning ("%s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free_full (list, (GDestroyNotify) g_object_unref);
|
|
|
|
g_free (uri);
|
|
|
|
/* This does something completely different.
|
|
* XXX Make it a separate signal handler? */
|
|
mail_filter_delete_folder (store, folder_name, alert_sink);
|
|
}
|
|
|
|
static void
|
|
mail_backend_folder_renamed_cb (MailFolderCache *folder_cache,
|
|
CamelStore *store,
|
|
const gchar *old_folder_name,
|
|
const gchar *new_folder_name,
|
|
EMailBackend *backend)
|
|
{
|
|
EShell *shell;
|
|
CamelStoreClass *class;
|
|
ESourceRegistry *registry;
|
|
EShellBackend *shell_backend;
|
|
GList *list, *link;
|
|
const gchar *extension_name;
|
|
gchar *old_uri;
|
|
gchar *new_uri;
|
|
gint ii;
|
|
|
|
const gchar *cachenames[] = {
|
|
"views/current_view-",
|
|
"views/custom_view-"
|
|
};
|
|
|
|
/* Check whether the renamed folder was a designated Drafts or
|
|
* Sent folder for any mail account, and if so update the setting
|
|
* to the new folder name. */
|
|
|
|
shell_backend = E_SHELL_BACKEND (backend);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
registry = e_shell_get_registry (shell);
|
|
|
|
class = CAMEL_STORE_GET_CLASS (store);
|
|
g_return_if_fail (class->equal_folder_name != NULL);
|
|
|
|
old_uri = e_mail_folder_uri_build (store, old_folder_name);
|
|
new_uri = e_mail_folder_uri_build (store, new_folder_name);
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
|
|
list = e_source_registry_list_sources (registry, extension_name);
|
|
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
ESource *source = E_SOURCE (link->data);
|
|
ESourceExtension *extension;
|
|
const gchar *drafts_folder_uri;
|
|
gboolean need_update;
|
|
|
|
extension = e_source_get_extension (source, extension_name);
|
|
|
|
drafts_folder_uri =
|
|
e_source_mail_composition_get_drafts_folder (
|
|
E_SOURCE_MAIL_COMPOSITION (extension));
|
|
|
|
need_update =
|
|
(drafts_folder_uri != NULL) &&
|
|
class->equal_folder_name (drafts_folder_uri, old_uri);
|
|
|
|
if (need_update) {
|
|
GError *error = NULL;
|
|
|
|
e_source_mail_composition_set_drafts_folder (
|
|
E_SOURCE_MAIL_COMPOSITION (extension),
|
|
new_uri);
|
|
|
|
/* FIXME This is a blocking D-Bus method call. */
|
|
if (!e_source_write_sync (source, NULL, &error)) {
|
|
g_warning ("%s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free_full (list, (GDestroyNotify) g_object_unref);
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
|
|
list = e_source_registry_list_sources (registry, extension_name);
|
|
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
ESource *source = E_SOURCE (link->data);
|
|
ESourceExtension *extension;
|
|
const gchar *sent_folder_uri;
|
|
gboolean need_update;
|
|
|
|
extension = e_source_get_extension (source, extension_name);
|
|
|
|
sent_folder_uri =
|
|
e_source_mail_submission_get_sent_folder (
|
|
E_SOURCE_MAIL_SUBMISSION (extension));
|
|
|
|
need_update =
|
|
(sent_folder_uri != NULL) &&
|
|
class->equal_folder_name (sent_folder_uri, old_uri);
|
|
|
|
if (need_update) {
|
|
GError *error = NULL;
|
|
|
|
e_source_mail_submission_set_sent_folder (
|
|
E_SOURCE_MAIL_SUBMISSION (extension),
|
|
new_uri);
|
|
|
|
/* FIXME This is a blocking D-Bus method call. */
|
|
if (!e_source_write_sync (source, NULL, &error)) {
|
|
g_warning ("%s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free_full (list, (GDestroyNotify) g_object_unref);
|
|
|
|
/* Rename GalView files. */
|
|
|
|
for (ii = 0; ii < G_N_ELEMENTS (cachenames); ii++) {
|
|
gchar *oldname;
|
|
gchar *newname;
|
|
|
|
oldname = mail_backend_uri_to_evname (old_uri, cachenames[ii]);
|
|
newname = mail_backend_uri_to_evname (new_uri, cachenames[ii]);
|
|
|
|
/* Ignore errors; doesn't matter. */
|
|
if (g_rename (oldname, newname) == -1 && errno != ENOENT) {
|
|
g_warning (
|
|
"%s: Failed to rename '%s' to '%s': %s",
|
|
G_STRFUNC,
|
|
oldname, newname,
|
|
g_strerror (errno));
|
|
}
|
|
|
|
g_free (oldname);
|
|
g_free (newname);
|
|
}
|
|
|
|
g_free (old_uri);
|
|
g_free (new_uri);
|
|
|
|
/* This does something completely different.
|
|
* XXX Make it a separate signal handler? */
|
|
mail_filter_rename_folder (
|
|
store, old_folder_name, new_folder_name);
|
|
}
|
|
|
|
static void
|
|
mail_backend_folder_changed_cb (MailFolderCache *folder_cache,
|
|
CamelStore *store,
|
|
const gchar *folder_name,
|
|
gint new_messages,
|
|
const gchar *msg_uid,
|
|
const gchar *msg_sender,
|
|
const gchar *msg_subject,
|
|
EMailBackend *mail_backend)
|
|
{
|
|
EMEvent *event = em_event_peek ();
|
|
EMEventTargetFolder *target;
|
|
EMFolderTreeModel *model;
|
|
gchar *folder_uri;
|
|
gint folder_type;
|
|
CamelFolderInfoFlags flags = 0;
|
|
|
|
folder_uri = e_mail_folder_uri_build (store, folder_name);
|
|
|
|
mail_folder_cache_get_folder_info_flags (
|
|
folder_cache, store, folder_name, &flags);
|
|
|
|
target = em_event_target_new_folder (
|
|
event, store, folder_uri, new_messages,
|
|
msg_uid, msg_sender, msg_subject);
|
|
|
|
g_free (folder_uri);
|
|
|
|
folder_type = (flags & CAMEL_FOLDER_TYPE_MASK);
|
|
target->is_inbox = (folder_type == CAMEL_FOLDER_TYPE_INBOX);
|
|
|
|
model = em_folder_tree_model_get_default ();
|
|
target->display_name = em_folder_tree_model_get_folder_name (
|
|
model, store, folder_name);
|
|
|
|
if (target->new > 0) {
|
|
EShell *shell;
|
|
EShellBackend *shell_backend;
|
|
|
|
shell_backend = E_SHELL_BACKEND (mail_backend);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
e_shell_event (shell, "mail-icon", (gpointer) "mail-unread");
|
|
}
|
|
|
|
/**
|
|
* @Event: folder.changed
|
|
* @Title: Folder changed
|
|
* @Target: EMEventTargetFolder
|
|
*
|
|
* folder.changed is emitted whenever a folder changes. There is no
|
|
* detail on how the folder has changed.
|
|
*
|
|
* UPDATE: We tell the number of new UIDs added rather than the new
|
|
* mails received.
|
|
*/
|
|
e_event_emit (
|
|
(EEvent *) event, "folder.changed",
|
|
(EEventTarget *) target);
|
|
}
|
|
|
|
static void
|
|
mail_backend_job_started_cb (CamelSession *session,
|
|
GCancellable *cancellable,
|
|
EShellBackend *shell_backend)
|
|
{
|
|
EMailBackendPrivate *priv;
|
|
EActivity *activity;
|
|
|
|
priv = E_MAIL_BACKEND_GET_PRIVATE (shell_backend);
|
|
|
|
activity = e_activity_new ();
|
|
e_activity_set_cancellable (activity, cancellable);
|
|
e_shell_backend_add_activity (shell_backend, activity);
|
|
|
|
/* The hash table takes ownership of the activity. */
|
|
g_hash_table_insert (priv->jobs, cancellable, activity);
|
|
}
|
|
|
|
static void
|
|
mail_backend_job_finished_cb (CamelSession *session,
|
|
GCancellable *cancellable,
|
|
const GError *error,
|
|
EShellBackend *shell_backend)
|
|
{
|
|
EMailBackendPrivate *priv;
|
|
EShellBackendClass *class;
|
|
EActivity *activity;
|
|
const gchar *description;
|
|
|
|
priv = E_MAIL_BACKEND_GET_PRIVATE (shell_backend);
|
|
class = E_SHELL_BACKEND_GET_CLASS (shell_backend);
|
|
|
|
activity = g_hash_table_lookup (priv->jobs, cancellable);
|
|
description = e_activity_get_text (activity);
|
|
|
|
if (e_activity_handle_cancellation (activity, error)) {
|
|
/* nothing to do */
|
|
|
|
} else if (error != NULL) {
|
|
EShell *shell;
|
|
GtkApplication *application;
|
|
GList *list, *iter;
|
|
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
|
|
application = GTK_APPLICATION (shell);
|
|
list = gtk_application_get_windows (application);
|
|
|
|
/* Submit the error to an appropriate EAlertSink. */
|
|
for (iter = list; iter != NULL; iter = g_list_next (iter)) {
|
|
EShellView *shell_view;
|
|
EShellContent *shell_content;
|
|
|
|
if (!E_IS_SHELL_WINDOW (iter->data))
|
|
continue;
|
|
|
|
shell_view = e_shell_window_peek_shell_view (
|
|
E_SHELL_WINDOW (iter->data), class->name);
|
|
|
|
if (!E_IS_SHELL_VIEW (shell_view))
|
|
continue;
|
|
|
|
shell_content =
|
|
e_shell_view_get_shell_content (shell_view);
|
|
|
|
if (description != NULL && *description != '\0')
|
|
e_alert_submit (
|
|
E_ALERT_SINK (shell_content),
|
|
"mail:async-error", description,
|
|
error->message, NULL);
|
|
else
|
|
e_alert_submit (
|
|
E_ALERT_SINK (shell_content),
|
|
"mail:async-error-nodescribe",
|
|
error->message, NULL);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_hash_table_remove (priv->jobs, cancellable);
|
|
}
|
|
|
|
static void
|
|
mail_backend_allow_auth_prompt_cb (EMailSession *session,
|
|
ESource *source,
|
|
EShell *shell)
|
|
{
|
|
g_return_if_fail (E_IS_SOURCE (source));
|
|
g_return_if_fail (E_IS_SHELL (shell));
|
|
|
|
e_shell_allow_auth_prompt_for (shell, source);
|
|
}
|
|
|
|
static void
|
|
mail_backend_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id) {
|
|
case PROP_SESSION:
|
|
g_value_set_object (
|
|
value,
|
|
e_mail_backend_get_session (
|
|
E_MAIL_BACKEND (object)));
|
|
return;
|
|
|
|
case PROP_SEND_ACCOUNT_OVERRIDE:
|
|
g_value_set_object (
|
|
value,
|
|
e_mail_backend_get_send_account_override (
|
|
E_MAIL_BACKEND (object)));
|
|
return;
|
|
}
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
mail_backend_dispose (GObject *object)
|
|
{
|
|
EMailBackendPrivate *priv;
|
|
|
|
priv = E_MAIL_BACKEND_GET_PRIVATE (object);
|
|
|
|
if (priv->session != NULL) {
|
|
em_folder_tree_model_free_default ();
|
|
|
|
g_signal_handlers_disconnect_matched (
|
|
priv->session, G_SIGNAL_MATCH_DATA,
|
|
0, 0, NULL, NULL, object);
|
|
camel_session_remove_services (
|
|
CAMEL_SESSION (priv->session));
|
|
g_object_unref (priv->session);
|
|
priv->session = NULL;
|
|
}
|
|
|
|
/* There should be no unfinished jobs left. */
|
|
g_warn_if_fail (g_hash_table_size (priv->jobs) == 0);
|
|
|
|
/* Chain up to parent's dispose() method. */
|
|
G_OBJECT_CLASS (e_mail_backend_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
mail_backend_finalize (GObject *object)
|
|
{
|
|
EMailBackendPrivate *priv;
|
|
|
|
priv = E_MAIL_BACKEND_GET_PRIVATE (object);
|
|
|
|
g_hash_table_destroy (priv->jobs);
|
|
g_clear_object (&priv->send_account_override);
|
|
|
|
/* Chain up to parent's finalize() method. */
|
|
G_OBJECT_CLASS (e_mail_backend_parent_class)->finalize (object);
|
|
|
|
camel_shutdown ();
|
|
}
|
|
|
|
static void
|
|
mail_backend_add_store (EMailSession *session,
|
|
CamelStore *store,
|
|
EMailBackend *backend)
|
|
{
|
|
EMFolderTreeModel *model;
|
|
|
|
model = em_folder_tree_model_get_default ();
|
|
em_folder_tree_model_add_store (model, store);
|
|
}
|
|
|
|
static void
|
|
mail_backend_remove_store (EMailSession *session,
|
|
CamelStore *store,
|
|
EMailBackend *backend)
|
|
{
|
|
EMFolderTreeModel *model;
|
|
|
|
model = em_folder_tree_model_get_default ();
|
|
em_folder_tree_model_remove_store (model, store);
|
|
}
|
|
|
|
#define SET_ACTIVITY(cancellable, activity) \
|
|
g_object_set_data (G_OBJECT (cancellable), "e-activity", activity)
|
|
#define GET_ACTIVITY(cancellable) \
|
|
g_object_get_data (G_OBJECT (cancellable), "e-activity")
|
|
|
|
static void
|
|
mail_mt_create_activity (GCancellable *cancellable)
|
|
{
|
|
EActivity *activity;
|
|
|
|
activity = e_activity_new ();
|
|
e_activity_set_percent (activity, 0.0);
|
|
e_activity_set_cancellable (activity, cancellable);
|
|
SET_ACTIVITY (cancellable, activity);
|
|
}
|
|
|
|
static void
|
|
mail_mt_submit_activity (GCancellable *cancellable)
|
|
{
|
|
EShell *shell;
|
|
EShellBackend *shell_backend;
|
|
EActivity *activity;
|
|
|
|
shell = e_shell_get_default ();
|
|
shell_backend = e_shell_get_backend_by_name (
|
|
shell, "mail");
|
|
|
|
activity = GET_ACTIVITY (cancellable);
|
|
if (activity)
|
|
e_shell_backend_add_activity (shell_backend, activity);
|
|
|
|
}
|
|
|
|
static void
|
|
mail_mt_free_activity (GCancellable *cancellable)
|
|
{
|
|
EActivity *activity = GET_ACTIVITY (cancellable);
|
|
|
|
if (activity)
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
static void
|
|
mail_mt_complete_activity (GCancellable *cancellable)
|
|
{
|
|
EActivity *activity = GET_ACTIVITY (cancellable);
|
|
|
|
if (activity)
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
}
|
|
|
|
static void
|
|
mail_mt_cancel_activity (GCancellable *cancellable)
|
|
{
|
|
EActivity *activity = GET_ACTIVITY (cancellable);
|
|
|
|
if (activity)
|
|
e_activity_set_state (activity, E_ACTIVITY_CANCELLED);
|
|
}
|
|
|
|
static void
|
|
mail_mt_alert_error (GCancellable *cancellable,
|
|
const gchar *what,
|
|
const gchar *message)
|
|
{
|
|
EShell *shell;
|
|
EShellView *shell_view;
|
|
EShellWindow *shell_window = NULL;
|
|
EShellContent *shell_content;
|
|
GList *list, *iter;
|
|
GtkApplication *application;
|
|
|
|
shell = e_shell_get_default ();
|
|
application = GTK_APPLICATION (shell);
|
|
list = gtk_application_get_windows (application);
|
|
|
|
/* Find the most recently used EShellWindow. */
|
|
for (iter = list; iter != NULL; iter = g_list_next (iter)) {
|
|
if (E_IS_SHELL_WINDOW (iter->data)) {
|
|
shell_window = E_SHELL_WINDOW (iter->data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If we can't find an EShellWindow then... well, screw it. */
|
|
if (shell_window == NULL)
|
|
return;
|
|
|
|
shell_view = e_shell_window_get_shell_view (
|
|
shell_window, "mail");
|
|
shell_content = e_shell_view_get_shell_content (shell_view);
|
|
|
|
if (what) {
|
|
e_alert_submit (
|
|
E_ALERT_SINK (shell_content),
|
|
"mail:async-error", what,
|
|
message, NULL);
|
|
} else
|
|
e_alert_submit (
|
|
E_ALERT_SINK (shell_content),
|
|
"mail:async-error-nodescribe",
|
|
message, NULL);
|
|
}
|
|
|
|
static EAlertSink *
|
|
mail_mt_get_alert_sink ()
|
|
{
|
|
EShell *shell;
|
|
EShellBackend *shell_backend;
|
|
|
|
shell = e_shell_get_default ();
|
|
shell_backend = e_shell_get_backend_by_name (
|
|
shell, "mail");
|
|
|
|
return e_mail_backend_get_alert_sink (E_MAIL_BACKEND (shell_backend));
|
|
}
|
|
|
|
static void
|
|
mail_backend_constructed (GObject *object)
|
|
{
|
|
EMailBackendPrivate *priv;
|
|
EShell *shell;
|
|
EShellBackend *shell_backend;
|
|
MailFolderCache *folder_cache;
|
|
ESourceRegistry *registry;
|
|
gchar *send_overrides_ini;
|
|
|
|
priv = E_MAIL_BACKEND_GET_PRIVATE (object);
|
|
|
|
shell_backend = E_SHELL_BACKEND (object);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
|
|
if (camel_init (e_get_user_data_dir (), TRUE) != 0)
|
|
exit (0);
|
|
|
|
registry = e_shell_get_registry (shell);
|
|
priv->session = e_mail_ui_session_new (registry);
|
|
|
|
g_signal_connect (
|
|
priv->session, "allow-auth-prompt",
|
|
G_CALLBACK (mail_backend_allow_auth_prompt_cb), shell);
|
|
|
|
g_signal_connect (
|
|
priv->session, "flush-outbox",
|
|
G_CALLBACK (mail_send), priv->session);
|
|
|
|
/* Propagate "activity-added" signals from
|
|
* the mail session to the shell backend. */
|
|
g_signal_connect_swapped (
|
|
priv->session, "activity-added",
|
|
G_CALLBACK (e_shell_backend_add_activity),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
priv->session, "job-started",
|
|
G_CALLBACK (mail_backend_job_started_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
priv->session, "job-finished",
|
|
G_CALLBACK (mail_backend_job_finished_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
priv->session, "store-added",
|
|
G_CALLBACK (mail_backend_add_store),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
priv->session, "store-removed",
|
|
G_CALLBACK (mail_backend_remove_store),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
shell, "prepare-for-offline",
|
|
G_CALLBACK (mail_backend_prepare_for_offline_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
shell, "prepare-for-online",
|
|
G_CALLBACK (mail_backend_prepare_for_online_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
shell, "prepare-for-quit",
|
|
G_CALLBACK (mail_backend_prepare_for_quit_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
shell, "quit-requested",
|
|
G_CALLBACK (mail_backend_quit_requested_cb),
|
|
shell_backend);
|
|
|
|
folder_cache = e_mail_session_get_folder_cache (priv->session);
|
|
|
|
g_signal_connect (
|
|
folder_cache, "folder-deleted",
|
|
G_CALLBACK (mail_backend_folder_deleted_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
folder_cache, "folder-renamed",
|
|
G_CALLBACK (mail_backend_folder_renamed_cb),
|
|
shell_backend);
|
|
|
|
g_signal_connect (
|
|
folder_cache, "folder-changed",
|
|
G_CALLBACK (mail_backend_folder_changed_cb), shell_backend);
|
|
|
|
mail_config_init (priv->session);
|
|
|
|
mail_msg_register_activities (
|
|
mail_mt_create_activity,
|
|
mail_mt_submit_activity,
|
|
mail_mt_free_activity,
|
|
mail_mt_complete_activity,
|
|
mail_mt_cancel_activity,
|
|
mail_mt_alert_error,
|
|
mail_mt_get_alert_sink);
|
|
|
|
/* Chain up to parent's constructed() method. */
|
|
G_OBJECT_CLASS (e_mail_backend_parent_class)->constructed (object);
|
|
|
|
send_overrides_ini = g_build_filename (e_shell_backend_get_config_dir (shell_backend), "send-overrides.ini", NULL);
|
|
priv->send_account_override = e_mail_send_account_override_new (send_overrides_ini);
|
|
g_free (send_overrides_ini);
|
|
}
|
|
|
|
static void
|
|
e_mail_backend_class_init (EMailBackendClass *class)
|
|
{
|
|
GObjectClass *object_class;
|
|
EShellBackendClass *shell_backend_class;
|
|
|
|
g_type_class_add_private (class, sizeof (EMailBackendPrivate));
|
|
|
|
object_class = G_OBJECT_CLASS (class);
|
|
object_class->get_property = mail_backend_get_property;
|
|
object_class->dispose = mail_backend_dispose;
|
|
object_class->finalize = mail_backend_finalize;
|
|
object_class->constructed = mail_backend_constructed;
|
|
|
|
shell_backend_class = E_SHELL_BACKEND_CLASS (class);
|
|
shell_backend_class->migrate = e_mail_migrate;
|
|
shell_backend_class->get_data_dir = mail_shell_backend_get_data_dir;
|
|
shell_backend_class->get_config_dir = mail_shell_backend_get_config_dir;
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SESSION,
|
|
g_param_spec_object (
|
|
"session",
|
|
NULL,
|
|
NULL,
|
|
E_TYPE_MAIL_SESSION,
|
|
G_PARAM_READABLE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SEND_ACCOUNT_OVERRIDE,
|
|
g_param_spec_object (
|
|
"send-account-override",
|
|
NULL,
|
|
NULL,
|
|
E_TYPE_MAIL_SEND_ACCOUNT_OVERRIDE,
|
|
G_PARAM_READABLE));
|
|
}
|
|
|
|
static void
|
|
e_mail_backend_init (EMailBackend *backend)
|
|
{
|
|
backend->priv = E_MAIL_BACKEND_GET_PRIVATE (backend);
|
|
|
|
backend->priv->jobs = g_hash_table_new_full (
|
|
(GHashFunc) g_direct_hash,
|
|
(GEqualFunc) g_direct_equal,
|
|
(GDestroyNotify) NULL,
|
|
(GDestroyNotify) g_object_unref);
|
|
}
|
|
|
|
EMailSession *
|
|
e_mail_backend_get_session (EMailBackend *backend)
|
|
{
|
|
g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
|
|
|
|
return backend->priv->session;
|
|
}
|
|
|
|
EAlertSink *
|
|
e_mail_backend_get_alert_sink (EMailBackend *backend)
|
|
{
|
|
EShell *shell;
|
|
EShellView *shell_view;
|
|
EShellBackend *shell_backend;
|
|
EShellContent *shell_content;
|
|
EShellWindow *shell_window = NULL;
|
|
EShellBackendClass *class;
|
|
GtkApplication *application;
|
|
GList *list, *link;
|
|
|
|
/* XXX This is meant to be a convenient but temporary hack.
|
|
* It digs through the list of available EShellWindows
|
|
* to find a suitable EAlertSink. */
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
|
|
|
|
shell_backend = E_SHELL_BACKEND (backend);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
|
|
application = GTK_APPLICATION (shell);
|
|
list = gtk_application_get_windows (application);
|
|
|
|
/* Find the most recently used EShellWindow. */
|
|
for (link = list; link != NULL; link = g_list_next (link)) {
|
|
if (E_IS_SHELL_WINDOW (link->data)) {
|
|
shell_window = E_SHELL_WINDOW (link->data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_return_val_if_fail (shell_window != NULL, NULL);
|
|
|
|
class = E_SHELL_BACKEND_GET_CLASS (shell_backend);
|
|
shell_view = e_shell_window_get_shell_view (shell_window, class->name);
|
|
shell_content = e_shell_view_get_shell_content (shell_view);
|
|
|
|
return E_ALERT_SINK (shell_content);
|
|
}
|
|
|
|
gboolean
|
|
e_mail_backend_delete_junk_policy_decision (EMailBackend *backend)
|
|
{
|
|
EMailBackendClass *class;
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), FALSE);
|
|
|
|
class = E_MAIL_BACKEND_GET_CLASS (backend);
|
|
if (class->delete_junk_policy_decision == NULL)
|
|
return FALSE;
|
|
|
|
return class->delete_junk_policy_decision (backend);
|
|
}
|
|
|
|
gboolean
|
|
e_mail_backend_empty_trash_policy_decision (EMailBackend *backend)
|
|
{
|
|
EMailBackendClass *class;
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), FALSE);
|
|
|
|
class = E_MAIL_BACKEND_GET_CLASS (backend);
|
|
if (class->empty_trash_policy_decision == NULL)
|
|
return FALSE;
|
|
|
|
return class->empty_trash_policy_decision (backend);
|
|
}
|
|
|
|
EMailSendAccountOverride *
|
|
e_mail_backend_get_send_account_override (EMailBackend *backend)
|
|
{
|
|
g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
|
|
|
|
return backend->priv->send_account_override;
|
|
}
|