Take a CamelStore and folder name instead of a CamelFolder. CamelStore and folder name can easily be obtained from either a folder URI or a CamelFolder instance, and the function is more efficient with separate parameters.
2470 lines
65 KiB
C
2470 lines
65 KiB
C
/*
|
|
* e-mail-reader-utils.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; either
|
|
* version 2 of the License, or (at your option) version 3.
|
|
*
|
|
* 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*
|
|
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
|
*
|
|
*/
|
|
|
|
/* Miscellaneous utility functions used by EMailReader actions. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "e-mail-reader-utils.h"
|
|
|
|
#include <glib/gi18n.h>
|
|
#include <libxml/tree.h>
|
|
#include <gtkhtml/gtkhtml.h>
|
|
#include <camel/camel.h>
|
|
|
|
#include "shell/e-shell-utils.h"
|
|
|
|
#include "libemail-engine/e-mail-folder-utils.h"
|
|
#include "libemail-engine/e-mail-utils.h"
|
|
#include "libemail-engine/mail-ops.h"
|
|
#include "libemail-engine/mail-tools.h"
|
|
|
|
#include "em-format/e-mail-parser.h"
|
|
#include "em-format/e-mail-part-utils.h"
|
|
|
|
#include "composer/e-composer-actions.h"
|
|
|
|
#include "e-mail-backend.h"
|
|
#include "e-mail-browser.h"
|
|
#include "e-mail-printer.h"
|
|
#include "e-mail-display.h"
|
|
#include "em-composer-utils.h"
|
|
#include "em-utils.h"
|
|
#include "mail-autofilter.h"
|
|
#include "mail-vfolder-ui.h"
|
|
#include "message-list.h"
|
|
|
|
#define d(x)
|
|
|
|
typedef struct _AsyncContext AsyncContext;
|
|
|
|
struct _AsyncContext {
|
|
EActivity *activity;
|
|
CamelFolder *folder;
|
|
CamelMimeMessage *message;
|
|
EMailPartList *part_list;
|
|
EMailReader *reader;
|
|
CamelInternetAddress *address;
|
|
GPtrArray *uids;
|
|
gchar *folder_name;
|
|
gchar *message_uid;
|
|
|
|
EMailReplyType reply_type;
|
|
EMailReplyStyle reply_style;
|
|
EMailForwardStyle forward_style;
|
|
GtkPrintOperationAction print_action;
|
|
const gchar *filter_source;
|
|
gint filter_type;
|
|
gboolean replace;
|
|
gboolean keep_signature;
|
|
};
|
|
|
|
static void
|
|
async_context_free (AsyncContext *async_context)
|
|
{
|
|
g_clear_object (&async_context->activity);
|
|
g_clear_object (&async_context->folder);
|
|
g_clear_object (&async_context->message);
|
|
g_clear_object (&async_context->part_list);
|
|
g_clear_object (&async_context->reader);
|
|
g_clear_object (&async_context->address);
|
|
|
|
if (async_context->uids != NULL)
|
|
g_ptr_array_unref (async_context->uids);
|
|
|
|
g_free (async_context->folder_name);
|
|
g_free (async_context->message_uid);
|
|
|
|
g_slice_free (AsyncContext, async_context);
|
|
}
|
|
|
|
static gboolean
|
|
mail_reader_is_special_local_folder (const gchar *name)
|
|
{
|
|
return (strcmp (name, "Drafts") == 0 ||
|
|
strcmp (name, "Inbox") == 0 ||
|
|
strcmp (name, "Outbox") == 0 ||
|
|
strcmp (name, "Sent") == 0 ||
|
|
strcmp (name, "Templates") == 0);
|
|
}
|
|
|
|
gboolean
|
|
e_mail_reader_confirm_delete (EMailReader *reader)
|
|
{
|
|
CamelFolder *folder;
|
|
CamelStore *parent_store;
|
|
GtkWidget *check_button;
|
|
GtkWidget *container;
|
|
GtkWidget *dialog;
|
|
GtkWindow *window;
|
|
GSettings *settings;
|
|
const gchar *label;
|
|
gboolean prompt_delete_in_vfolder;
|
|
gint response = GTK_RESPONSE_OK;
|
|
|
|
/* Remind users what deleting from a search folder does. */
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
window = e_mail_reader_get_window (reader);
|
|
|
|
settings = g_settings_new ("org.gnome.evolution.mail");
|
|
|
|
prompt_delete_in_vfolder = g_settings_get_boolean (
|
|
settings, "prompt-on-delete-in-vfolder");
|
|
|
|
parent_store = camel_folder_get_parent_store (folder);
|
|
|
|
if (!CAMEL_IS_VEE_STORE (parent_store))
|
|
goto exit;
|
|
|
|
if (!prompt_delete_in_vfolder)
|
|
goto exit;
|
|
|
|
dialog = e_alert_dialog_new_for_args (
|
|
window, "mail:ask-delete-vfolder-msg",
|
|
camel_folder_get_full_name (folder), NULL);
|
|
|
|
container = e_alert_dialog_get_content_area (E_ALERT_DIALOG (dialog));
|
|
|
|
label = _("Do not warn me again");
|
|
check_button = gtk_check_button_new_with_label (label);
|
|
gtk_box_pack_start (GTK_BOX (container), check_button, TRUE, TRUE, 6);
|
|
gtk_widget_show (check_button);
|
|
|
|
response = gtk_dialog_run (GTK_DIALOG (dialog));
|
|
|
|
if (response != GTK_RESPONSE_DELETE_EVENT)
|
|
g_settings_set_boolean (
|
|
settings,
|
|
"prompt-on-delete-in-vfolder",
|
|
!gtk_toggle_button_get_active (
|
|
GTK_TOGGLE_BUTTON (check_button)));
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
exit:
|
|
g_clear_object (&folder);
|
|
|
|
return (response == GTK_RESPONSE_OK);
|
|
}
|
|
|
|
static void
|
|
mail_reader_delete_folder_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
e_mail_folder_remove_finish (folder, result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-delete-folder",
|
|
camel_folder_get_full_name (folder),
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_delete_folder (EMailReader *reader,
|
|
CamelFolder *folder)
|
|
{
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
EShell *shell;
|
|
EAlertSink *alert_sink;
|
|
CamelStore *parent_store;
|
|
CamelProvider *provider;
|
|
MailFolderCache *folder_cache;
|
|
GtkWindow *parent = e_shell_get_active_window (NULL);
|
|
GtkWidget *dialog;
|
|
gboolean store_is_local;
|
|
const gchar *display_name;
|
|
const gchar *full_name;
|
|
CamelFolderInfoFlags flags = 0;
|
|
gboolean have_flags;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
|
|
full_name = camel_folder_get_full_name (folder);
|
|
display_name = camel_folder_get_display_name (folder);
|
|
parent_store = camel_folder_get_parent_store (folder);
|
|
provider = camel_service_get_provider (CAMEL_SERVICE (parent_store));
|
|
|
|
store_is_local = (provider->flags & CAMEL_PROVIDER_IS_LOCAL) != 0;
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
session = e_mail_backend_get_session (backend);
|
|
|
|
alert_sink = e_mail_reader_get_alert_sink (reader);
|
|
folder_cache = e_mail_session_get_folder_cache (session);
|
|
|
|
if (store_is_local &&
|
|
mail_reader_is_special_local_folder (full_name)) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-delete-special-folder",
|
|
display_name, NULL);
|
|
return;
|
|
}
|
|
|
|
shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
|
|
|
if (!store_is_local && !e_shell_get_online (shell))
|
|
{
|
|
e_alert_submit (
|
|
alert_sink, "mail:online-operation",
|
|
display_name, NULL);
|
|
return;
|
|
}
|
|
|
|
have_flags = mail_folder_cache_get_folder_info_flags (
|
|
folder_cache, parent_store, full_name, &flags);
|
|
|
|
if (have_flags && (flags & CAMEL_FOLDER_SYSTEM)) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-delete-special-folder",
|
|
display_name, NULL);
|
|
return;
|
|
}
|
|
|
|
if (have_flags && (flags & CAMEL_FOLDER_CHILDREN)) {
|
|
if (CAMEL_IS_VEE_STORE (parent_store))
|
|
dialog = e_alert_dialog_new_for_args (
|
|
parent, "mail:ask-delete-vfolder",
|
|
display_name, NULL);
|
|
else
|
|
dialog = e_alert_dialog_new_for_args (
|
|
parent, "mail:ask-delete-folder",
|
|
display_name, NULL);
|
|
} else {
|
|
if (CAMEL_IS_VEE_STORE (parent_store))
|
|
dialog = e_alert_dialog_new_for_args (
|
|
parent, "mail:ask-delete-vfolder-nochild",
|
|
display_name, NULL);
|
|
else
|
|
dialog = e_alert_dialog_new_for_args (
|
|
parent, "mail:ask-delete-folder-nochild",
|
|
display_name, NULL);
|
|
}
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
|
|
/* Disable the dialog until the activity finishes. */
|
|
gtk_widget_set_sensitive (dialog, FALSE);
|
|
|
|
/* Destroy the dialog once the activity finishes. */
|
|
g_object_set_data_full (
|
|
G_OBJECT (activity), "delete-dialog",
|
|
dialog, (GDestroyNotify) gtk_widget_destroy);
|
|
|
|
e_mail_folder_remove (
|
|
folder,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_delete_folder_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
} else {
|
|
gtk_widget_destroy (dialog);
|
|
}
|
|
}
|
|
|
|
static void
|
|
mail_reader_delete_folder_name_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
/* XXX The returned CamelFolder is a borrowed reference. */
|
|
folder = camel_store_get_folder_finish (
|
|
CAMEL_STORE (source_object), result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((folder != NULL) && (local_error == NULL)) ||
|
|
((folder == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-delete-folder",
|
|
async_context->folder_name,
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
e_mail_reader_delete_folder (async_context->reader, folder);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_delete_folder_name (EMailReader *reader,
|
|
CamelStore *store,
|
|
const gchar *folder_name)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_STORE (store));
|
|
g_return_if_fail (folder_name != NULL);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->folder_name = g_strdup (folder_name);
|
|
|
|
camel_store_get_folder (
|
|
store, folder_name,
|
|
CAMEL_STORE_FOLDER_INFO_FAST,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_delete_folder_name_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_expunge_folder() */
|
|
static void
|
|
mail_reader_expunge_folder_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
e_mail_folder_expunge_finish (folder, result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-expunge-folder",
|
|
camel_folder_get_display_name (folder),
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_expunge_folder (EMailReader *reader,
|
|
CamelFolder *folder)
|
|
{
|
|
GtkWindow *window;
|
|
const gchar *display_name;
|
|
gboolean proceed;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
|
|
window = e_mail_reader_get_window (reader);
|
|
display_name = camel_folder_get_display_name (folder);
|
|
|
|
proceed = em_utils_prompt_user (
|
|
window, "prompt-on-expunge",
|
|
"mail:ask-expunge", display_name, NULL);
|
|
|
|
if (proceed) {
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
|
|
e_mail_folder_expunge (
|
|
folder,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_expunge_folder_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
}
|
|
|
|
/* Helper for e_mail_reader_expunge_folder_name() */
|
|
static void
|
|
mail_reader_expunge_folder_name_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
/* XXX The returned CamelFolder is a borrowed reference. */
|
|
folder = camel_store_get_folder_finish (
|
|
CAMEL_STORE (source_object), result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-expunge-folder",
|
|
async_context->folder_name,
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
e_mail_reader_expunge_folder (async_context->reader, folder);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_expunge_folder_name (EMailReader *reader,
|
|
CamelStore *store,
|
|
const gchar *folder_name)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_STORE (store));
|
|
g_return_if_fail (folder_name != NULL);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->folder_name = g_strdup (folder_name);
|
|
|
|
camel_store_get_folder (
|
|
store, folder_name,
|
|
CAMEL_STORE_FOLDER_INFO_FAST,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_expunge_folder_name_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_refresh_folder() */
|
|
static void
|
|
mail_reader_refresh_folder_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-refresh-folder",
|
|
camel_folder_get_display_name (folder),
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_refresh_folder (EMailReader *reader,
|
|
CamelFolder *folder)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
|
|
camel_folder_refresh_info (
|
|
folder,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_refresh_folder_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_refresh_folder_name() */
|
|
static void
|
|
mail_reader_refresh_folder_name_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
/* XXX The returned CamelFolder is a borrowed reference. */
|
|
folder = camel_store_get_folder_finish (
|
|
CAMEL_STORE (source_object), result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-refresh-folder",
|
|
async_context->folder_name,
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
e_mail_reader_refresh_folder (async_context->reader, folder);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_refresh_folder_name (EMailReader *reader,
|
|
CamelStore *store,
|
|
const gchar *folder_name)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_STORE (store));
|
|
g_return_if_fail (folder_name != NULL);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->folder_name = g_strdup (folder_name);
|
|
|
|
camel_store_get_folder (
|
|
store, folder_name,
|
|
CAMEL_STORE_FOLDER_INFO_FAST,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_refresh_folder_name_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_unsubscribe_folder_name() */
|
|
static void
|
|
mail_reader_unsubscribe_folder_name_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
camel_subscribable_unsubscribe_folder_finish (
|
|
CAMEL_SUBSCRIBABLE (source_object), result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:folder-unsubscribe",
|
|
async_context->folder_name,
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_unsubscribe_folder_name (EMailReader *reader,
|
|
CamelStore *store,
|
|
const gchar *folder_name)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_SUBSCRIBABLE (store));
|
|
g_return_if_fail (folder_name != NULL);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->folder_name = g_strdup (folder_name);
|
|
|
|
camel_subscribable_unsubscribe_folder (
|
|
CAMEL_SUBSCRIBABLE (store), folder_name,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_unsubscribe_folder_name_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
guint
|
|
e_mail_reader_mark_selected (EMailReader *reader,
|
|
guint32 mask,
|
|
guint32 set)
|
|
{
|
|
CamelFolder *folder;
|
|
guint ii = 0;
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
|
|
if (folder != NULL) {
|
|
GPtrArray *uids;
|
|
|
|
camel_folder_freeze (folder);
|
|
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
|
|
for (ii = 0; ii < uids->len; ii++)
|
|
camel_folder_set_message_flags (
|
|
folder, uids->pdata[ii], mask, set);
|
|
|
|
g_ptr_array_unref (uids);
|
|
|
|
camel_folder_thaw (folder);
|
|
|
|
g_object_unref (folder);
|
|
}
|
|
|
|
return ii;
|
|
}
|
|
|
|
static void
|
|
copy_tree_state (EMailReader *src_reader,
|
|
EMailReader *des_reader)
|
|
{
|
|
GtkWidget *src_mlist, *des_mlist;
|
|
ETableState *state;
|
|
|
|
g_return_if_fail (src_reader != NULL);
|
|
g_return_if_fail (des_reader != NULL);
|
|
|
|
src_mlist = e_mail_reader_get_message_list (src_reader);
|
|
if (!src_mlist)
|
|
return;
|
|
|
|
des_mlist = e_mail_reader_get_message_list (des_reader);
|
|
if (!des_mlist)
|
|
return;
|
|
|
|
state = e_tree_get_state_object (E_TREE (src_mlist));
|
|
e_tree_set_state_object (E_TREE (des_mlist), state);
|
|
g_object_unref (state);
|
|
|
|
message_list_set_search (MESSAGE_LIST (des_mlist), MESSAGE_LIST (src_mlist)->search);
|
|
}
|
|
|
|
guint
|
|
e_mail_reader_open_selected (EMailReader *reader)
|
|
{
|
|
EShell *shell;
|
|
EMailBackend *backend;
|
|
ESourceRegistry *registry;
|
|
CamelFolder *folder;
|
|
GtkWindow *window;
|
|
GPtrArray *views;
|
|
GPtrArray *uids;
|
|
guint ii = 0;
|
|
|
|
g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
|
registry = e_shell_get_registry (shell);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
window = e_mail_reader_get_window (reader);
|
|
|
|
if (!em_utils_ask_open_many (window, uids->len))
|
|
goto exit;
|
|
|
|
if (em_utils_folder_is_drafts (registry, folder) ||
|
|
em_utils_folder_is_outbox (registry, folder) ||
|
|
em_utils_folder_is_templates (registry, folder)) {
|
|
|
|
e_mail_reader_edit_messages (reader, folder, uids, TRUE, TRUE);
|
|
|
|
ii = uids->len;
|
|
|
|
goto exit;
|
|
}
|
|
|
|
views = g_ptr_array_new ();
|
|
|
|
/* For vfolders we need to edit the original, not the vfolder copy. */
|
|
for (ii = 0; ii < uids->len; ii++) {
|
|
const gchar *uid = uids->pdata[ii];
|
|
CamelFolder *real_folder;
|
|
CamelMessageInfo *info;
|
|
gchar *real_uid;
|
|
|
|
if (!CAMEL_IS_VEE_FOLDER (folder)) {
|
|
g_ptr_array_add (views, g_strdup (uid));
|
|
continue;
|
|
}
|
|
|
|
info = camel_folder_get_message_info (folder, uid);
|
|
if (info == NULL)
|
|
continue;
|
|
|
|
real_folder = camel_vee_folder_get_location (
|
|
CAMEL_VEE_FOLDER (folder),
|
|
(CamelVeeMessageInfo *) info, &real_uid);
|
|
|
|
if (em_utils_folder_is_drafts (registry, real_folder) ||
|
|
em_utils_folder_is_outbox (registry, real_folder)) {
|
|
GPtrArray *edits;
|
|
|
|
edits = g_ptr_array_new ();
|
|
g_ptr_array_add (edits, real_uid);
|
|
e_mail_reader_edit_messages (
|
|
reader, real_folder, edits, TRUE, TRUE);
|
|
g_ptr_array_unref (edits);
|
|
} else {
|
|
g_free (real_uid);
|
|
g_ptr_array_add (views, g_strdup (uid));
|
|
}
|
|
|
|
camel_folder_free_message_info (folder, info);
|
|
}
|
|
|
|
for (ii = 0; ii < views->len; ii++) {
|
|
const gchar *uid = views->pdata[ii];
|
|
GtkWidget *browser;
|
|
MessageList *ml;
|
|
|
|
browser = e_mail_browser_new (
|
|
backend, folder, uid,
|
|
E_MAIL_FORMATTER_MODE_NORMAL);
|
|
|
|
e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
|
|
e_mail_reader_set_message (E_MAIL_READER (browser), uid);
|
|
|
|
ml = MESSAGE_LIST (e_mail_reader_get_message_list (
|
|
E_MAIL_READER (browser)));
|
|
message_list_freeze (ml);
|
|
|
|
copy_tree_state (reader, E_MAIL_READER (browser));
|
|
e_mail_reader_set_group_by_threads (
|
|
E_MAIL_READER (browser),
|
|
e_mail_reader_get_group_by_threads (reader));
|
|
|
|
message_list_thaw (ml);
|
|
gtk_widget_show (browser);
|
|
}
|
|
|
|
g_ptr_array_foreach (views, (GFunc) g_free, NULL);
|
|
g_ptr_array_free (views, TRUE);
|
|
|
|
exit:
|
|
g_clear_object (&folder);
|
|
g_ptr_array_unref (uids);
|
|
|
|
return ii;
|
|
}
|
|
|
|
static void
|
|
mail_reader_print_message_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
e_mail_printer_print_finish (
|
|
E_MAIL_PRINTER (source_object), result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:printing-failed",
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
|
|
} else {
|
|
/* Set activity as completed, and keep it displayed for a few
|
|
* seconds so that user can actually see the the printing was
|
|
* successfully finished. */
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
static void
|
|
mail_reader_print_parse_message_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EMailReader *reader;
|
|
EMailDisplay *mail_display;
|
|
EMailFormatter *formatter;
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
EMailPrinter *printer;
|
|
EMailPartList *part_list;
|
|
AsyncContext *async_context;
|
|
|
|
reader = E_MAIL_READER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
part_list = e_mail_reader_parse_message_finish (reader, result);
|
|
|
|
printer = e_mail_printer_new (part_list);
|
|
|
|
mail_display = e_mail_reader_get_mail_display (reader);
|
|
formatter = e_mail_display_get_formatter (mail_display);
|
|
|
|
e_activity_set_text (activity, _("Printing"));
|
|
|
|
e_mail_printer_print (
|
|
printer,
|
|
async_context->print_action,
|
|
formatter,
|
|
cancellable,
|
|
mail_reader_print_message_cb,
|
|
async_context);
|
|
|
|
g_object_unref (printer);
|
|
}
|
|
|
|
static void
|
|
mail_reader_print_get_message_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
CamelMimeMessage *message;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
message = camel_folder_get_message_finish (
|
|
CAMEL_FOLDER (source_object), result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((message != NULL) && (local_error == NULL)) ||
|
|
((message == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-retrieve-message",
|
|
local_error->message, NULL);
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
}
|
|
|
|
e_activity_set_text (activity, "");
|
|
|
|
e_mail_reader_parse_message (
|
|
async_context->reader,
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
message,
|
|
cancellable,
|
|
mail_reader_print_parse_message_cb,
|
|
async_context);
|
|
|
|
g_object_unref (message);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_print (EMailReader *reader,
|
|
GtkPrintOperationAction action)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
MessageList *message_list;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->folder = e_mail_reader_ref_folder (reader);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->message_uid = g_strdup (message_list->cursor_uid);
|
|
async_context->print_action = action;
|
|
|
|
camel_folder_get_message (
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
G_PRIORITY_DEFAULT, cancellable,
|
|
mail_reader_print_get_message_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
static void
|
|
mail_reader_remove_attachments_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
e_mail_folder_remove_attachments_finish (
|
|
CAMEL_FOLDER (source_object), result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink,
|
|
"mail:remove-attachments",
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_remove_attachments (EMailReader *reader)
|
|
{
|
|
EActivity *activity;
|
|
AsyncContext *async_context;
|
|
GCancellable *cancellable;
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
g_return_if_fail (uids != NULL);
|
|
|
|
/* Remove attachments asynchronously. */
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
|
|
e_mail_folder_remove_attachments (
|
|
folder, uids,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_remove_attachments_cb,
|
|
async_context);
|
|
|
|
g_object_unref (folder);
|
|
|
|
g_object_unref (activity);
|
|
|
|
g_ptr_array_unref (uids);
|
|
}
|
|
|
|
static void
|
|
mail_reader_remove_duplicates_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
CamelFolder *folder;
|
|
GHashTable *duplicates;
|
|
GtkWindow *parent_window;
|
|
guint n_duplicates;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
parent_window = e_mail_reader_get_window (async_context->reader);
|
|
|
|
duplicates = e_mail_folder_find_duplicate_messages_finish (
|
|
folder, result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((duplicates != NULL) && (local_error == NULL)) ||
|
|
((duplicates == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink,
|
|
"mail:find-duplicate-messages",
|
|
local_error->message, NULL);
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
}
|
|
|
|
/* Finalize the activity here so we don't leave a message in
|
|
* the task bar while prompting the user for confirmation. */
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
g_clear_object (&async_context->activity);
|
|
|
|
n_duplicates = g_hash_table_size (duplicates);
|
|
|
|
if (n_duplicates == 0) {
|
|
em_utils_prompt_user (
|
|
parent_window, NULL,
|
|
"mail:info-no-remove-duplicates",
|
|
camel_folder_get_display_name (folder), NULL);
|
|
} else {
|
|
gchar *confirmation;
|
|
gboolean proceed;
|
|
|
|
confirmation = g_strdup_printf (ngettext (
|
|
/* Translators: %s is replaced with a folder
|
|
* name %u with count of duplicate messages. */
|
|
"Folder '%s' contains %u duplicate message. "
|
|
"Are you sure you want to delete it?",
|
|
"Folder '%s' contains %u duplicate messages. "
|
|
"Are you sure you want to delete them?",
|
|
n_duplicates),
|
|
camel_folder_get_display_name (folder),
|
|
n_duplicates);
|
|
|
|
proceed = em_utils_prompt_user (
|
|
parent_window, NULL,
|
|
"mail:ask-remove-duplicates",
|
|
confirmation, NULL);
|
|
|
|
if (proceed) {
|
|
GHashTableIter iter;
|
|
gpointer key;
|
|
|
|
camel_folder_freeze (folder);
|
|
|
|
g_hash_table_iter_init (&iter, duplicates);
|
|
|
|
/* Mark duplicate messages for deletion. */
|
|
while (g_hash_table_iter_next (&iter, &key, NULL))
|
|
camel_folder_delete_message (folder, key);
|
|
|
|
camel_folder_thaw (folder);
|
|
}
|
|
|
|
g_free (confirmation);
|
|
}
|
|
|
|
g_hash_table_destroy (duplicates);
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_remove_duplicates (EMailReader *reader)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
g_return_if_fail (uids != NULL);
|
|
|
|
/* Find duplicate messages asynchronously. */
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
|
|
e_mail_folder_find_duplicate_messages (
|
|
folder, uids,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_remove_duplicates_cb,
|
|
async_context);
|
|
|
|
g_object_unref (folder);
|
|
|
|
g_object_unref (activity);
|
|
|
|
g_ptr_array_unref (uids);
|
|
}
|
|
|
|
static void
|
|
mail_reader_edit_messages_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EShell *shell;
|
|
EMailBackend *backend;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
GHashTable *hash_table;
|
|
GHashTableIter iter;
|
|
gpointer key, value;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
hash_table = e_mail_folder_get_multiple_messages_finish (
|
|
folder, result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((hash_table != NULL) && (local_error == NULL)) ||
|
|
((hash_table == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
goto exit;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink,
|
|
"mail:get-multiple-messages",
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
goto exit;
|
|
}
|
|
|
|
backend = e_mail_reader_get_backend (async_context->reader);
|
|
shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
|
|
|
/* Open each message in its own composer window. */
|
|
|
|
g_hash_table_iter_init (&iter, hash_table);
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
EMsgComposer *composer;
|
|
CamelMimeMessage *message;
|
|
const gchar *message_uid = NULL;
|
|
|
|
if (async_context->replace)
|
|
message_uid = (const gchar *) key;
|
|
|
|
message = CAMEL_MIME_MESSAGE (value);
|
|
|
|
camel_medium_remove_header (
|
|
CAMEL_MEDIUM (message), "X-Mailer");
|
|
|
|
composer = em_utils_edit_message (
|
|
shell, folder, message, message_uid,
|
|
async_context->keep_signature);
|
|
|
|
e_mail_reader_composer_created (
|
|
async_context->reader, composer, message);
|
|
}
|
|
|
|
g_hash_table_unref (hash_table);
|
|
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
|
|
exit:
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_edit_messages (EMailReader *reader,
|
|
CamelFolder *folder,
|
|
GPtrArray *uids,
|
|
gboolean replace,
|
|
gboolean keep_signature)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (uids != NULL);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->replace = replace;
|
|
async_context->keep_signature = keep_signature;
|
|
|
|
e_mail_folder_get_multiple_messages (
|
|
folder, uids,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_edit_messages_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
static void
|
|
mail_reader_forward_attachment_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EMailBackend *backend;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
CamelMimePart *part;
|
|
CamelDataWrapper *content;
|
|
EMsgComposer *composer;
|
|
gchar *subject = NULL;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
part = e_mail_folder_build_attachment_finish (
|
|
folder, result, &subject, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((part != NULL) && (local_error == NULL)) ||
|
|
((part == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_warn_if_fail (subject == NULL);
|
|
g_error_free (local_error);
|
|
goto exit;
|
|
|
|
} else if (local_error != NULL) {
|
|
g_warn_if_fail (subject == NULL);
|
|
e_alert_submit (
|
|
alert_sink,
|
|
"mail:get-multiple-messages",
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
goto exit;
|
|
}
|
|
|
|
backend = e_mail_reader_get_backend (async_context->reader);
|
|
|
|
composer = em_utils_forward_attachment (
|
|
backend, part, subject, folder, async_context->uids);
|
|
|
|
content = camel_medium_get_content (CAMEL_MEDIUM (part));
|
|
if (CAMEL_IS_MIME_MESSAGE (content)) {
|
|
e_mail_reader_composer_created (
|
|
async_context->reader, composer,
|
|
CAMEL_MIME_MESSAGE (content));
|
|
} else {
|
|
/* XXX What to do for the multipart/digest case?
|
|
* Extract the first message from the digest, or
|
|
* change the argument type to CamelMimePart and
|
|
* just pass the whole digest through?
|
|
*
|
|
* This signal is primarily serving EMailBrowser,
|
|
* which can only forward one message at a time.
|
|
* So for the moment it doesn't matter, but still
|
|
* something to consider. */
|
|
e_mail_reader_composer_created (
|
|
async_context->reader, composer, NULL);
|
|
}
|
|
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
|
|
g_object_unref (part);
|
|
g_free (subject);
|
|
|
|
exit:
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
static void
|
|
mail_reader_forward_messages_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
CamelFolder *folder;
|
|
EMailBackend *backend;
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
GHashTable *hash_table;
|
|
GHashTableIter iter;
|
|
gpointer key, value;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
folder = CAMEL_FOLDER (source_object);
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
backend = e_mail_reader_get_backend (async_context->reader);
|
|
|
|
hash_table = e_mail_folder_get_multiple_messages_finish (
|
|
folder, result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((hash_table != NULL) && (local_error == NULL)) ||
|
|
((hash_table == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
goto exit;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink,
|
|
"mail:get-multiple-messages",
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
goto exit;
|
|
}
|
|
|
|
/* Create a new composer window for each message. */
|
|
|
|
g_hash_table_iter_init (&iter, hash_table);
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
EMsgComposer *composer;
|
|
CamelMimeMessage *message;
|
|
const gchar *message_uid;
|
|
|
|
message_uid = (const gchar *) key;
|
|
message = CAMEL_MIME_MESSAGE (value);
|
|
|
|
composer = em_utils_forward_message (
|
|
backend, message,
|
|
async_context->forward_style,
|
|
folder, message_uid);
|
|
|
|
e_mail_reader_composer_created (
|
|
async_context->reader, composer, message);
|
|
}
|
|
|
|
g_hash_table_unref (hash_table);
|
|
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
|
|
exit:
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_forward_messages (EMailReader *reader,
|
|
CamelFolder *folder,
|
|
GPtrArray *uids,
|
|
EMailForwardStyle style)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (uids != NULL);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->uids = g_ptr_array_ref (uids);
|
|
async_context->forward_style = style;
|
|
|
|
switch (style) {
|
|
case E_MAIL_FORWARD_STYLE_ATTACHED:
|
|
e_mail_folder_build_attachment (
|
|
folder, uids,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_forward_attachment_cb,
|
|
async_context);
|
|
break;
|
|
|
|
case E_MAIL_FORWARD_STYLE_INLINE:
|
|
case E_MAIL_FORWARD_STYLE_QUOTED:
|
|
e_mail_folder_get_multiple_messages (
|
|
folder, uids,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_forward_messages_cb,
|
|
async_context);
|
|
break;
|
|
|
|
default:
|
|
g_warn_if_reached ();
|
|
}
|
|
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_reply_to_message()
|
|
* XXX This function belongs in e-html-utils.c */
|
|
static gboolean
|
|
html_contains_nonwhitespace (const gchar *html,
|
|
gint len)
|
|
{
|
|
const gchar *cp;
|
|
gunichar uc = 0;
|
|
|
|
if (html == NULL || len <= 0)
|
|
return FALSE;
|
|
|
|
cp = html;
|
|
|
|
while (cp != NULL && cp - html < len) {
|
|
uc = g_utf8_get_char (cp);
|
|
if (uc == 0)
|
|
break;
|
|
|
|
if (uc == '<') {
|
|
/* skip until next '>' */
|
|
uc = g_utf8_get_char (cp);
|
|
while (uc != 0 && uc != '>' && cp - html < len) {
|
|
cp = g_utf8_next_char (cp);
|
|
uc = g_utf8_get_char (cp);
|
|
}
|
|
if (uc == 0)
|
|
break;
|
|
} else if (uc == '&') {
|
|
/* sequence ' ' is a space */
|
|
if (g_ascii_strncasecmp (cp, " ", 6) == 0)
|
|
cp = cp + 5;
|
|
else
|
|
break;
|
|
} else if (!g_unichar_isspace (uc))
|
|
break;
|
|
|
|
cp = g_utf8_next_char (cp);
|
|
}
|
|
|
|
return cp - html < len - 1 && uc != 0;
|
|
}
|
|
|
|
static void
|
|
mail_reader_reply_message_parsed (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EShell *shell;
|
|
EMailBackend *backend;
|
|
EMailReader *reader = E_MAIL_READER (object);
|
|
EMailPartList *part_list;
|
|
EMsgComposer *composer;
|
|
CamelMimeMessage *message;
|
|
AsyncContext *async_context;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
part_list = e_mail_reader_parse_message_finish (reader, result);
|
|
message = e_mail_part_list_get_message (part_list);
|
|
|
|
backend = e_mail_reader_get_backend (async_context->reader);
|
|
shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
|
|
|
composer = em_utils_reply_to_message (
|
|
shell, message,
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
async_context->reply_type,
|
|
async_context->reply_style,
|
|
part_list,
|
|
async_context->address);
|
|
|
|
e_mail_reader_composer_created (reader, composer, message);
|
|
|
|
g_object_unref (part_list);
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
static void
|
|
mail_reader_get_message_ready_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
GCancellable *cancellable;
|
|
CamelMimeMessage *message;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
message = camel_folder_get_message_finish (
|
|
CAMEL_FOLDER (source_object), result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((message != NULL) && (local_error == NULL)) ||
|
|
((message == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-retrieve-message",
|
|
local_error->message, NULL);
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
}
|
|
|
|
e_mail_reader_parse_message (
|
|
async_context->reader,
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
message,
|
|
cancellable,
|
|
mail_reader_reply_message_parsed,
|
|
async_context);
|
|
|
|
g_object_unref (message);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_reply_to_message (EMailReader *reader,
|
|
CamelMimeMessage *src_message,
|
|
EMailReplyType reply_type)
|
|
{
|
|
EShell *shell;
|
|
EMailBackend *backend;
|
|
EShellBackend *shell_backend;
|
|
EMailDisplay *display;
|
|
EMailPartList *part_list = NULL;
|
|
GtkWidget *message_list;
|
|
CamelMimeMessage *new_message;
|
|
CamelInternetAddress *address = NULL;
|
|
CamelFolder *folder;
|
|
EMailReplyStyle reply_style;
|
|
EWebView *web_view;
|
|
struct _camel_header_raw *header;
|
|
const gchar *uid;
|
|
gchar *selection = NULL;
|
|
gint length;
|
|
gchar *mail_uri;
|
|
CamelObjectBag *registry;
|
|
EMsgComposer *composer;
|
|
EMailPartValidityFlags validity_pgp_sum = 0;
|
|
EMailPartValidityFlags validity_smime_sum = 0;
|
|
|
|
/* This handles quoting only selected text in the reply. If
|
|
* nothing is selected or only whitespace is selected, fall
|
|
* back to the normal em_utils_reply_to_message(). */
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
display = e_mail_reader_get_mail_display (reader);
|
|
message_list = e_mail_reader_get_message_list (reader);
|
|
reply_style = e_mail_reader_get_reply_style (reader);
|
|
|
|
shell_backend = E_SHELL_BACKEND (backend);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
|
|
web_view = E_WEB_VIEW (display);
|
|
|
|
if (reply_type == E_MAIL_REPLY_TO_RECIPIENT) {
|
|
const gchar *uri;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
|
|
if (uri) {
|
|
CamelURL *curl;
|
|
|
|
curl = camel_url_new (uri, NULL);
|
|
|
|
if (curl && curl->path && *curl->path) {
|
|
address = camel_internet_address_new ();
|
|
if (camel_address_decode (
|
|
CAMEL_ADDRESS (address),
|
|
curl->path) < 0) {
|
|
g_object_unref (address);
|
|
address = NULL;
|
|
}
|
|
}
|
|
|
|
if (curl)
|
|
camel_url_free (curl);
|
|
}
|
|
}
|
|
|
|
uid = MESSAGE_LIST (message_list)->cursor_uid;
|
|
g_return_if_fail (uid != NULL);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
|
|
if (!gtk_widget_get_visible (GTK_WIDGET (web_view)))
|
|
goto whole_message;
|
|
|
|
registry = e_mail_part_list_get_registry ();
|
|
mail_uri = e_mail_part_build_uri (folder, uid, NULL, NULL);
|
|
part_list = camel_object_bag_get (registry, mail_uri);
|
|
g_free (mail_uri);
|
|
|
|
if (!part_list) {
|
|
goto whole_message;
|
|
} else {
|
|
GQueue queue = G_QUEUE_INIT;
|
|
|
|
e_mail_part_list_queue_parts (part_list, NULL, &queue);
|
|
|
|
while (!g_queue_is_empty (&queue)) {
|
|
EMailPart *part = g_queue_pop_head (&queue);
|
|
GList *head, *link;
|
|
|
|
head = g_queue_peek_head_link (&part->validities);
|
|
|
|
for (link = head; link != NULL; link = g_list_next (link)) {
|
|
EMailPartValidityPair *vpair = link->data;
|
|
|
|
if (vpair == NULL)
|
|
continue;
|
|
|
|
if ((vpair->validity_type & E_MAIL_PART_VALIDITY_PGP) != 0)
|
|
validity_pgp_sum |= vpair->validity_type;
|
|
if ((vpair->validity_type & E_MAIL_PART_VALIDITY_SMIME) != 0)
|
|
validity_smime_sum |= vpair->validity_type;
|
|
}
|
|
|
|
g_object_unref (part);
|
|
}
|
|
}
|
|
|
|
if (src_message == NULL) {
|
|
src_message = e_mail_part_list_get_message (part_list);
|
|
if (src_message != NULL)
|
|
g_object_ref (src_message);
|
|
|
|
g_object_unref (part_list);
|
|
part_list = NULL;
|
|
|
|
g_return_if_fail (src_message != NULL);
|
|
} else {
|
|
g_object_unref (part_list);
|
|
part_list = NULL;
|
|
}
|
|
|
|
if (!e_web_view_is_selection_active (web_view))
|
|
goto whole_message;
|
|
|
|
selection = e_web_view_get_selection_html (web_view);
|
|
if (selection == NULL || *selection == '\0')
|
|
goto whole_message;
|
|
|
|
length = strlen (selection);
|
|
if (!html_contains_nonwhitespace (selection, length))
|
|
goto whole_message;
|
|
|
|
new_message = camel_mime_message_new ();
|
|
|
|
/* Filter out "content-*" headers. */
|
|
header = CAMEL_MIME_PART (src_message)->headers;
|
|
while (header != NULL) {
|
|
if (g_ascii_strncasecmp (header->name, "content-", 8) != 0)
|
|
camel_medium_add_header (
|
|
CAMEL_MEDIUM (new_message),
|
|
header->name, header->value);
|
|
|
|
header = header->next;
|
|
}
|
|
|
|
camel_mime_part_set_encoding (
|
|
CAMEL_MIME_PART (new_message),
|
|
CAMEL_TRANSFER_ENCODING_8BIT);
|
|
|
|
camel_mime_part_set_content (
|
|
CAMEL_MIME_PART (new_message),
|
|
selection, length, "text/html");
|
|
|
|
g_object_unref (src_message);
|
|
|
|
composer = em_utils_reply_to_message (
|
|
shell, new_message, folder, uid,
|
|
reply_type, reply_style, NULL, address);
|
|
if (validity_pgp_sum != 0 || validity_smime_sum != 0) {
|
|
GtkToggleAction *action;
|
|
|
|
if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_PGP) != 0) {
|
|
if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) {
|
|
action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_SIGN (composer));
|
|
gtk_toggle_action_set_active (action, TRUE);
|
|
}
|
|
|
|
if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) {
|
|
action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_ENCRYPT (composer));
|
|
gtk_toggle_action_set_active (action, TRUE);
|
|
}
|
|
}
|
|
|
|
if ((validity_smime_sum & E_MAIL_PART_VALIDITY_SMIME) != 0) {
|
|
if ((validity_smime_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) {
|
|
action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_SIGN (composer));
|
|
gtk_toggle_action_set_active (action, TRUE);
|
|
}
|
|
|
|
if ((validity_smime_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) {
|
|
action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer));
|
|
gtk_toggle_action_set_active (action, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
e_mail_reader_composer_created (reader, composer, new_message);
|
|
|
|
g_object_unref (new_message);
|
|
|
|
g_free (selection);
|
|
|
|
goto exit;
|
|
|
|
whole_message:
|
|
if (src_message == NULL) {
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->folder = g_object_ref (folder);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->message_uid = g_strdup (uid);
|
|
async_context->reply_type = reply_type;
|
|
async_context->reply_style = reply_style;
|
|
|
|
if (address != NULL)
|
|
async_context->address = g_object_ref (address);
|
|
|
|
camel_folder_get_message (
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_get_message_ready_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
|
|
} else {
|
|
composer = em_utils_reply_to_message (
|
|
shell, src_message, folder, uid,
|
|
reply_type, reply_style, part_list, address);
|
|
|
|
e_mail_reader_composer_created (reader, composer, src_message);
|
|
}
|
|
|
|
exit:
|
|
g_clear_object (&address);
|
|
g_clear_object (&folder);
|
|
}
|
|
|
|
static void
|
|
mail_reader_save_messages_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EAlertSink *alert_sink;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
e_mail_folder_save_messages_finish (
|
|
CAMEL_FOLDER (source_object), result, &local_error);
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
g_error_free (local_error);
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink,
|
|
"mail:save-messages",
|
|
local_error->message, NULL);
|
|
g_error_free (local_error);
|
|
}
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_save_messages (EMailReader *reader)
|
|
{
|
|
EShell *shell;
|
|
EActivity *activity;
|
|
EMailBackend *backend;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
EShellBackend *shell_backend;
|
|
CamelMessageInfo *info;
|
|
CamelFolder *folder;
|
|
GFile *destination;
|
|
GPtrArray *uids;
|
|
const gchar *message_uid;
|
|
const gchar *title;
|
|
gchar *suggestion = NULL;
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
backend = e_mail_reader_get_backend (reader);
|
|
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
g_return_if_fail (uids != NULL && uids->len > 0);
|
|
|
|
if (uids->len > 1) {
|
|
GtkWidget *message_list;
|
|
|
|
message_list = e_mail_reader_get_message_list (reader);
|
|
message_list_sort_uids (MESSAGE_LIST (message_list), uids);
|
|
}
|
|
|
|
message_uid = g_ptr_array_index (uids, 0);
|
|
|
|
title = ngettext ("Save Message", "Save Messages", uids->len);
|
|
|
|
/* Suggest as a filename the subject of the first message. */
|
|
info = camel_folder_get_message_info (folder, message_uid);
|
|
if (info != NULL) {
|
|
const gchar *subject;
|
|
|
|
subject = camel_message_info_subject (info);
|
|
if (subject != NULL)
|
|
suggestion = g_strconcat (subject, ".mbox", NULL);
|
|
camel_folder_free_message_info (folder, info);
|
|
}
|
|
|
|
if (suggestion == NULL) {
|
|
const gchar *basename;
|
|
|
|
/* Translators: This is part of a suggested file name
|
|
* used when saving a message or multiple messages to
|
|
* mbox format, when the first message doesn't have a
|
|
* subject. The extension ".mbox" is appended to the
|
|
* string; for example "Message.mbox". */
|
|
basename = ngettext ("Message", "Messages", uids->len);
|
|
suggestion = g_strconcat (basename, ".mbox", NULL);
|
|
}
|
|
|
|
shell_backend = E_SHELL_BACKEND (backend);
|
|
shell = e_shell_backend_get_shell (shell_backend);
|
|
|
|
destination = e_shell_run_save_dialog (
|
|
shell, title, suggestion,
|
|
"*.mbox:application/mbox,message/rfc822", NULL, NULL);
|
|
|
|
if (destination == NULL)
|
|
goto exit;
|
|
|
|
/* Save messages asynchronously. */
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
|
|
e_mail_folder_save_messages (
|
|
folder, uids,
|
|
destination,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_save_messages_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
|
|
g_object_unref (destination);
|
|
|
|
exit:
|
|
g_clear_object (&folder);
|
|
g_ptr_array_unref (uids);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_select_next_message (EMailReader *reader,
|
|
gboolean or_else_previous)
|
|
{
|
|
GtkWidget *message_list;
|
|
gboolean hide_deleted;
|
|
gboolean success;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
hide_deleted = e_mail_reader_get_hide_deleted (reader);
|
|
message_list = e_mail_reader_get_message_list (reader);
|
|
|
|
success = message_list_select (
|
|
MESSAGE_LIST (message_list),
|
|
MESSAGE_LIST_SELECT_NEXT, 0, 0);
|
|
|
|
if (!success && (hide_deleted || or_else_previous))
|
|
message_list_select (
|
|
MESSAGE_LIST (message_list),
|
|
MESSAGE_LIST_SELECT_PREVIOUS, 0, 0);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_create_filter_from_selected() */
|
|
static void
|
|
mail_reader_create_filter_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
EAlertSink *alert_sink;
|
|
CamelMimeMessage *message;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
message = camel_folder_get_message_finish (
|
|
CAMEL_FOLDER (source_object), result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((message != NULL) && (local_error == NULL)) ||
|
|
((message == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-retrieve-message",
|
|
local_error->message, NULL);
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
}
|
|
|
|
/* Finalize the activity here so we don't leave a message
|
|
* in the task bar while displaying the filter editor. */
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
g_clear_object (&async_context->activity);
|
|
|
|
backend = e_mail_reader_get_backend (async_context->reader);
|
|
session = e_mail_backend_get_session (backend);
|
|
|
|
/* Switch to Incoming filter in case the message contains a Received header */
|
|
if (g_str_equal (async_context->filter_source, E_FILTER_SOURCE_OUTGOING) &&
|
|
camel_medium_get_header (CAMEL_MEDIUM (message), "received"))
|
|
async_context->filter_source = E_FILTER_SOURCE_INCOMING;
|
|
|
|
filter_gui_add_from_message (
|
|
session, message,
|
|
async_context->filter_source,
|
|
async_context->filter_type);
|
|
|
|
g_object_unref (message);
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_create_filter_from_selected (EMailReader *reader,
|
|
gint filter_type)
|
|
{
|
|
EShell *shell;
|
|
EActivity *activity;
|
|
EMailBackend *backend;
|
|
AsyncContext *async_context;
|
|
GCancellable *cancellable;
|
|
ESourceRegistry *registry;
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
const gchar *filter_source;
|
|
const gchar *message_uid;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
|
|
registry = e_shell_get_registry (shell);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
g_return_if_fail (folder != NULL);
|
|
|
|
if (em_utils_folder_is_sent (registry, folder) ||
|
|
em_utils_folder_is_outbox (registry, folder))
|
|
filter_source = E_FILTER_SOURCE_OUTGOING;
|
|
else
|
|
filter_source = E_FILTER_SOURCE_INCOMING;
|
|
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
g_return_if_fail (uids != NULL && uids->len == 1);
|
|
message_uid = g_ptr_array_index (uids, 0);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->filter_source = filter_source;
|
|
async_context->filter_type = filter_type;
|
|
|
|
camel_folder_get_message (
|
|
folder, message_uid,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_create_filter_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
|
|
g_ptr_array_unref (uids);
|
|
|
|
g_object_unref (folder);
|
|
}
|
|
|
|
/* Helper for e_mail_reader_create_vfolder_from_selected() */
|
|
static void
|
|
mail_reader_create_vfolder_cb (GObject *source_object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
EActivity *activity;
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
EAlertSink *alert_sink;
|
|
CamelMimeMessage *message;
|
|
CamelFolder *use_folder;
|
|
AsyncContext *async_context;
|
|
GError *local_error = NULL;
|
|
|
|
async_context = (AsyncContext *) user_data;
|
|
|
|
activity = async_context->activity;
|
|
alert_sink = e_activity_get_alert_sink (activity);
|
|
|
|
message = camel_folder_get_message_finish (
|
|
CAMEL_FOLDER (source_object), result, &local_error);
|
|
|
|
/* Sanity check. */
|
|
g_return_if_fail (
|
|
((message != NULL) && (local_error == NULL)) ||
|
|
((message == NULL) && (local_error != NULL)));
|
|
|
|
if (e_activity_handle_cancellation (activity, local_error)) {
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
|
|
} else if (local_error != NULL) {
|
|
e_alert_submit (
|
|
alert_sink, "mail:no-retrieve-message",
|
|
local_error->message, NULL);
|
|
async_context_free (async_context);
|
|
g_error_free (local_error);
|
|
return;
|
|
}
|
|
|
|
/* Finalize the activity here so we don't leave a message
|
|
* in the task bar while displaying the vfolder editor. */
|
|
e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
|
|
g_clear_object (&async_context->activity);
|
|
|
|
backend = e_mail_reader_get_backend (async_context->reader);
|
|
session = e_mail_backend_get_session (backend);
|
|
|
|
use_folder = async_context->folder;
|
|
if (CAMEL_IS_VEE_FOLDER (use_folder)) {
|
|
CamelStore *parent_store;
|
|
CamelVeeFolder *vfolder;
|
|
|
|
parent_store = camel_folder_get_parent_store (use_folder);
|
|
vfolder = CAMEL_VEE_FOLDER (use_folder);
|
|
|
|
if (CAMEL_IS_VEE_STORE (parent_store) &&
|
|
vfolder == camel_vee_store_get_unmatched_folder (CAMEL_VEE_STORE (parent_store))) {
|
|
/* use source folder instead of the Unmatched folder */
|
|
use_folder = camel_vee_folder_get_vee_uid_folder (
|
|
vfolder, async_context->message_uid);
|
|
}
|
|
}
|
|
|
|
vfolder_gui_add_from_message (
|
|
session, message,
|
|
async_context->filter_type,
|
|
use_folder);
|
|
|
|
g_object_unref (message);
|
|
|
|
async_context_free (async_context);
|
|
}
|
|
|
|
void
|
|
e_mail_reader_create_vfolder_from_selected (EMailReader *reader,
|
|
gint vfolder_type)
|
|
{
|
|
EActivity *activity;
|
|
GCancellable *cancellable;
|
|
AsyncContext *async_context;
|
|
GPtrArray *uids;
|
|
const gchar *message_uid;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
uids = e_mail_reader_get_selected_uids (reader);
|
|
g_return_if_fail (uids != NULL && uids->len == 1);
|
|
message_uid = g_ptr_array_index (uids, 0);
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
cancellable = e_activity_get_cancellable (activity);
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->folder = e_mail_reader_ref_folder (reader);
|
|
async_context->reader = g_object_ref (reader);
|
|
async_context->message_uid = g_strdup (message_uid);
|
|
async_context->filter_type = vfolder_type;
|
|
|
|
camel_folder_get_message (
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
G_PRIORITY_DEFAULT,
|
|
cancellable,
|
|
mail_reader_create_vfolder_cb,
|
|
async_context);
|
|
|
|
g_object_unref (activity);
|
|
|
|
g_ptr_array_unref (uids);
|
|
}
|
|
|
|
static void
|
|
mail_reader_parse_message_run (GSimpleAsyncResult *simple,
|
|
GObject *object,
|
|
GCancellable *cancellable)
|
|
{
|
|
EMailReader *reader = E_MAIL_READER (object);
|
|
CamelObjectBag *registry;
|
|
EMailPartList *part_list;
|
|
AsyncContext *async_context;
|
|
gchar *mail_uri;
|
|
|
|
async_context = g_simple_async_result_get_op_res_gpointer (simple);
|
|
|
|
registry = e_mail_part_list_get_registry ();
|
|
|
|
mail_uri = e_mail_part_build_uri (
|
|
async_context->folder,
|
|
async_context->message_uid, NULL, NULL);
|
|
|
|
part_list = camel_object_bag_reserve (registry, mail_uri);
|
|
if (part_list == NULL) {
|
|
EMailBackend *mail_backend;
|
|
EMailSession *mail_session;
|
|
EMailParser *parser;
|
|
|
|
mail_backend = e_mail_reader_get_backend (reader);
|
|
mail_session = e_mail_backend_get_session (mail_backend);
|
|
|
|
parser = e_mail_parser_new (CAMEL_SESSION (mail_session));
|
|
|
|
part_list = e_mail_parser_parse_sync (
|
|
parser,
|
|
async_context->folder,
|
|
async_context->message_uid,
|
|
async_context->message,
|
|
cancellable);
|
|
|
|
g_object_unref (parser);
|
|
|
|
if (part_list == NULL)
|
|
camel_object_bag_abort (registry, mail_uri);
|
|
else
|
|
camel_object_bag_add (registry, mail_uri, part_list);
|
|
}
|
|
|
|
g_free (mail_uri);
|
|
|
|
async_context->part_list = part_list;
|
|
}
|
|
|
|
void
|
|
e_mail_reader_parse_message (EMailReader *reader,
|
|
CamelFolder *folder,
|
|
const gchar *message_uid,
|
|
CamelMimeMessage *message,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
GSimpleAsyncResult *simple;
|
|
AsyncContext *async_context;
|
|
EActivity *activity;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (message_uid != NULL);
|
|
g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
|
|
|
activity = e_mail_reader_new_activity (reader);
|
|
e_activity_set_cancellable (activity, cancellable);
|
|
e_activity_set_text (activity, _("Parsing message"));
|
|
|
|
async_context = g_slice_new0 (AsyncContext);
|
|
async_context->activity = g_object_ref (activity);
|
|
async_context->folder = g_object_ref (folder);
|
|
async_context->message_uid = g_strdup (message_uid);
|
|
async_context->message = g_object_ref (message);
|
|
|
|
simple = g_simple_async_result_new (
|
|
G_OBJECT (reader), callback, user_data,
|
|
e_mail_reader_parse_message);
|
|
|
|
g_simple_async_result_set_check_cancellable (simple, cancellable);
|
|
|
|
g_simple_async_result_set_op_res_gpointer (
|
|
simple, async_context, (GDestroyNotify) async_context_free);
|
|
|
|
g_simple_async_result_run_in_thread (
|
|
simple, mail_reader_parse_message_run,
|
|
G_PRIORITY_DEFAULT, cancellable);
|
|
|
|
g_object_unref (simple);
|
|
g_object_unref (activity);
|
|
}
|
|
|
|
EMailPartList *
|
|
e_mail_reader_parse_message_finish (EMailReader *reader,
|
|
GAsyncResult *result)
|
|
{
|
|
GSimpleAsyncResult *simple;
|
|
AsyncContext *async_context;
|
|
|
|
g_return_val_if_fail (
|
|
g_simple_async_result_is_valid (
|
|
result, G_OBJECT (reader),
|
|
e_mail_reader_parse_message), NULL);
|
|
|
|
simple = G_SIMPLE_ASYNC_RESULT (result);
|
|
async_context = g_simple_async_result_get_op_res_gpointer (simple);
|
|
|
|
if (async_context->part_list != NULL)
|
|
g_object_ref (async_context->part_list);
|
|
|
|
return async_context->part_list;
|
|
}
|