
* mail-ops.c (do_flag_messages): clean up the cleanup a bit svn path=/trunk/; revision=6906
2584 lines
66 KiB
C
2584 lines
66 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
/* mail-ops.c: callbacks for the mail toolbar/menus */
|
|
|
|
/*
|
|
* Author :
|
|
* Dan Winship <danw@helixcode.com>
|
|
* Jeffrey Stedfast <fejj@helixcode.com>
|
|
* Peter Williams <peterw@helixcode.com>
|
|
*
|
|
* Copyright 2000 Helix Code, Inc. (http://www.helixcode.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* 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 General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
* USA
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <gnome.h>
|
|
#include <ctype.h>
|
|
#include <camel/camel-mime-filter-from.h>
|
|
#include "mail.h"
|
|
#include "mail-threads.h"
|
|
#include "mail-tools.h"
|
|
#include "mail-ops.h"
|
|
#include "composer/e-msg-composer.h"
|
|
#include "folder-browser.h"
|
|
#include "e-util/e-html-utils.h"
|
|
|
|
/* ** FETCH MAIL ********************************************************** */
|
|
|
|
typedef struct fetch_mail_input_s
|
|
{
|
|
gchar *source_url;
|
|
gboolean keep_on_server;
|
|
CamelFolder *destination;
|
|
gpointer hook_func;
|
|
gpointer hook_data;
|
|
}
|
|
fetch_mail_input_t;
|
|
|
|
typedef struct fetch_mail_update_info_s {
|
|
gchar *name;
|
|
gchar *display;
|
|
gboolean new_messages;
|
|
} fetch_mail_update_info_t;
|
|
|
|
typedef struct fetch_mail_data_s {
|
|
gboolean empty;
|
|
EvolutionStorage *storage;
|
|
GPtrArray *update_infos;
|
|
} fetch_mail_data_t;
|
|
|
|
static gchar *
|
|
describe_fetch_mail (gpointer in_data, gboolean gerund)
|
|
{
|
|
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
|
|
char *name;
|
|
|
|
/*source = camel_session_get_store (session, input->source_url, NULL);
|
|
*if (source) {
|
|
* name = camel_service_get_name (CAMEL_SERVICE (source), FALSE);
|
|
* camel_object_unref (CAMEL_OBJECT (source));
|
|
*} else
|
|
*/
|
|
name = input->source_url;
|
|
|
|
if (gerund)
|
|
return g_strdup_printf (_("Fetching email from %s"), name);
|
|
else
|
|
return g_strdup_printf (_("Fetch email from %s"), name);
|
|
}
|
|
|
|
static void
|
|
setup_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
|
|
fetch_mail_data_t *data = (fetch_mail_data_t *) op_data;
|
|
|
|
data->empty = FALSE;
|
|
data->storage = NULL;
|
|
data->update_infos = NULL;
|
|
|
|
if (input->destination)
|
|
camel_object_ref (CAMEL_OBJECT (input->destination));
|
|
}
|
|
|
|
static FilterContext *
|
|
mail_load_evolution_rule_context ()
|
|
{
|
|
gchar *userrules;
|
|
gchar *systemrules;
|
|
FilterContext *fc;
|
|
|
|
userrules = g_strdup_printf ("%s/filters.xml", evolution_dir);
|
|
systemrules = g_strdup_printf ("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
|
|
fc = filter_context_new ();
|
|
rule_context_load ((RuleContext *)fc, systemrules, userrules);
|
|
g_free (userrules);
|
|
g_free (systemrules);
|
|
|
|
return fc;
|
|
}
|
|
|
|
static void
|
|
mail_op_report_status (FilterDriver *driver, enum filter_status_t status, const char *desc, void *data)
|
|
{
|
|
/* FIXME: make it work */
|
|
switch (status) {
|
|
case FILTER_STATUS_START:
|
|
mail_op_set_message_plain (desc);
|
|
break;
|
|
case FILTER_STATUS_END:
|
|
break;
|
|
case FILTER_STATUS_ACTION:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_changed_folders (CamelStore *store, CamelFolderInfo *info,
|
|
EvolutionStorage *storage, const char *path,
|
|
GPtrArray *update_infos, CamelException *ex)
|
|
{
|
|
char *name;
|
|
|
|
name = g_strdup_printf ("%s/%s", path, info->name);
|
|
|
|
if (info->url) {
|
|
CamelFolder *folder;
|
|
fetch_mail_update_info_t *update_info;
|
|
|
|
update_info = g_new (fetch_mail_update_info_t, 1);
|
|
update_info->name = g_strdup (name);
|
|
|
|
if (info->unread_message_count > 0) {
|
|
update_info->new_messages = TRUE;
|
|
update_info->display = g_strdup_printf ("%s (%d)", info->name,
|
|
info->unread_message_count);
|
|
} else {
|
|
update_info->new_messages = FALSE;
|
|
update_info->display = g_strdup (info->name);
|
|
}
|
|
|
|
/* This is a bit of a hack... if the store is already
|
|
* caching the folder, then we update it. Otherwise
|
|
* we don't.
|
|
*/
|
|
folder = CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (store))->
|
|
lookup_folder (store, info->full_name);
|
|
if (folder) {
|
|
camel_folder_sync (folder, FALSE, ex);
|
|
if (!camel_exception_is_set (ex))
|
|
camel_folder_refresh_info (folder, ex);
|
|
camel_object_unref (CAMEL_OBJECT (folder));
|
|
}
|
|
|
|
/* Save our info to update */
|
|
g_ptr_array_add (update_infos, update_info);
|
|
}
|
|
if (!camel_exception_is_set (ex) && info->sibling) {
|
|
update_changed_folders (store, info->sibling, storage,
|
|
path, update_infos, ex);
|
|
}
|
|
if (!camel_exception_is_set (ex) && info->child) {
|
|
update_changed_folders (store, info->child, storage,
|
|
name, update_infos, ex);
|
|
}
|
|
g_free (name);
|
|
}
|
|
|
|
static void
|
|
do_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
|
|
fetch_mail_data_t *data = (fetch_mail_data_t *) op_data;
|
|
FilterContext *fc;
|
|
FilterDriver *filter;
|
|
FILE *logfile = NULL;
|
|
CamelFolder *folder;
|
|
|
|
/* FIXME: This shouldn't be checking for "imap" specifically. */
|
|
if (!strncmp (input->source_url, "imap:", 5)) {
|
|
CamelStore *store;
|
|
CamelFolderInfo *info;
|
|
EvolutionStorage *storage;
|
|
|
|
store = camel_session_get_store (session, input->source_url, ex);
|
|
if (!store)
|
|
return;
|
|
storage = mail_lookup_storage (store);
|
|
g_return_if_fail (storage != NULL);
|
|
|
|
info = camel_store_get_folder_info (store, NULL, FALSE,
|
|
TRUE, TRUE, ex);
|
|
if (!info) {
|
|
camel_object_unref (CAMEL_OBJECT (store));
|
|
gtk_object_unref (GTK_OBJECT (storage));
|
|
return;
|
|
}
|
|
|
|
data->storage = storage;
|
|
data->update_infos = g_ptr_array_new ();
|
|
update_changed_folders (store, info, storage, "", data->update_infos, ex);
|
|
|
|
camel_store_free_folder_info (store, info);
|
|
camel_object_unref (CAMEL_OBJECT (store));
|
|
gtk_object_unref (GTK_OBJECT (storage));
|
|
|
|
data->empty = FALSE;
|
|
return;
|
|
}
|
|
|
|
if (input->destination == NULL) {
|
|
input->destination = mail_tool_get_local_inbox (ex);
|
|
|
|
if (input->destination == NULL)
|
|
return;
|
|
}
|
|
|
|
/* setup filter driver */
|
|
fc = mail_load_evolution_rule_context ();
|
|
filter = filter_driver_new (fc, mail_tool_filter_get_folder_func, 0);
|
|
filter_driver_set_default_folder (filter, input->destination);
|
|
|
|
if (TRUE /* perform_logging */) {
|
|
char *filename = g_strdup_printf ("%s/evolution-filter-log", evolution_dir);
|
|
logfile = fopen (filename, "a+");
|
|
g_free (filename);
|
|
}
|
|
|
|
filter_driver_set_logfile (filter, logfile);
|
|
filter_driver_set_status_func (filter, mail_op_report_status, NULL);
|
|
|
|
/* why on earth we 'up' a lock to get it, ... */
|
|
mail_tool_camel_lock_up ();
|
|
|
|
camel_folder_freeze (input->destination);
|
|
|
|
if (!strncmp (input->source_url, "mbox:", 5)) {
|
|
char *path = mail_tool_do_movemail (input->source_url, ex);
|
|
|
|
if (path && !camel_exception_is_set (ex)) {
|
|
filter_driver_filter_mbox (filter, path, FILTER_SOURCE_INCOMING, ex);
|
|
|
|
/* ok? zap the output file */
|
|
if (!camel_exception_is_set (ex)) {
|
|
unlink (path);
|
|
}
|
|
}
|
|
g_free (path);
|
|
} else {
|
|
folder = mail_tool_get_inbox (input->source_url, ex);
|
|
|
|
if (folder) {
|
|
if (camel_folder_get_message_count (folder) > 0) {
|
|
CamelUIDCache *cache = NULL;
|
|
GPtrArray *uids;
|
|
|
|
uids = camel_folder_get_uids (folder);
|
|
if (input->keep_on_server) {
|
|
char *cachename = mail_config_folder_to_cachename (folder, "cache-");
|
|
|
|
cache = camel_uid_cache_new (cachename);
|
|
if (cache) {
|
|
GPtrArray *new_uids;
|
|
|
|
new_uids = camel_uid_cache_get_new_uids (cache, uids);
|
|
camel_folder_free_uids (folder, uids);
|
|
uids = new_uids;
|
|
}
|
|
|
|
g_free (cachename);
|
|
}
|
|
|
|
filter_driver_filter_folder (filter, folder, FILTER_SOURCE_INCOMING,
|
|
uids, !input->keep_on_server, ex);
|
|
|
|
if (cache) {
|
|
/* save the cache for the next time we fetch mail! */
|
|
camel_uid_cache_free_uids (uids);
|
|
|
|
if (!camel_exception_is_set (ex))
|
|
camel_uid_cache_save (cache);
|
|
camel_uid_cache_destroy (cache);
|
|
} else
|
|
camel_folder_free_uids (folder, uids);
|
|
} else {
|
|
data->empty = TRUE;
|
|
}
|
|
|
|
/* sync and expunge */
|
|
camel_folder_sync (folder, TRUE, ex);
|
|
|
|
camel_object_unref (CAMEL_OBJECT (folder));
|
|
} else {
|
|
data->empty = TRUE;
|
|
}
|
|
}
|
|
|
|
if (logfile)
|
|
fclose (logfile);
|
|
|
|
camel_folder_thaw (input->destination);
|
|
|
|
mail_tool_camel_lock_down ();
|
|
|
|
/*camel_object_unref (CAMEL_OBJECT (input->destination));*/
|
|
gtk_object_unref (GTK_OBJECT (filter));
|
|
}
|
|
|
|
static void
|
|
cleanup_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
|
|
fetch_mail_data_t *data = (fetch_mail_data_t *) op_data;
|
|
|
|
if (data->empty && !camel_exception_is_set (ex))
|
|
mail_op_set_message (_("There is no new mail at %s."),
|
|
input->source_url);
|
|
|
|
if (data->update_infos) {
|
|
int i;
|
|
|
|
for (i = 0; i < data->update_infos->len; i++) {
|
|
fetch_mail_update_info_t *update_info;
|
|
|
|
update_info = (fetch_mail_update_info_t *) data->update_infos->pdata[i];
|
|
evolution_storage_update_folder (data->storage,
|
|
update_info->name,
|
|
update_info->display,
|
|
update_info->new_messages);
|
|
g_free (update_info->name);
|
|
g_free (update_info->display);
|
|
g_free (update_info);
|
|
}
|
|
|
|
g_ptr_array_free (data->update_infos, TRUE);
|
|
}
|
|
|
|
g_free (input->source_url);
|
|
if (input->destination)
|
|
camel_object_unref (CAMEL_OBJECT (input->destination));
|
|
}
|
|
|
|
static const mail_operation_spec op_fetch_mail = {
|
|
describe_fetch_mail,
|
|
sizeof (fetch_mail_data_t),
|
|
setup_fetch_mail,
|
|
do_fetch_mail,
|
|
cleanup_fetch_mail
|
|
};
|
|
|
|
void
|
|
mail_do_fetch_mail (const gchar *source_url, gboolean keep_on_server,
|
|
CamelFolder *destination,
|
|
gpointer hook_func, gpointer hook_data)
|
|
{
|
|
fetch_mail_input_t *input;
|
|
|
|
g_return_if_fail (source_url != NULL);
|
|
g_return_if_fail (destination == NULL ||
|
|
CAMEL_IS_FOLDER (destination));
|
|
|
|
input = g_new (fetch_mail_input_t, 1);
|
|
input->source_url = g_strdup (source_url);
|
|
input->keep_on_server = keep_on_server;
|
|
input->destination = destination;
|
|
input->hook_func = hook_func;
|
|
input->hook_data = hook_data;
|
|
|
|
mail_operation_queue (&op_fetch_mail, input, TRUE);
|
|
}
|
|
|
|
/* ** FILTER ON DEMAND ********************************************************** */
|
|
|
|
/* why do we have this separate code, it is basically a copy of the code above,
|
|
should be consolidated */
|
|
|
|
typedef struct filter_ondemand_input_s {
|
|
CamelFolder *source;
|
|
GPtrArray *uids;
|
|
} filter_ondemand_input_t;
|
|
|
|
static gchar *
|
|
describe_filter_ondemand (gpointer in_data, gboolean gerund)
|
|
{
|
|
if (gerund)
|
|
return g_strdup_printf (_("Filtering email on demand"));
|
|
else
|
|
return g_strdup_printf (_("Filter email on demand"));
|
|
}
|
|
|
|
static void
|
|
setup_filter_ondemand (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->source));
|
|
}
|
|
|
|
static void
|
|
do_filter_ondemand (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;
|
|
FilterDriver *driver;
|
|
FilterContext *context;
|
|
FILE *logfile = NULL;
|
|
int i;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
if (camel_folder_get_message_count (input->source) == 0) {
|
|
mail_tool_camel_lock_down ();
|
|
return;
|
|
}
|
|
|
|
/* create the filter context */
|
|
context = mail_load_evolution_rule_context ();
|
|
|
|
if (((RuleContext *)context)->error) {
|
|
gtk_object_unref (GTK_OBJECT (context));
|
|
|
|
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
|
|
"Cannot apply filters: failed to load filter rules.");
|
|
|
|
mail_tool_camel_lock_down ();
|
|
return;
|
|
}
|
|
|
|
/* setup filter driver - no default destination */
|
|
driver = filter_driver_new (context, mail_tool_filter_get_folder_func, NULL);
|
|
|
|
if (TRUE /* perform_logging */) {
|
|
char *filename;
|
|
|
|
filename = g_strdup_printf ("%s/evolution-filter-log", evolution_dir);
|
|
logfile = fopen (filename, "a+");
|
|
g_free (filename);
|
|
}
|
|
|
|
filter_driver_set_logfile (driver, logfile);
|
|
filter_driver_set_status_func (driver, mail_op_report_status, NULL);
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
CamelMimeMessage *message;
|
|
CamelMessageInfo *info;
|
|
|
|
message = camel_folder_get_message (input->source, input->uids->pdata[i], ex);
|
|
info = (CamelMessageInfo *) camel_folder_get_message_info (input->source, input->uids->pdata[i]);
|
|
|
|
/* filter the message - use "incoming" rules since we don't want special "demand" filters? */
|
|
filter_driver_filter_message (driver, message, info, "", FILTER_SOURCE_INCOMING, ex);
|
|
}
|
|
|
|
if (logfile)
|
|
fclose (logfile);
|
|
|
|
/* sync the source folder */
|
|
camel_folder_sync (input->source, FALSE, ex);
|
|
|
|
gtk_object_unref (GTK_OBJECT (driver));
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_filter_ondemand (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;
|
|
int i;
|
|
|
|
if (input->source)
|
|
camel_object_unref (CAMEL_OBJECT (input->source));
|
|
|
|
for (i = 0; i < input->uids->len; i++)
|
|
g_free (input->uids->pdata[i]);
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
}
|
|
|
|
static const mail_operation_spec op_filter_ondemand = {
|
|
describe_filter_ondemand,
|
|
0,
|
|
setup_filter_ondemand,
|
|
do_filter_ondemand,
|
|
cleanup_filter_ondemand
|
|
};
|
|
|
|
void
|
|
mail_do_filter_ondemand (CamelFolder *source, GPtrArray *uids)
|
|
{
|
|
filter_ondemand_input_t *input;
|
|
|
|
g_return_if_fail (source == NULL || CAMEL_IS_FOLDER (source));
|
|
|
|
input = g_new (filter_ondemand_input_t, 1);
|
|
input->source = source;
|
|
input->uids = uids;
|
|
|
|
mail_operation_queue (&op_filter_ondemand, input, TRUE);
|
|
}
|
|
|
|
/* ** SEND MAIL *********************************************************** */
|
|
|
|
typedef struct send_mail_input_s
|
|
{
|
|
gchar *xport_uri;
|
|
CamelMimeMessage *message;
|
|
|
|
/* If done_folder != NULL, will add done_flags to
|
|
* the flags of the message done_uid in done_folder. */
|
|
|
|
CamelFolder *done_folder;
|
|
char *done_uid;
|
|
guint32 done_flags;
|
|
|
|
GtkWidget *composer;
|
|
}
|
|
send_mail_input_t;
|
|
|
|
static gchar *
|
|
describe_send_mail (gpointer in_data, gboolean gerund)
|
|
{
|
|
send_mail_input_t *input = (send_mail_input_t *) in_data;
|
|
|
|
if (gerund) {
|
|
if (input->message->subject && input->message->subject[0])
|
|
return g_strdup_printf (_("Sending \"%s\""),
|
|
input->message->subject);
|
|
else
|
|
return
|
|
g_strdup
|
|
(_("Sending a message without a subject"));
|
|
} else {
|
|
if (input->message->subject && input->message->subject[0])
|
|
return g_strdup_printf (_("Send \"%s\""),
|
|
input->message->subject);
|
|
else
|
|
return g_strdup (_("Send a message without a subject"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_send_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
send_mail_input_t *input = (send_mail_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->message));
|
|
if (input->done_folder)
|
|
camel_object_ref (CAMEL_OBJECT (input->done_folder));
|
|
if (input->composer) {
|
|
gtk_object_ref (GTK_OBJECT (input->composer));
|
|
gtk_widget_hide (GTK_WIDGET (input->composer));
|
|
}
|
|
}
|
|
|
|
static void
|
|
do_send_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
send_mail_input_t *input = (send_mail_input_t *) in_data;
|
|
extern CamelFolder *sent_folder;
|
|
CamelMessageInfo *info;
|
|
CamelTransport *xport;
|
|
FilterContext *context;
|
|
char *x_mailer;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
x_mailer = g_strdup_printf ("Evolution %s (Developer Preview)", VERSION);
|
|
camel_medium_add_header (CAMEL_MEDIUM (input->message), "X-Mailer",
|
|
x_mailer);
|
|
g_free (x_mailer);
|
|
camel_mime_message_set_date (input->message,
|
|
CAMEL_MESSAGE_DATE_CURRENT, 0);
|
|
|
|
xport = camel_session_get_transport (session, input->xport_uri, ex);
|
|
mail_tool_camel_lock_down ();
|
|
if (camel_exception_is_set (ex))
|
|
return;
|
|
|
|
mail_tool_send_via_transport (xport, CAMEL_MEDIUM (input->message), ex);
|
|
camel_object_unref (CAMEL_OBJECT (xport));
|
|
|
|
if (camel_exception_is_set (ex))
|
|
return;
|
|
|
|
/* if we replied to a message, mark the appropriate flags and stuff */
|
|
if (input->done_folder) {
|
|
guint32 set;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
set = camel_folder_get_message_flags (input->done_folder,
|
|
input->done_uid);
|
|
camel_folder_set_message_flags (input->done_folder,
|
|
input->done_uid,
|
|
input->done_flags,
|
|
input->done_flags);
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
/* now lets run it through the outgoing filters */
|
|
|
|
info = g_new0 (CamelMessageInfo, 1);
|
|
info->flags = CAMEL_MESSAGE_SEEN;
|
|
|
|
/* setup filter driver */
|
|
context = mail_load_evolution_rule_context ();
|
|
|
|
if (!((RuleContext *)context)->error) {
|
|
FilterDriver *driver;
|
|
FILE *logfile;
|
|
|
|
driver = filter_driver_new (context, mail_tool_filter_get_folder_func, NULL);
|
|
|
|
if (TRUE /* perform_logging */) {
|
|
char *filename;
|
|
|
|
filename = g_strdup_printf ("%s/evolution-filter-log", evolution_dir);
|
|
logfile = fopen (filename, "a+");
|
|
g_free (filename);
|
|
}
|
|
|
|
filter_driver_filter_message (driver, input->message, info, "", FILTER_SOURCE_OUTGOING, ex);
|
|
|
|
gtk_object_unref (GTK_OBJECT (driver));
|
|
|
|
if (logfile)
|
|
fclose (logfile);
|
|
}
|
|
|
|
/* now to save the message in Sent */
|
|
if (sent_folder) {
|
|
mail_tool_camel_lock_up ();
|
|
|
|
camel_folder_append_message (sent_folder, input->message, info, ex);
|
|
g_free (info);
|
|
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
cleanup_send_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
send_mail_input_t *input = (send_mail_input_t *) in_data;
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->message));
|
|
if (input->done_folder)
|
|
camel_object_unref (CAMEL_OBJECT (input->done_folder));
|
|
|
|
g_free (input->xport_uri);
|
|
g_free (input->done_uid);
|
|
|
|
if (input->composer) {
|
|
if (!camel_exception_is_set (ex))
|
|
gtk_widget_destroy (input->composer);
|
|
else
|
|
gtk_widget_show (input->composer);
|
|
}
|
|
}
|
|
|
|
static const mail_operation_spec op_send_mail = {
|
|
describe_send_mail,
|
|
0,
|
|
setup_send_mail,
|
|
do_send_mail,
|
|
cleanup_send_mail
|
|
};
|
|
|
|
void
|
|
mail_do_send_mail (const char *xport_uri,
|
|
CamelMimeMessage *message,
|
|
CamelFolder *done_folder,
|
|
const char *done_uid,
|
|
guint32 done_flags, GtkWidget *composer)
|
|
{
|
|
send_mail_input_t *input;
|
|
|
|
g_return_if_fail (xport_uri != NULL);
|
|
g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
|
g_return_if_fail (done_folder == NULL ||
|
|
CAMEL_IS_FOLDER (done_folder));
|
|
g_return_if_fail (done_folder == NULL || done_uid != NULL);
|
|
|
|
input = g_new (send_mail_input_t, 1);
|
|
input->xport_uri = g_strdup (xport_uri);
|
|
input->message = message;
|
|
input->done_folder = done_folder;
|
|
input->done_uid = g_strdup (done_uid);
|
|
input->done_flags = done_flags;
|
|
input->composer = composer;
|
|
|
|
mail_operation_queue (&op_send_mail, input, TRUE);
|
|
}
|
|
|
|
/* ** SEND MAIL QUEUE ***************************************************** */
|
|
|
|
typedef struct send_queue_input_s
|
|
{
|
|
CamelFolder *folder_queue;
|
|
gchar *xport_uri;
|
|
}
|
|
send_queue_input_t;
|
|
|
|
static gchar *
|
|
describe_send_queue (gpointer in_data, gboolean gerund)
|
|
{
|
|
/*send_queue_input_t *input = (send_queue_input_t *) in_data;*/
|
|
|
|
if (gerund) {
|
|
return g_strdup_printf (_("Sending queue"));
|
|
} else {
|
|
return g_strdup_printf (_("Send queue"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_send_queue (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
send_queue_input_t *input = (send_queue_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->folder_queue));
|
|
}
|
|
|
|
static void
|
|
do_send_queue (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
send_queue_input_t *input = (send_queue_input_t *) in_data;
|
|
extern CamelFolder *sent_folder;
|
|
CamelTransport *xport;
|
|
GPtrArray *uids;
|
|
char *x_mailer;
|
|
guint32 set;
|
|
int i;
|
|
|
|
uids = camel_folder_get_uids (input->folder_queue);
|
|
if (!uids)
|
|
return;
|
|
|
|
x_mailer = g_strdup_printf ("Evolution %s (Developer Preview)",
|
|
VERSION);
|
|
|
|
for (i = 0; i < uids->len; i++) {
|
|
CamelMimeMessage *message;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
|
|
message = camel_folder_get_message (input->folder_queue, uids->pdata[i], ex);
|
|
if (camel_exception_is_set (ex))
|
|
break;
|
|
|
|
camel_medium_add_header (CAMEL_MEDIUM (message), "X-Mailer", x_mailer);
|
|
|
|
camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0);
|
|
|
|
xport = camel_session_get_transport (session, input->xport_uri, ex);
|
|
mail_tool_camel_lock_down ();
|
|
if (camel_exception_is_set (ex))
|
|
break;
|
|
|
|
mail_tool_send_via_transport (xport, CAMEL_MEDIUM (message), ex);
|
|
camel_object_unref (CAMEL_OBJECT (xport));
|
|
|
|
if (camel_exception_is_set (ex))
|
|
break;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
set = camel_folder_get_message_flags (input->folder_queue,
|
|
uids->pdata[i]);
|
|
camel_folder_set_message_flags (input->folder_queue,
|
|
uids->pdata[i],
|
|
CAMEL_MESSAGE_DELETED, ~set);
|
|
mail_tool_camel_lock_down ();
|
|
|
|
/* now to save the message in Sent */
|
|
if (sent_folder) {
|
|
CamelMessageInfo *info;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
|
|
info = g_new0 (CamelMessageInfo, 1);
|
|
info->flags = CAMEL_MESSAGE_SEEN;
|
|
camel_folder_append_message (sent_folder, message, info, ex);
|
|
g_free (info);
|
|
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
}
|
|
|
|
g_free (x_mailer);
|
|
|
|
for (i = 0; i < uids->len; i++)
|
|
g_free (uids->pdata[i]);
|
|
g_ptr_array_free (uids, TRUE);
|
|
}
|
|
|
|
static void
|
|
cleanup_send_queue (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
send_queue_input_t *input = (send_queue_input_t *) in_data;
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->folder_queue));
|
|
|
|
g_free (input->xport_uri);
|
|
}
|
|
|
|
static const mail_operation_spec op_send_queue = {
|
|
describe_send_queue,
|
|
0,
|
|
setup_send_queue,
|
|
do_send_queue,
|
|
cleanup_send_queue
|
|
};
|
|
|
|
void
|
|
mail_do_send_queue (CamelFolder *folder_queue,
|
|
const char *xport_uri)
|
|
{
|
|
send_queue_input_t *input;
|
|
|
|
g_return_if_fail (xport_uri != NULL);
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder_queue));
|
|
|
|
input = g_new (send_queue_input_t, 1);
|
|
input->xport_uri = g_strdup (xport_uri);
|
|
input->folder_queue = folder_queue;
|
|
|
|
mail_operation_queue (&op_send_queue, input, TRUE);
|
|
}
|
|
|
|
|
|
/* ** APPEND MESSAGE TO FOLDER ******************************************** */
|
|
|
|
typedef struct append_mail_input_s
|
|
{
|
|
CamelFolder *folder;
|
|
CamelMimeMessage *message;
|
|
CamelMessageInfo *info;
|
|
}
|
|
append_mail_input_t;
|
|
|
|
static gchar *
|
|
describe_append_mail (gpointer in_data, gboolean gerund)
|
|
{
|
|
append_mail_input_t *input = (append_mail_input_t *) in_data;
|
|
|
|
if (gerund) {
|
|
if (input->message->subject && input->message->subject[0])
|
|
return g_strdup_printf (_("Appending \"%s\""),
|
|
input->message->subject);
|
|
else
|
|
return
|
|
g_strdup (_("Appending a message without a subject"));
|
|
} else {
|
|
if (input->message->subject && input->message->subject[0])
|
|
return g_strdup_printf (_("Appending \"%s\""),
|
|
input->message->subject);
|
|
else
|
|
return g_strdup (_("Appending a message without a subject"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_append_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
append_mail_input_t *input = (append_mail_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->message));
|
|
camel_object_ref (CAMEL_OBJECT (input->folder));
|
|
}
|
|
|
|
static void
|
|
do_append_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
append_mail_input_t *input = (append_mail_input_t *) in_data;
|
|
|
|
camel_mime_message_set_date (input->message,
|
|
CAMEL_MESSAGE_DATE_CURRENT, 0);
|
|
|
|
mail_tool_camel_lock_up ();
|
|
|
|
/* now to save the message in the specified folder */
|
|
camel_folder_append_message (input->folder, input->message, input->info, ex);
|
|
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_append_mail (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
append_mail_input_t *input = (append_mail_input_t *) in_data;
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->message));
|
|
camel_object_unref (CAMEL_OBJECT (input->folder));
|
|
}
|
|
|
|
static const mail_operation_spec op_append_mail = {
|
|
describe_append_mail,
|
|
0,
|
|
setup_append_mail,
|
|
do_append_mail,
|
|
cleanup_append_mail
|
|
};
|
|
|
|
void
|
|
mail_do_append_mail (CamelFolder *folder,
|
|
CamelMimeMessage *message,
|
|
CamelMessageInfo *info)
|
|
{
|
|
append_mail_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
|
|
|
|
input = g_new (append_mail_input_t, 1);
|
|
input->folder = folder;
|
|
input->message = message;
|
|
input->info = info;
|
|
|
|
mail_operation_queue (&op_append_mail, input, TRUE);
|
|
}
|
|
|
|
/* ** EXPUNGE FOLDER ****************************************************** */
|
|
|
|
static gchar *
|
|
describe_expunge_folder (gpointer in_data, gboolean gerund)
|
|
{
|
|
CamelFolder *f = CAMEL_FOLDER (in_data);
|
|
|
|
if (gerund)
|
|
return g_strdup_printf (_("Expunging \"%s\""), mail_tool_get_folder_name (f));
|
|
else
|
|
return g_strdup_printf (_("Expunge \"%s\""), mail_tool_get_folder_name (f));
|
|
}
|
|
|
|
static void
|
|
setup_expunge_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
camel_object_ref (CAMEL_OBJECT (in_data));
|
|
}
|
|
|
|
static void
|
|
do_expunge_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
mail_tool_camel_lock_up ();
|
|
camel_folder_expunge (CAMEL_FOLDER (in_data), ex);
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_expunge_folder (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
camel_object_unref (CAMEL_OBJECT (in_data));
|
|
}
|
|
|
|
static const mail_operation_spec op_expunge_folder = {
|
|
describe_expunge_folder,
|
|
0,
|
|
setup_expunge_folder,
|
|
do_expunge_folder,
|
|
cleanup_expunge_folder
|
|
};
|
|
|
|
void
|
|
mail_do_expunge_folder (CamelFolder *folder)
|
|
{
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
|
|
mail_operation_queue (&op_expunge_folder, folder, FALSE);
|
|
}
|
|
|
|
/* ** TRANSFER MESSAGES **************************************************** */
|
|
|
|
typedef struct transfer_messages_input_s
|
|
{
|
|
CamelFolder *source;
|
|
GPtrArray *uids;
|
|
gboolean delete_from_source;
|
|
gchar *dest_uri;
|
|
}
|
|
transfer_messages_input_t;
|
|
|
|
static gchar *
|
|
describe_transfer_messages (gpointer in_data, gboolean gerund)
|
|
{
|
|
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
|
|
char *format;
|
|
|
|
if (gerund) {
|
|
if (input->delete_from_source)
|
|
format = _("Moving messages from \"%s\" into \"%s\"");
|
|
else
|
|
format = _("Copying messages from \"%s\" into \"%s\"");
|
|
} else {
|
|
if (input->delete_from_source)
|
|
format = _("Move messages from \"%s\" into \"%s\"");
|
|
else
|
|
format = _("Copy messages from \"%s\" into \"%s\"");
|
|
}
|
|
|
|
return g_strdup_printf (format,
|
|
mail_tool_get_folder_name (input->source),
|
|
input->dest_uri);
|
|
}
|
|
|
|
static void
|
|
setup_transfer_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->source));
|
|
}
|
|
|
|
static void
|
|
do_transfer_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
|
|
CamelFolder *dest;
|
|
gint i;
|
|
time_t last_update = 0;
|
|
gchar *desc;
|
|
void (*func) (CamelFolder *, const char *,
|
|
CamelFolder *,
|
|
CamelException *);
|
|
|
|
if (input->delete_from_source) {
|
|
func = camel_folder_move_message_to;
|
|
desc = _("Moving");
|
|
} else {
|
|
func = camel_folder_copy_message_to;
|
|
desc = _("Copying");
|
|
}
|
|
|
|
dest = mail_tool_uri_to_folder (input->dest_uri, ex);
|
|
if (camel_exception_is_set (ex))
|
|
return;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
camel_folder_freeze (input->source);
|
|
camel_folder_freeze (dest);
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
const gboolean last_message = (i+1 == input->uids->len);
|
|
time_t now;
|
|
|
|
/*
|
|
* Update the time display every 2 seconds
|
|
*/
|
|
time (&now);
|
|
if (last_message || ((now - last_update) > 2)) {
|
|
mail_op_set_message (_("%s message %d of %d (uid \"%s\")"), desc,
|
|
i + 1, input->uids->len, (char *) input->uids->pdata[i]);
|
|
last_update = now;
|
|
}
|
|
|
|
(func) (input->source,
|
|
input->uids->pdata[i], dest,
|
|
ex);
|
|
g_free (input->uids->pdata[i]);
|
|
if (camel_exception_is_set (ex))
|
|
break;
|
|
}
|
|
|
|
camel_folder_thaw (input->source);
|
|
camel_folder_thaw (dest);
|
|
camel_object_unref (CAMEL_OBJECT (dest));
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_transfer_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->source));
|
|
g_free (input->dest_uri);
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
}
|
|
|
|
static const mail_operation_spec op_transfer_messages = {
|
|
describe_transfer_messages,
|
|
0,
|
|
setup_transfer_messages,
|
|
do_transfer_messages,
|
|
cleanup_transfer_messages
|
|
};
|
|
|
|
void
|
|
mail_do_transfer_messages (CamelFolder *source, GPtrArray *uids,
|
|
gboolean delete_from_source,
|
|
gchar *dest_uri)
|
|
{
|
|
transfer_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (source));
|
|
g_return_if_fail (uids != NULL);
|
|
g_return_if_fail (dest_uri != NULL);
|
|
|
|
input = g_new (transfer_messages_input_t, 1);
|
|
input->source = source;
|
|
input->uids = uids;
|
|
input->delete_from_source = delete_from_source;
|
|
input->dest_uri = g_strdup (dest_uri);
|
|
|
|
mail_operation_queue (&op_transfer_messages, input, TRUE);
|
|
}
|
|
|
|
/* ** FLAG MESSAGES ******************************************************* */
|
|
|
|
typedef struct flag_messages_input_s
|
|
{
|
|
CamelFolder *source;
|
|
GPtrArray *uids;
|
|
gboolean invert;
|
|
guint32 mask;
|
|
guint32 set;
|
|
gboolean flag_all;
|
|
}
|
|
flag_messages_input_t;
|
|
|
|
static gchar *
|
|
describe_flag_messages (gpointer in_data, gboolean gerund)
|
|
{
|
|
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
|
|
|
|
/* FIXME: change based on flags being applied? */
|
|
|
|
if (gerund)
|
|
return g_strdup_printf (_("Marking messages in folder \"%s\""),
|
|
mail_tool_get_folder_name (input->source));
|
|
else
|
|
return g_strdup_printf (_("Mark messages in folder \"%s\""),
|
|
mail_tool_get_folder_name (input->source));
|
|
}
|
|
|
|
static void
|
|
setup_flag_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->source));
|
|
}
|
|
|
|
static void
|
|
do_flag_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
|
|
gint i;
|
|
time_t last_update = 0;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
camel_folder_freeze (input->source);
|
|
if (input->uids == NULL)
|
|
input->uids = camel_folder_get_uids (input->source);
|
|
mail_tool_camel_lock_down ();
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
const gboolean last_message = (i+1 == input->uids->len);
|
|
time_t now;
|
|
|
|
time (&now);
|
|
if (last_message || ((now - last_update) > 2)){
|
|
mail_op_set_message (_("Marking message %d of %d"), i + 1,
|
|
input->uids->len);
|
|
last_update = now;
|
|
}
|
|
|
|
if (input->invert) {
|
|
const CamelMessageInfo *info;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
info = camel_folder_get_message_info (input->source, input->uids->pdata[i]);
|
|
camel_folder_set_message_flags (input->source, input->uids->pdata[i],
|
|
input->mask, ~info->flags);
|
|
mail_tool_camel_lock_down ();
|
|
} else {
|
|
mail_tool_set_uid_flags (input->source, input->uids->pdata[i],
|
|
input->mask, input->set);
|
|
}
|
|
|
|
if (input->flag_all == FALSE)
|
|
g_free (input->uids->pdata[i]);
|
|
}
|
|
|
|
mail_tool_camel_lock_up ();
|
|
if (input->flag_all)
|
|
camel_folder_free_uids (input->source, input->uids);
|
|
else
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
camel_folder_thaw (input->source);
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_flag_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->source));
|
|
}
|
|
|
|
static const mail_operation_spec op_flag_messages = {
|
|
describe_flag_messages,
|
|
0,
|
|
setup_flag_messages,
|
|
do_flag_messages,
|
|
cleanup_flag_messages
|
|
};
|
|
|
|
void
|
|
mail_do_flag_messages (CamelFolder *source, GPtrArray *uids,
|
|
gboolean invert,
|
|
guint32 mask, guint32 set)
|
|
{
|
|
flag_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (source));
|
|
g_return_if_fail (uids != NULL);
|
|
|
|
input = g_new (flag_messages_input_t, 1);
|
|
input->source = source;
|
|
input->uids = uids;
|
|
input->invert = invert;
|
|
input->mask = mask;
|
|
input->set = set;
|
|
input->flag_all = FALSE;
|
|
|
|
mail_operation_queue (&op_flag_messages, input, TRUE);
|
|
}
|
|
|
|
void
|
|
mail_do_flag_all_messages (CamelFolder *source, gboolean invert,
|
|
guint32 mask, guint32 set)
|
|
{
|
|
flag_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (source));
|
|
|
|
input = g_new (flag_messages_input_t, 1);
|
|
input->source = source;
|
|
input->uids = NULL;
|
|
input->invert = invert;
|
|
input->mask = mask;
|
|
input->set = set;
|
|
input->flag_all = TRUE;
|
|
|
|
mail_operation_queue (&op_flag_messages, input, TRUE);
|
|
}
|
|
|
|
/* ** SCAN SUBFOLDERS ***************************************************** */
|
|
|
|
typedef struct scan_subfolders_input_s
|
|
{
|
|
CamelStore *store;
|
|
EvolutionStorage *storage;
|
|
}
|
|
scan_subfolders_input_t;
|
|
|
|
typedef struct scan_subfolders_folderinfo_s
|
|
{
|
|
char *path;
|
|
char *name;
|
|
char *uri;
|
|
gboolean highlighted;
|
|
}
|
|
scan_subfolders_folderinfo_t;
|
|
|
|
typedef struct scan_subfolders_op_s
|
|
{
|
|
GPtrArray *new_folders;
|
|
}
|
|
scan_subfolders_op_t;
|
|
|
|
static gchar *
|
|
describe_scan_subfolders (gpointer in_data, gboolean gerund)
|
|
{
|
|
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
|
|
char *name;
|
|
|
|
name = camel_service_get_name (CAMEL_SERVICE (input->store), TRUE);
|
|
if (gerund)
|
|
return g_strdup_printf (_("Scanning folders in \"%s\""), name);
|
|
else
|
|
return g_strdup_printf (_("Scan folders in \"%s\""), name);
|
|
g_free (name);
|
|
}
|
|
|
|
static void
|
|
setup_scan_subfolders (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
|
|
scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->store));
|
|
gtk_object_ref (GTK_OBJECT (input->storage));
|
|
|
|
data->new_folders = g_ptr_array_new ();
|
|
}
|
|
|
|
static void
|
|
add_folders (GPtrArray *folders, const char *prefix, CamelFolderInfo *fi)
|
|
{
|
|
scan_subfolders_folderinfo_t *info;
|
|
|
|
info = g_new (scan_subfolders_folderinfo_t, 1);
|
|
info->path = g_strdup_printf ("%s/%s", prefix, fi->name);
|
|
if (fi->unread_message_count > 0) {
|
|
info->name = g_strdup_printf ("%s (%d)", fi->name,
|
|
fi->unread_message_count);
|
|
info->highlighted = TRUE;
|
|
} else {
|
|
info->name = g_strdup (fi->name);
|
|
info->highlighted = FALSE;
|
|
}
|
|
info->uri = g_strdup (fi->url);
|
|
g_ptr_array_add (folders, info);
|
|
if (fi->child)
|
|
add_folders (folders, info->path, fi->child);
|
|
if (fi->sibling)
|
|
add_folders (folders, prefix, fi->sibling);
|
|
}
|
|
|
|
static void
|
|
do_scan_subfolders (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
|
|
scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
|
|
CamelFolderInfo *tree;
|
|
|
|
tree = camel_store_get_folder_info (input->store, NULL, FALSE,
|
|
TRUE, TRUE, ex);
|
|
if (tree) {
|
|
add_folders (data->new_folders, "", tree);
|
|
camel_store_free_folder_info (input->store, tree);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cleanup_scan_subfolders (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
|
|
scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
|
|
scan_subfolders_folderinfo_t *info;
|
|
int i;
|
|
|
|
for (i = 0; i < data->new_folders->len; i++) {
|
|
info = data->new_folders->pdata[i];
|
|
evolution_storage_new_folder (input->storage, info->path,
|
|
info->name, "mail",
|
|
info->uri ? info->uri : "",
|
|
_("(No description)"),
|
|
info->highlighted);
|
|
|
|
g_free (info->uri);
|
|
g_free (info->name);
|
|
g_free (info->path);
|
|
g_free (info);
|
|
}
|
|
g_ptr_array_free (data->new_folders, TRUE);
|
|
|
|
gtk_object_unref (GTK_OBJECT (input->storage));
|
|
camel_object_unref (CAMEL_OBJECT (input->store));
|
|
}
|
|
|
|
static const mail_operation_spec op_scan_subfolders = {
|
|
describe_scan_subfolders,
|
|
sizeof (scan_subfolders_op_t),
|
|
setup_scan_subfolders,
|
|
do_scan_subfolders,
|
|
cleanup_scan_subfolders
|
|
};
|
|
|
|
void
|
|
mail_do_scan_subfolders (CamelStore *store, EvolutionStorage *storage)
|
|
{
|
|
scan_subfolders_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_STORE (store));
|
|
g_return_if_fail (EVOLUTION_IS_STORAGE (storage));
|
|
|
|
input = g_new (scan_subfolders_input_t, 1);
|
|
input->store = store;
|
|
input->storage = storage;
|
|
|
|
mail_operation_queue (&op_scan_subfolders, input, TRUE);
|
|
}
|
|
|
|
/* ** ATTACH MESSAGE ****************************************************** */
|
|
|
|
typedef struct attach_message_input_s
|
|
{
|
|
EMsgComposer *composer;
|
|
CamelFolder *folder;
|
|
gchar *uid;
|
|
}
|
|
attach_message_input_t;
|
|
|
|
typedef struct attach_message_data_s
|
|
{
|
|
CamelMimePart *part;
|
|
}
|
|
attach_message_data_t;
|
|
|
|
static gchar *
|
|
describe_attach_message (gpointer in_data, gboolean gerund)
|
|
{
|
|
attach_message_input_t *input = (attach_message_input_t *) in_data;
|
|
|
|
if (gerund)
|
|
return
|
|
g_strdup_printf
|
|
(_("Attaching messages from folder \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
else
|
|
return g_strdup_printf (_("Attach messages from \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
}
|
|
|
|
static void
|
|
setup_attach_message (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
attach_message_input_t *input = (attach_message_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->folder));
|
|
gtk_object_ref (GTK_OBJECT (input->composer));
|
|
}
|
|
|
|
static void
|
|
do_attach_message (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
attach_message_input_t *input = (attach_message_input_t *) in_data;
|
|
attach_message_data_t *data = (attach_message_data_t *) op_data;
|
|
|
|
CamelMimeMessage *message;
|
|
CamelMimePart *part;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
message = camel_folder_get_message (input->folder, input->uid, ex);
|
|
if (!message) {
|
|
mail_tool_camel_lock_down ();
|
|
return;
|
|
}
|
|
|
|
part = mail_tool_make_message_attachment (message);
|
|
camel_object_unref (CAMEL_OBJECT (message));
|
|
mail_tool_camel_lock_down ();
|
|
if (!part)
|
|
return;
|
|
|
|
data->part = part;
|
|
}
|
|
|
|
static void
|
|
cleanup_attach_message (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
attach_message_input_t *input = (attach_message_input_t *) in_data;
|
|
attach_message_data_t *data = (attach_message_data_t *) op_data;
|
|
|
|
e_msg_composer_attach (input->composer, data->part);
|
|
camel_object_unref (CAMEL_OBJECT (data->part));
|
|
camel_object_unref (CAMEL_OBJECT (input->folder));
|
|
gtk_object_unref (GTK_OBJECT (input->composer));
|
|
g_free (input->uid);
|
|
}
|
|
|
|
static const mail_operation_spec op_attach_message = {
|
|
describe_attach_message,
|
|
sizeof (attach_message_data_t),
|
|
setup_attach_message,
|
|
do_attach_message,
|
|
cleanup_attach_message
|
|
};
|
|
|
|
void
|
|
mail_do_attach_message (CamelFolder *folder, const char *uid,
|
|
EMsgComposer *composer)
|
|
{
|
|
attach_message_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (uid != NULL);
|
|
g_return_if_fail (E_IS_MSG_COMPOSER (composer));
|
|
|
|
input = g_new (attach_message_input_t, 1);
|
|
input->folder = folder;
|
|
input->uid = g_strdup (uid);
|
|
input->composer = composer;
|
|
|
|
mail_operation_queue (&op_attach_message, input, TRUE);
|
|
}
|
|
|
|
/* ** FORWARD MESSAGES **************************************************** */
|
|
|
|
typedef struct forward_messages_input_s {
|
|
CamelMimeMessage *basis;
|
|
CamelFolder *source;
|
|
GPtrArray *uids;
|
|
EMsgComposer *composer;
|
|
gboolean attach;
|
|
} forward_messages_input_t;
|
|
|
|
typedef struct forward_messages_data_s {
|
|
gchar *subject;
|
|
GPtrArray *parts;
|
|
} forward_messages_data_t;
|
|
|
|
static gchar *
|
|
describe_forward_messages (gpointer in_data, gboolean gerund)
|
|
{
|
|
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
|
|
|
|
if (gerund) {
|
|
if (input->basis->subject)
|
|
return g_strdup_printf (_("Forwarding messages \"%s\""),
|
|
input->basis->subject);
|
|
else
|
|
return g_strdup_printf
|
|
(_("Forwarding a message without a subject"));
|
|
} else {
|
|
if (input->basis->subject)
|
|
return g_strdup_printf (_("Forward message \"%s\""),
|
|
input->basis->subject);
|
|
else
|
|
return g_strdup_printf
|
|
(_("Forward a message without a subject"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_forward_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
|
|
|
|
if (!input->attach && input->uids->len > 1) {
|
|
/* Hmmm, this behavior is undefined so lets default
|
|
back to forwarding each message as an attachment. */
|
|
|
|
input->attach = TRUE;
|
|
}
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->basis));
|
|
camel_object_ref (CAMEL_OBJECT (input->source));
|
|
gtk_object_ref (GTK_OBJECT (input->composer));
|
|
}
|
|
|
|
static void
|
|
do_forward_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
|
|
forward_messages_data_t *data = (forward_messages_data_t *) op_data;
|
|
CamelMimeMessage *message;
|
|
|
|
data->parts = g_ptr_array_new ();
|
|
|
|
mail_tool_camel_lock_up ();
|
|
|
|
if (input->attach) {
|
|
CamelMimePart *part;
|
|
time_t last_update = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
const int last_message = (i+1 == input->uids->len);
|
|
time_t now;
|
|
|
|
/*
|
|
* Update the time display every 2 seconds
|
|
*/
|
|
time (&now);
|
|
if (last_message || ((now - last_update) > 2)){
|
|
mail_op_set_message (_("Retrieving message number %d of %d (uid \"%s\")"),
|
|
i + 1, input->uids->len, (char *) input->uids->pdata[i]);
|
|
last_update = now;
|
|
}
|
|
|
|
message = camel_folder_get_message (input->source,
|
|
input->uids->pdata[i], ex);
|
|
g_free (input->uids->pdata[i]);
|
|
if (!message) {
|
|
mail_tool_camel_lock_down ();
|
|
return;
|
|
}
|
|
|
|
part = mail_tool_make_message_attachment (message);
|
|
if (!part) {
|
|
camel_object_unref (CAMEL_OBJECT (message));
|
|
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
|
|
_("Failed to generate mime part from "
|
|
"message while generating forwarded message."));
|
|
mail_tool_camel_lock_down ();
|
|
return;
|
|
}
|
|
|
|
camel_object_unref (CAMEL_OBJECT (message));
|
|
g_ptr_array_add (data->parts, part);
|
|
}
|
|
} else {
|
|
message = camel_folder_get_message (input->source,
|
|
input->uids->pdata[0], ex);
|
|
g_free (input->uids->pdata[0]);
|
|
if (!message) {
|
|
mail_tool_camel_lock_down ();
|
|
return;
|
|
}
|
|
|
|
g_ptr_array_add (data->parts, message);
|
|
}
|
|
|
|
mail_tool_camel_lock_down ();
|
|
|
|
data->subject = mail_tool_generate_forward_subject (input->basis);
|
|
}
|
|
|
|
static void
|
|
cleanup_forward_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
|
|
forward_messages_data_t *data = (forward_messages_data_t *) op_data;
|
|
|
|
if (input->attach) {
|
|
if (data->parts->len > 1) {
|
|
/* construct and attach a multipart/digest */
|
|
CamelMimePart *digest;
|
|
CamelMultipart *multipart;
|
|
int i;
|
|
|
|
multipart = camel_multipart_new ();
|
|
camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart),
|
|
"multipart/digest");
|
|
camel_multipart_set_boundary (multipart, NULL);
|
|
|
|
for (i = 0; i < data->parts->len; i++) {
|
|
camel_multipart_add_part (multipart, CAMEL_MIME_PART (data->parts->pdata[i]));
|
|
camel_object_unref (CAMEL_OBJECT (data->parts->pdata[i]));
|
|
}
|
|
|
|
digest = camel_mime_part_new ();
|
|
camel_medium_set_content_object (CAMEL_MEDIUM (digest),
|
|
CAMEL_DATA_WRAPPER (multipart));
|
|
camel_object_unref (CAMEL_OBJECT (multipart));
|
|
|
|
camel_mime_part_set_description (digest, _("Forwarded messages"));
|
|
|
|
e_msg_composer_attach (input->composer, CAMEL_MIME_PART (digest));
|
|
camel_object_unref (CAMEL_OBJECT (digest));
|
|
} else if (data->parts->len == 1) {
|
|
/* simply attach the message as message/rfc822 */
|
|
e_msg_composer_attach (input->composer, CAMEL_MIME_PART (data->parts->pdata[0]));
|
|
camel_object_unref (CAMEL_OBJECT (data->parts->pdata[0]));
|
|
}
|
|
} else {
|
|
/* attach as inlined text */
|
|
CamelMimeMessage *message = data->parts->pdata[0];
|
|
char *text;
|
|
|
|
text = mail_tool_quote_message (message, _("Forwarded message:\n"));
|
|
|
|
if (text) {
|
|
e_msg_composer_set_body_text (input->composer, text);
|
|
g_free (text);
|
|
}
|
|
|
|
camel_object_unref (CAMEL_OBJECT (message));
|
|
}
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->source));
|
|
|
|
e_msg_composer_set_headers (input->composer, NULL, NULL, NULL,
|
|
data->subject);
|
|
|
|
gtk_object_unref (GTK_OBJECT (input->composer));
|
|
g_free (data->subject);
|
|
g_ptr_array_free (data->parts, TRUE);
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
gtk_widget_show (GTK_WIDGET (input->composer));
|
|
}
|
|
|
|
static const mail_operation_spec op_forward_messages = {
|
|
describe_forward_messages,
|
|
sizeof (forward_messages_data_t),
|
|
setup_forward_messages,
|
|
do_forward_messages,
|
|
cleanup_forward_messages
|
|
};
|
|
|
|
void
|
|
mail_do_forward_message (CamelMimeMessage *basis,
|
|
CamelFolder *source,
|
|
GPtrArray *uids,
|
|
EMsgComposer *composer,
|
|
gboolean attach)
|
|
{
|
|
forward_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_MIME_MESSAGE (basis));
|
|
g_return_if_fail (CAMEL_IS_FOLDER (source));
|
|
g_return_if_fail (uids != NULL);
|
|
g_return_if_fail (E_IS_MSG_COMPOSER (composer));
|
|
|
|
input = g_new (forward_messages_input_t, 1);
|
|
input->basis = basis;
|
|
input->source = source;
|
|
input->uids = uids;
|
|
input->composer = composer;
|
|
input->attach = attach;
|
|
|
|
mail_operation_queue (&op_forward_messages, input, TRUE);
|
|
}
|
|
|
|
/* ** LOAD FOLDER ********************************************************* */
|
|
|
|
typedef struct load_folder_input_s
|
|
{
|
|
FolderBrowser *fb;
|
|
gchar *url;
|
|
}
|
|
load_folder_input_t;
|
|
|
|
static gchar *
|
|
describe_load_folder (gpointer in_data, gboolean gerund)
|
|
{
|
|
load_folder_input_t *input = (load_folder_input_t *) in_data;
|
|
|
|
if (gerund) {
|
|
return g_strdup_printf (_("Loading \"%s\""), input->url);
|
|
} else {
|
|
return g_strdup_printf (_("Load \"%s\""), input->url);
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
load_folder_input_t *input = (load_folder_input_t *) in_data;
|
|
|
|
gtk_object_ref (GTK_OBJECT (input->fb));
|
|
|
|
if (input->fb->uri)
|
|
g_free (input->fb->uri);
|
|
|
|
input->fb->uri = input->url;
|
|
}
|
|
|
|
static void
|
|
do_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
load_folder_input_t *input = (load_folder_input_t *) in_data;
|
|
|
|
CamelFolder *folder;
|
|
|
|
folder = mail_tool_uri_to_folder (input->url, ex);
|
|
if (!folder)
|
|
return;
|
|
|
|
if (input->fb->folder) {
|
|
mail_tool_camel_lock_up ();
|
|
camel_object_unref (CAMEL_OBJECT (input->fb->folder));
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
input->fb->folder = folder;
|
|
}
|
|
|
|
static void
|
|
cleanup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
load_folder_input_t *input = (load_folder_input_t *) in_data;
|
|
|
|
if (input->fb->folder) {
|
|
gtk_widget_set_sensitive (GTK_WIDGET (input->fb->search->entry),
|
|
camel_folder_has_search_capability (input->
|
|
fb->
|
|
folder));
|
|
gtk_widget_set_sensitive (GTK_WIDGET (input->fb->search->option),
|
|
camel_folder_has_search_capability (input->
|
|
fb->
|
|
folder));
|
|
message_list_set_threaded(input->fb->message_list, mail_config_thread_list());
|
|
message_list_set_folder (input->fb->message_list, input->fb->folder);
|
|
}
|
|
|
|
gtk_object_unref (GTK_OBJECT (input->fb));
|
|
}
|
|
|
|
static const mail_operation_spec op_load_folder = {
|
|
describe_load_folder,
|
|
0,
|
|
setup_load_folder,
|
|
do_load_folder,
|
|
cleanup_load_folder
|
|
};
|
|
|
|
void
|
|
mail_do_load_folder (FolderBrowser *fb, const char *url)
|
|
{
|
|
load_folder_input_t *input;
|
|
|
|
g_return_if_fail (IS_FOLDER_BROWSER (fb));
|
|
g_return_if_fail (url != NULL);
|
|
|
|
input = g_new (load_folder_input_t, 1);
|
|
input->fb = fb;
|
|
input->url = g_strdup (url);
|
|
|
|
mail_operation_queue (&op_load_folder, input, TRUE);
|
|
}
|
|
|
|
/* ** CREATE FOLDER ******************************************************* */
|
|
|
|
typedef struct create_folder_input_s
|
|
{
|
|
GNOME_Evolution_ShellComponentListener listener;
|
|
char *uri;
|
|
char *type;
|
|
}
|
|
create_folder_input_t;
|
|
|
|
typedef struct create_folder_data_s
|
|
{
|
|
GNOME_Evolution_ShellComponentListener_Result result;
|
|
}
|
|
create_folder_data_t;
|
|
|
|
static gchar *
|
|
describe_create_folder (gpointer in_data, gboolean gerund)
|
|
{
|
|
create_folder_input_t *input = (create_folder_input_t *) in_data;
|
|
|
|
if (gerund) {
|
|
return g_strdup_printf (_("Creating \"%s\""), input->uri);
|
|
} else {
|
|
return g_strdup_printf (_("Create \"%s\""), input->uri);
|
|
}
|
|
}
|
|
|
|
static void
|
|
do_create_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
create_folder_input_t *input = (create_folder_input_t *) in_data;
|
|
create_folder_data_t *data = (create_folder_data_t *) op_data;
|
|
|
|
CamelFolder *folder;
|
|
gchar *camel_url;
|
|
|
|
if (strcmp (input->type, "mail") != 0)
|
|
data->result =
|
|
GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE;
|
|
else {
|
|
camel_url = g_strdup_printf ("mbox://%s", input->uri);
|
|
/* FIXME: supply a way to make indexes optional */
|
|
folder = mail_tool_get_folder_from_urlname (camel_url,
|
|
"mbox", CAMEL_STORE_FOLDER_CREATE
|
|
|CAMEL_STORE_FOLDER_BODY_INDEX, ex);
|
|
g_free (camel_url);
|
|
|
|
if (!camel_exception_is_set (ex)) {
|
|
camel_object_unref (CAMEL_OBJECT (folder));
|
|
data->result = GNOME_Evolution_ShellComponentListener_OK;
|
|
} else {
|
|
data->result =
|
|
GNOME_Evolution_ShellComponentListener_INVALID_URI;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
cleanup_create_folder (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
create_folder_input_t *input = (create_folder_input_t *) in_data;
|
|
create_folder_data_t *data = (create_folder_data_t *) op_data;
|
|
|
|
CORBA_Environment ev;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (input->listener,
|
|
data->result, &ev);
|
|
if (ev._major != CORBA_NO_EXCEPTION)
|
|
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
|
|
_("Exception while reporting result to shell "
|
|
"component listener."));
|
|
CORBA_Object_release (input->listener, &ev);
|
|
|
|
g_free (input->uri);
|
|
g_free (input->type);
|
|
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static const mail_operation_spec op_create_folder = {
|
|
describe_create_folder,
|
|
sizeof (create_folder_data_t),
|
|
NULL,
|
|
do_create_folder,
|
|
cleanup_create_folder
|
|
};
|
|
|
|
void
|
|
mail_do_create_folder (const GNOME_Evolution_ShellComponentListener listener,
|
|
const char *uri, const char *type)
|
|
{
|
|
CORBA_Environment ev;
|
|
create_folder_input_t *input;
|
|
|
|
g_return_if_fail (uri != NULL);
|
|
g_return_if_fail (type != NULL);
|
|
|
|
input = g_new (create_folder_input_t, 1);
|
|
CORBA_exception_init (&ev);
|
|
input->listener = CORBA_Object_duplicate (listener, &ev);
|
|
CORBA_exception_free (&ev);
|
|
input->uri = g_strdup (uri);
|
|
input->type = g_strdup (type);
|
|
|
|
mail_operation_queue (&op_create_folder, input, FALSE);
|
|
}
|
|
|
|
/* ** SYNC FOLDER ********************************************************* */
|
|
|
|
static gchar *
|
|
describe_sync_folder (gpointer in_data, gboolean gerund)
|
|
{
|
|
CamelFolder *f = CAMEL_FOLDER (in_data);
|
|
|
|
if (gerund) {
|
|
return g_strdup_printf (_("Synchronizing \"%s\""), mail_tool_get_folder_name (f));
|
|
} else {
|
|
return g_strdup_printf (_("Synchronize \"%s\""), mail_tool_get_folder_name (f));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
camel_object_ref (CAMEL_OBJECT (in_data));
|
|
}
|
|
|
|
static void
|
|
do_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
mail_tool_camel_lock_up ();
|
|
camel_folder_sync (CAMEL_FOLDER (in_data), FALSE, ex);
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
camel_object_unref (CAMEL_OBJECT (in_data));
|
|
}
|
|
|
|
static const mail_operation_spec op_sync_folder = {
|
|
describe_sync_folder,
|
|
0,
|
|
setup_sync_folder,
|
|
do_sync_folder,
|
|
cleanup_sync_folder
|
|
};
|
|
|
|
void
|
|
mail_do_sync_folder (CamelFolder *folder)
|
|
{
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
|
|
mail_operation_queue (&op_sync_folder, folder, FALSE);
|
|
}
|
|
|
|
/* ** DISPLAY MESSAGE ***************************************************** */
|
|
|
|
typedef struct display_message_input_s
|
|
{
|
|
MessageList *ml;
|
|
MailDisplay *md;
|
|
gchar *uid;
|
|
gint (*timeout) (gpointer);
|
|
}
|
|
display_message_input_t;
|
|
|
|
typedef struct display_message_data_s
|
|
{
|
|
CamelMimeMessage *msg;
|
|
}
|
|
display_message_data_t;
|
|
|
|
static gchar *
|
|
describe_display_message (gpointer in_data, gboolean gerund)
|
|
{
|
|
display_message_input_t *input = (display_message_input_t *) in_data;
|
|
|
|
if (gerund) {
|
|
if (input->uid)
|
|
return g_strdup_printf (_("Displaying message UID \"%s\""),
|
|
input->uid);
|
|
else
|
|
return g_strdup (_("Clearing message display"));
|
|
} else {
|
|
if (input->uid)
|
|
return g_strdup_printf (_("Display message UID \"%s\""),
|
|
input->uid);
|
|
else
|
|
return g_strdup (_("Clear message display"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_display_message (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
display_message_input_t *input = (display_message_input_t *) in_data;
|
|
display_message_data_t *data = (display_message_data_t *) op_data;
|
|
|
|
data->msg = NULL;
|
|
gtk_object_ref (GTK_OBJECT (input->ml));
|
|
}
|
|
|
|
static void
|
|
do_display_message (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
display_message_input_t *input = (display_message_input_t *) in_data;
|
|
display_message_data_t *data = (display_message_data_t *) op_data;
|
|
|
|
if (input->uid == NULL) {
|
|
data->msg = NULL;
|
|
return;
|
|
}
|
|
|
|
data->msg = camel_folder_get_message (input->ml->folder, input->uid, ex);
|
|
}
|
|
|
|
static void
|
|
cleanup_display_message (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
display_message_input_t *input = (display_message_input_t *) in_data;
|
|
display_message_data_t *data = (display_message_data_t *) op_data;
|
|
MailDisplay *md = input->md;
|
|
|
|
if (data->msg == NULL) {
|
|
mail_display_set_message (md, NULL);
|
|
} else {
|
|
gint timeout = mail_config_mark_as_seen_timeout ();
|
|
|
|
if (input->ml->seen_id)
|
|
gtk_timeout_remove (input->ml->seen_id);
|
|
|
|
mail_display_set_message (md, CAMEL_MEDIUM (data->msg));
|
|
camel_object_unref (CAMEL_OBJECT (data->msg));
|
|
|
|
if (timeout > 0) {
|
|
input->ml->seen_id = gtk_timeout_add (timeout,
|
|
input->timeout,
|
|
input->ml);
|
|
} else {
|
|
input->ml->seen_id = 0;
|
|
input->timeout (input->ml);
|
|
}
|
|
}
|
|
|
|
if (input->uid)
|
|
g_free (input->uid);
|
|
gtk_object_unref (GTK_OBJECT (input->ml));
|
|
}
|
|
|
|
static const mail_operation_spec op_display_message = {
|
|
describe_display_message,
|
|
sizeof (display_message_data_t),
|
|
setup_display_message,
|
|
do_display_message,
|
|
cleanup_display_message
|
|
};
|
|
|
|
void
|
|
mail_do_display_message (MessageList *ml, MailDisplay *md, const char *uid,
|
|
gint (*timeout) (gpointer))
|
|
{
|
|
display_message_input_t *input;
|
|
|
|
g_return_if_fail (IS_MESSAGE_LIST (ml));
|
|
g_return_if_fail (timeout != NULL);
|
|
|
|
if (uid == NULL) {
|
|
mail_display_set_message (md, NULL);
|
|
return;
|
|
}
|
|
|
|
input = g_new (display_message_input_t, 1);
|
|
input->ml = ml;
|
|
input->md = md;
|
|
input->uid = g_strdup (uid);
|
|
input->timeout = timeout;
|
|
|
|
mail_operation_queue (&op_display_message, input, TRUE);
|
|
}
|
|
|
|
/* ** EDIT MESSAGES ******************************************************* */
|
|
|
|
typedef struct edit_messages_input_s {
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
GtkSignalFunc signal;
|
|
} edit_messages_input_t;
|
|
|
|
typedef struct edit_messages_data_s {
|
|
GPtrArray *messages;
|
|
} edit_messages_data_t;
|
|
|
|
static gchar *
|
|
describe_edit_messages (gpointer in_data, gboolean gerund)
|
|
{
|
|
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
|
|
|
|
if (gerund)
|
|
return g_strdup_printf
|
|
(_("Opening messages from folder \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
else
|
|
return g_strdup_printf (_("Open messages from \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
}
|
|
|
|
static void
|
|
setup_edit_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->folder));
|
|
}
|
|
|
|
static void
|
|
do_edit_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
|
|
edit_messages_data_t *data = (edit_messages_data_t *) op_data;
|
|
|
|
int i;
|
|
|
|
data->messages = g_ptr_array_new ();
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
CamelMimeMessage *message;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex);
|
|
mail_tool_camel_lock_down ();
|
|
|
|
if (message)
|
|
g_ptr_array_add (data->messages, message);
|
|
|
|
g_free (input->uids->pdata[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cleanup_edit_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
|
|
edit_messages_data_t *data = (edit_messages_data_t *) op_data;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < data->messages->len; i++) {
|
|
EMsgComposer *composer;
|
|
|
|
composer = e_msg_composer_new_with_message (data->messages->pdata[i]);
|
|
camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i]));
|
|
if (!composer)
|
|
continue;
|
|
|
|
if (input->signal)
|
|
gtk_signal_connect (GTK_OBJECT (composer), "send",
|
|
input->signal, NULL);
|
|
|
|
gtk_widget_show (GTK_WIDGET (composer));
|
|
}
|
|
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
g_ptr_array_free (data->messages, TRUE);
|
|
camel_object_unref (CAMEL_OBJECT (input->folder));
|
|
|
|
}
|
|
|
|
static const mail_operation_spec op_edit_messages = {
|
|
describe_edit_messages,
|
|
sizeof (edit_messages_data_t),
|
|
setup_edit_messages,
|
|
do_edit_messages,
|
|
cleanup_edit_messages
|
|
};
|
|
|
|
void
|
|
mail_do_edit_messages (CamelFolder *folder, GPtrArray *uids,
|
|
GtkSignalFunc signal)
|
|
{
|
|
edit_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (uids != NULL);
|
|
|
|
input = g_new (edit_messages_input_t, 1);
|
|
input->folder = folder;
|
|
input->uids = uids;
|
|
input->signal = signal;
|
|
|
|
mail_operation_queue (&op_edit_messages, input, TRUE);
|
|
}
|
|
|
|
/* ** SETUP FOLDER ****************************************************** */
|
|
|
|
typedef struct setup_folder_input_s {
|
|
gchar *name;
|
|
CamelFolder **folder;
|
|
} setup_folder_input_t;
|
|
|
|
static gchar *
|
|
describe_setup_folder (gpointer in_data, gboolean gerund)
|
|
{
|
|
setup_folder_input_t *input = (setup_folder_input_t *) in_data;
|
|
|
|
if (gerund)
|
|
return g_strdup_printf (_("Loading %s Folder"), input->name);
|
|
else
|
|
return g_strdup_printf (_("Load %s Folder"), input->name);
|
|
}
|
|
|
|
static void
|
|
do_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
setup_folder_input_t *input = (setup_folder_input_t *) in_data;
|
|
gchar *url;
|
|
|
|
url = g_strdup_printf ("file://%s/local/%s", evolution_dir,
|
|
input->name);
|
|
*(input->folder) = mail_tool_uri_to_folder (url, ex);
|
|
g_free (url);
|
|
}
|
|
|
|
static void
|
|
cleanup_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
setup_folder_input_t *input = (setup_folder_input_t *) in_data;
|
|
|
|
g_free (input->name);
|
|
}
|
|
|
|
static const mail_operation_spec op_setup_folder = {
|
|
describe_setup_folder,
|
|
0,
|
|
NULL,
|
|
do_setup_folder,
|
|
cleanup_setup_folder
|
|
};
|
|
|
|
void
|
|
mail_do_setup_folder (const char *name, CamelFolder **folder)
|
|
{
|
|
setup_folder_input_t *input;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (folder != NULL);
|
|
|
|
input = g_new (setup_folder_input_t, 1);
|
|
input->name = g_strdup (name);
|
|
input->folder = folder;
|
|
mail_operation_queue (&op_setup_folder, input, TRUE);
|
|
}
|
|
|
|
/* ** VIEW MESSAGES ******************************************************* */
|
|
|
|
typedef struct view_messages_input_s {
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
FolderBrowser *fb;
|
|
} view_messages_input_t;
|
|
|
|
typedef struct view_messages_data_s {
|
|
GPtrArray *messages;
|
|
} view_messages_data_t;
|
|
|
|
static gchar *
|
|
describe_view_messages (gpointer in_data, gboolean gerund)
|
|
{
|
|
view_messages_input_t *input = (view_messages_input_t *) in_data;
|
|
|
|
if (gerund)
|
|
return g_strdup_printf
|
|
(_("Viewing messages from folder \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
else
|
|
return g_strdup_printf (_("View messages from \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
}
|
|
|
|
static void
|
|
setup_view_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
view_messages_input_t *input = (view_messages_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->folder));
|
|
gtk_object_ref (GTK_OBJECT (input->fb));
|
|
}
|
|
|
|
static void
|
|
do_view_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
view_messages_input_t *input = (view_messages_input_t *) in_data;
|
|
view_messages_data_t *data = (view_messages_data_t *) op_data;
|
|
|
|
int i;
|
|
|
|
data->messages = g_ptr_array_new ();
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
CamelMimeMessage *message;
|
|
|
|
mail_op_set_message (_("Retrieving message %d of %d (uid \"%s\")"),
|
|
i + 1, input->uids->len, (char *)input->uids->pdata[i]);
|
|
|
|
mail_tool_camel_lock_up ();
|
|
message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex);
|
|
mail_tool_camel_lock_down ();
|
|
|
|
g_ptr_array_add (data->messages, message);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cleanup_view_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
view_messages_input_t *input = (view_messages_input_t *) in_data;
|
|
view_messages_data_t *data = (view_messages_data_t *) op_data;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < data->messages->len; i++) {
|
|
CamelMimeMessage *msg;
|
|
gchar *uid;
|
|
GtkWidget *view;
|
|
|
|
if (data->messages->pdata[i] == NULL)
|
|
continue;
|
|
|
|
msg = data->messages->pdata[i];
|
|
uid = input->uids->pdata[i];
|
|
|
|
view = mail_view_create (input->folder, uid, msg);
|
|
gtk_widget_show (view);
|
|
|
|
/*Owned by the mail_display now*/
|
|
camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i]));
|
|
g_free (uid);
|
|
}
|
|
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
g_ptr_array_free (data->messages, TRUE);
|
|
camel_object_unref (CAMEL_OBJECT (input->folder));
|
|
gtk_object_unref (GTK_OBJECT (input->fb));
|
|
}
|
|
|
|
static const mail_operation_spec op_view_messages = {
|
|
describe_view_messages,
|
|
sizeof (view_messages_data_t),
|
|
setup_view_messages,
|
|
do_view_messages,
|
|
cleanup_view_messages
|
|
};
|
|
|
|
void
|
|
mail_do_view_messages (CamelFolder *folder, GPtrArray *uids,
|
|
FolderBrowser *fb)
|
|
{
|
|
view_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (uids != NULL);
|
|
g_return_if_fail (IS_FOLDER_BROWSER (fb));
|
|
|
|
input = g_new (view_messages_input_t, 1);
|
|
input->folder = folder;
|
|
input->uids = uids;
|
|
input->fb = fb;
|
|
|
|
mail_operation_queue (&op_view_messages, input, TRUE);
|
|
}
|
|
|
|
|
|
/* ** SAVE MESSAGES ******************************************************* */
|
|
|
|
typedef struct save_messages_input_s {
|
|
CamelFolder *folder;
|
|
GPtrArray *uids;
|
|
gchar *path;
|
|
} save_messages_input_t;
|
|
|
|
typedef struct save_messages_data_s {
|
|
} save_messages_data_t;
|
|
|
|
static gchar *
|
|
describe_save_messages (gpointer in_data, gboolean gerund)
|
|
{
|
|
save_messages_input_t *input = (save_messages_input_t *) in_data;
|
|
|
|
if (gerund)
|
|
return g_strdup_printf (_("Saving messages from folder \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
else
|
|
return g_strdup_printf (_("Save messages from folder \"%s\""),
|
|
mail_tool_get_folder_name (input->folder));
|
|
}
|
|
|
|
static void
|
|
setup_save_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
save_messages_input_t *input = (save_messages_input_t *) in_data;
|
|
|
|
camel_object_ref (CAMEL_OBJECT (input->folder));
|
|
}
|
|
|
|
static void
|
|
do_save_messages (gpointer in_data, gpointer op_data, CamelException *ex)
|
|
{
|
|
save_messages_input_t *input = (save_messages_input_t *) in_data;
|
|
CamelStreamFilter *filtered_stream;
|
|
CamelMimeFilterFrom *from_filter;
|
|
CamelStream *stream;
|
|
time_t last_update = 0;
|
|
int fd, fid, i;
|
|
|
|
fd = open (input->path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
|
if (fd == -1)
|
|
return;
|
|
|
|
mail_tool_camel_lock_up ();
|
|
|
|
stream = camel_stream_fs_new_with_fd (fd);
|
|
from_filter = camel_mime_filter_from_new ();
|
|
filtered_stream = camel_stream_filter_new_with_stream (stream);
|
|
fid = camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (from_filter));
|
|
|
|
for (i = 0; i < input->uids->len; i++) {
|
|
CamelMimeMessage *message;
|
|
const gboolean last_message = (i+1 == input->uids->len);
|
|
time_t now;
|
|
|
|
/*
|
|
* Update the time display every 2 seconds
|
|
*/
|
|
time (&now);
|
|
if (last_message || ((now - last_update) > 2)) {
|
|
mail_op_set_message (_("Saving message %d of %d (uid \"%s\")"),
|
|
i + 1, input->uids->len, (char *)input->uids->pdata[i]);
|
|
last_update = now;
|
|
}
|
|
|
|
message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex);
|
|
g_free (input->uids->pdata[i]);
|
|
if (message && !camel_exception_is_set (ex)) {
|
|
struct _header_address *addr = NULL;
|
|
struct _header_raw *headers;
|
|
const char *sender, *str;
|
|
char *date_str;
|
|
time_t date;
|
|
int offset;
|
|
|
|
/* first we must write the "From " line */
|
|
camel_stream_write (stream, "From ", 5);
|
|
headers = CAMEL_MIME_PART (message)->headers;
|
|
|
|
/* try to use the sender header */
|
|
sender = header_raw_find (&headers, "Sender", NULL);
|
|
if (!sender) {
|
|
/* okay, try the field */
|
|
sender = header_raw_find (&headers, "From", NULL);
|
|
addr = header_address_decode (sender);
|
|
sender = NULL;
|
|
if (addr) {
|
|
if (addr->type == HEADER_ADDRESS_NAME)
|
|
sender = addr->v.addr;
|
|
else
|
|
sender = NULL;
|
|
}
|
|
|
|
if (!sender)
|
|
sender = "unknown@nodomain.com";
|
|
}
|
|
for ( ; *sender && isspace ((unsigned char) *sender); sender++);
|
|
camel_stream_write (stream, sender, strlen (sender));
|
|
if (addr)
|
|
header_address_unref (addr);
|
|
|
|
/* try to use the received header to get the date */
|
|
str = header_raw_find (&headers, "Received", NULL);
|
|
if (str) {
|
|
str = strrchr (str, ';');
|
|
if (str)
|
|
str++;
|
|
}
|
|
|
|
/* if there isn't one, try the Date field */
|
|
if (!str)
|
|
str = header_raw_find (&headers, "Date", NULL);
|
|
|
|
date = header_decode_date (str, &offset);
|
|
date += ((offset / 100) * (60 * 60)) + (offset % 100) * 60;
|
|
|
|
date_str = header_format_date (date, offset);
|
|
camel_stream_printf (stream, " %s\n", date_str);
|
|
g_free (date_str);
|
|
|
|
/* now write the message data */
|
|
camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (filtered_stream));
|
|
camel_object_unref (CAMEL_OBJECT (message));
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
camel_stream_flush (CAMEL_STREAM (filtered_stream));
|
|
|
|
g_ptr_array_free (input->uids, TRUE);
|
|
|
|
camel_stream_filter_remove (filtered_stream, fid);
|
|
camel_object_unref (CAMEL_OBJECT (from_filter));
|
|
camel_object_unref (CAMEL_OBJECT (filtered_stream));
|
|
camel_object_unref (CAMEL_OBJECT (stream));
|
|
|
|
mail_tool_camel_lock_down ();
|
|
}
|
|
|
|
static void
|
|
cleanup_save_messages (gpointer in_data, gpointer op_data,
|
|
CamelException *ex)
|
|
{
|
|
save_messages_input_t *input = (save_messages_input_t *) in_data;
|
|
|
|
g_free (input->path);
|
|
|
|
camel_object_unref (CAMEL_OBJECT (input->folder));
|
|
}
|
|
|
|
static const mail_operation_spec op_save_messages = {
|
|
describe_save_messages,
|
|
sizeof (save_messages_data_t),
|
|
setup_save_messages,
|
|
do_save_messages,
|
|
cleanup_save_messages
|
|
};
|
|
|
|
void
|
|
mail_do_save_messages (CamelFolder *folder, GPtrArray *uids, gchar *path)
|
|
{
|
|
save_messages_input_t *input;
|
|
|
|
g_return_if_fail (CAMEL_IS_FOLDER (folder));
|
|
g_return_if_fail (uids != NULL);
|
|
g_return_if_fail (path != NULL);
|
|
|
|
input = g_new (save_messages_input_t, 1);
|
|
input->folder = folder;
|
|
input->uids = uids;
|
|
input->path = g_strdup (path);
|
|
|
|
mail_operation_queue (&op_save_messages, input, TRUE);
|
|
}
|