aboutsummaryrefslogtreecommitdiffstats
path: root/mail/mail-send-recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/mail-send-recv.c')
-rw-r--r--mail/mail-send-recv.c672
1 files changed, 3 insertions, 669 deletions
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index 18cd0d5a51..980a242522 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -7,13 +7,14 @@
#include "camel/camel-filter-driver.h"
#include "camel/camel-folder.h"
#include "camel/camel-session.h"
-#include "camel/camel-uid-cache.h"
#include "evolution-storage.h"
#include "mail-mt.h"
#include "mail-config.h"
#include "mail-session.h"
+#include "mail-tools.h"
+#include "mail-ops.h"
/* for the dialogue stuff */
#include <glib.h>
@@ -23,664 +24,6 @@
/* send/receive email */
-extern char *evolution_dir;
-extern CamelFolder *mail_tool_filter_get_folder_func (CamelFilterDriver *d, const char *uri, void *data);
-extern CamelFolder *mail_tool_uri_to_folder(const char *uri, CamelException *ex);
-
-static FilterContext *
-load_context(void)
-{
- char *userrules;
- char *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
-setup_filter_driver(CamelFilterDriver *driver, FilterContext *fc, const char *source)
-{
- GString *fsearch, *faction;
- FilterFilter *rule = NULL;
-
- if (TRUE /* perform_logging */) {
- char *filename = g_strdup_printf("%s/evolution-filter-log", evolution_dir);
- FILE *logfile = fopen(filename, "a+");
- g_free(filename);
- if (logfile)
- camel_filter_driver_set_logfile(driver, logfile);
- }
-
- fsearch = g_string_new ("");
- faction = g_string_new ("");
-
- while ((rule = (FilterFilter *)rule_context_next_rule((RuleContext *)fc, (FilterRule *)rule, source))) {
- g_string_truncate (fsearch, 0);
- g_string_truncate (faction, 0);
-
- filter_rule_build_code ((FilterRule *)rule, fsearch);
- filter_filter_build_action (rule, faction);
-
- camel_filter_driver_add_rule(driver, ((FilterRule *)rule)->name, fsearch->str, faction->str);
- }
-
- g_string_free (fsearch, TRUE);
- g_string_free (faction, TRUE);
-}
-
-static CamelFolder *
-filter_get_folder(CamelFilterDriver *d, const char *uri, void *data, CamelException *ex)
-{
- CamelFolder *folder;
-
- folder = mail_tool_uri_to_folder(uri, ex);
-
- return folder;
-}
-
-/* used for both just filtering a folder + uid's, and for filtering a whole folder */
-/* used both for fetching mail, and for filtering mail */
-struct _filter_mail_msg {
- struct _mail_msg msg;
-
- CamelFolder *source_folder; /* where they come from */
- GPtrArray *source_uids; /* uids to copy, or NULL == copy all */
- CamelCancel *cancel;
- CamelFilterDriver *driver;
- int delete; /* delete messages after filtering them? */
- CamelFolder *destination; /* default destination for any messages, NULL for none */
-};
-
-/* since fetching also filters, we subclass the data here */
-struct _fetch_mail_msg {
- struct _filter_mail_msg fmsg;
-
- CamelCancel *cancel; /* we have our own cancellation struct, the other should be empty */
- int keep; /* keep on server? */
-
- char *source_uri;
-
- void (*done)(char *source, void *data);
- void *data;
-};
-
-/* filter a folder, or a subset thereof, uses source_folder/source_uids */
-/* this is shared with fetch_mail */
-static void
-filter_folder_filter(struct _mail_msg *mm)
-{
- struct _filter_mail_msg *m = (struct _filter_mail_msg *)mm;
- CamelFolder *folder;
- GPtrArray *uids, *folder_uids = NULL;
-
- if (m->cancel)
- camel_cancel_register(m->cancel);
-
- folder = m->source_folder;
-
- if (folder == NULL || camel_folder_get_message_count (folder) == 0) {
- if (m->cancel)
- camel_cancel_unregister(m->cancel);
- return;
- }
-
- if (m->destination) {
- camel_folder_freeze(m->destination);
- camel_filter_driver_set_default_folder(m->driver, m->destination);
- }
-
- camel_folder_freeze(folder);
-
- if (m->source_uids)
- uids = m->source_uids;
- else
- folder_uids = uids = camel_folder_get_uids (folder);
-
- camel_filter_driver_filter_folder(m->driver, folder, uids, m->delete, &mm->ex);
-
- if (folder_uids)
- camel_folder_free_uids(folder, folder_uids);
-
- /* sync and expunge */
- camel_folder_sync (folder, TRUE, &mm->ex);
- camel_folder_thaw(folder);
-
- if (m->destination)
- camel_folder_thaw(m->destination);
-
- if (m->cancel)
- camel_cancel_unregister(m->cancel);
-}
-
-static void
-filter_folder_filtered(struct _mail_msg *mm)
-{
-}
-
-static void
-filter_folder_free(struct _mail_msg *mm)
-{
- struct _filter_mail_msg *m = (struct _filter_mail_msg *)mm;
- int i;
-
- if (m->source_folder)
- camel_object_unref((CamelObject *)m->source_folder);
- if (m->source_uids) {
- for (i=0;i<m->source_uids->len;i++)
- g_free(m->source_uids->pdata[i]);
- g_ptr_array_free(m->source_uids, TRUE);
- }
- if (m->cancel)
- camel_cancel_unref(m->cancel);
- if (m->destination)
- camel_object_unref((CamelObject *)m->destination);
- camel_object_unref((CamelObject *)m->driver);
-}
-
-static struct _mail_msg_op filter_folder_op = {
- NULL, /* we do our own progress reporting? */
- filter_folder_filter,
- filter_folder_filtered,
- filter_folder_free,
-};
-
-void
-mail_filter_folder(CamelFolder *source_folder, GPtrArray *uids,
- FilterContext *fc, const char *type,
- CamelCancel *cancel)
-{
- struct _filter_mail_msg *m;
-
- m = mail_msg_new(&filter_folder_op, NULL, sizeof(*m));
- m->source_folder = source_folder;
- camel_object_ref((CamelObject *)source_folder);
- m->source_uids = uids;
- m->delete = FALSE;
- if (cancel) {
- m->cancel = cancel;
- camel_cancel_ref(cancel);
- }
-
- m->driver = camel_filter_driver_new(filter_get_folder, NULL);
- setup_filter_driver(m->driver, fc, type);
-
- e_thread_put(mail_thread_new, (EMsg *)m);
-}
-
-/* ********************************************************************** */
-
-static void
-fetch_mail_fetch(struct _mail_msg *mm)
-{
- struct _fetch_mail_msg *m = (struct _fetch_mail_msg *)mm;
- struct _filter_mail_msg *fm = (struct _filter_mail_msg *)mm;
- int i;
-
- if (m->cancel)
- camel_cancel_register(m->cancel);
-
- if ( (fm->destination = mail_tool_get_local_inbox(&mm->ex)) == NULL) {
- if (m->cancel)
- camel_cancel_unregister(m->cancel);
- return;
- }
-
- /* FIXME: this should support keep_on_server too, which would then perform a spool
- access thingy, right? problem is matching raw messages to uid's etc. */
- if (!strncmp (m->source_uri, "mbox:", 5)) {
- char *path = mail_tool_do_movemail (m->source_uri, &mm->ex);
-
- if (path && !camel_exception_is_set (&mm->ex)) {
- camel_filter_driver_filter_mbox(fm->driver, path, &mm->ex);
-
- if (!camel_exception_is_set (&mm->ex))
- unlink (path);
- }
- g_free (path);
- } else {
- CamelFolder *folder = fm->source_folder = mail_tool_get_inbox(m->source_uri, &mm->ex);
- CamelUIDCache *cache = NULL;
-
- if (folder) {
- /* this handles 'keep on server' stuff, if we have any new uid's to copy
- across, we need to copy them to a new array 'cause of the way fetch_mail_free works */
- if (!fm->delete) {
- char *cachename = mail_config_folder_to_cachename (folder, "cache-");
-
- cache = camel_uid_cache_new (cachename);
- if (cache) {
- GPtrArray *folder_uids, *cache_uids, *uids;
-
- folder_uids = camel_folder_get_uids(folder);
- cache_uids = camel_uid_cache_get_new_uids(cache, folder_uids);
- if (cache_uids) {
- /* need to copy this, sigh */
- fm->source_uids = uids = g_ptr_array_new();
- g_ptr_array_set_size(uids, cache_uids->len);
- for (i=0;i<cache_uids->len;i++)
- uids->pdata[i] = g_strdup(cache_uids->pdata[i]);
- camel_uid_cache_free_uids (cache_uids);
-
- filter_folder_filter(mm);
- if (!camel_exception_is_set (&mm->ex))
- camel_uid_cache_save (cache);
- camel_uid_cache_destroy (cache);
- }
- camel_folder_free_uids(folder, folder_uids);
- }
- g_free (cachename);
- } else {
- filter_folder_filter(mm);
- }
- }
-
- }
-
- if (m->cancel)
- camel_cancel_unregister(m->cancel);
-}
-
-static void
-fetch_mail_fetched(struct _mail_msg *mm)
-{
- struct _fetch_mail_msg *m = (struct _fetch_mail_msg *)mm;
-
- if (m->done)
- m->done(m->source_uri, m->data);
-}
-
-static void
-fetch_mail_free(struct _mail_msg *mm)
-{
- struct _fetch_mail_msg *m = (struct _fetch_mail_msg *)mm;
-
- g_free(m->source_uri);
- if (m->cancel)
- camel_cancel_unref(m->cancel);
-
- filter_folder_free(mm);
-}
-
-static struct _mail_msg_op fetch_mail_op = {
- NULL, /* we do our own progress reporting */
- fetch_mail_fetch,
- fetch_mail_fetched,
- fetch_mail_free,
-};
-
-/* ouch, a 'do everything' interface ... */
-void mail_fetch_mail(const char *source, int keep,
- FilterContext *fc, const char *type,
- CamelCancel *cancel,
- CamelFilterGetFolderFunc get_folder, void *get_data,
- CamelFilterStatusFunc *status, void *status_data,
- void (*done)(char *source, void *data), void *data)
-{
- struct _fetch_mail_msg *m;
- struct _filter_mail_msg *fm;
-
- m = mail_msg_new(&fetch_mail_op, NULL, sizeof(*m));
- fm = (struct _filter_mail_msg *)m;
- m->source_uri = g_strdup(source);
- fm->delete = !keep;
- if (cancel) {
- m->cancel = cancel;
- camel_cancel_ref(cancel);
- }
- m->done = done;
- m->data = data;
-
- fm->driver = camel_filter_driver_new(get_folder, get_data);
- setup_filter_driver(fm->driver, fc, type);
- if (status)
- camel_filter_driver_set_status_func(fm->driver, status, status_data);
-
- e_thread_put(mail_thread_new, (EMsg *)m);
-}
-
-
-/* updating of imap folders etc */
-struct _update_info {
- EvolutionStorage *storage;
-
- void (*done)(CamelStore *, void *data);
- void *data;
-};
-
-static void do_update_subfolders_rec(CamelStore *store, CamelFolderInfo *info, EvolutionStorage *storage, const char *prefix)
-{
- char *path, *name;
-
- path = g_strdup_printf("%s/%s", prefix, info->name);
- if (info->unread_message_count > 0)
- name = g_strdup_printf("%s (%d)", info->name, info->unread_message_count);
- else
- name = g_strdup(info->name);
-
- evolution_storage_update_folder(storage, path, name, info->unread_message_count > 0);
- g_free(name);
- if (info->child)
- do_update_subfolders_rec(store, info->child, storage, path);
- if (info->sibling)
- do_update_subfolders_rec(store, info->sibling, storage, prefix);
- g_free(path);
-}
-
-static void do_update_subfolders(CamelStore *store, CamelFolderInfo *info, void *data)
-{
- struct _update_info *uinfo = data;
-
- if (uinfo) {
- do_update_subfolders_rec(store, info, uinfo->storage, "");
- }
-
- if (uinfo->done)
- uinfo->done(store, uinfo->data);
-
- gtk_object_unref((GtkObject *)uinfo->storage);
- g_free(uinfo);
-}
-
-/* this interface is a little icky */
-int mail_update_subfolders(CamelStore *store, EvolutionStorage *storage,
- void (*done)(CamelStore *, void *data), void *data)
-{
- struct _update_info *info;
-
- /* FIXME: This wont actually work entirely right, as a failure may lose this data */
- /* however, this isn't a big problem ... */
- info = g_malloc0(sizeof(*info));
- info->storage = storage;
- gtk_object_ref((GtkObject *)storage);
- info->done = done;
- info->data = data;
-
- return mail_get_folderinfo(store, do_update_subfolders, info);
-}
-
-/* ********************************************************************** */
-/* sending stuff */
-/* ** SEND MAIL *********************************************************** */
-
-/* send 1 message to a specific transport */
-static void
-mail_send_message(CamelMimeMessage *message, const char *destination, CamelFilterDriver *driver, CamelException *ex)
-{
- extern CamelFolder *sent_folder; /* FIXME */
- CamelMessageInfo *info;
- CamelTransport *xport;
- const char *version;
-
- if (SUB_VERSION[0] == '\0')
- version = "Evolution (" VERSION " - Preview Release)";
- else
- version = "Evolution (" VERSION "/" SUB_VERSION " - Preview Release)";
- camel_medium_add_header(CAMEL_MEDIUM (message), "X-Mailer", version);
- camel_mime_message_set_date(message, CAMEL_MESSAGE_DATE_CURRENT, 0);
-
- xport = camel_session_get_transport(session, destination, ex);
- if (camel_exception_is_set(ex))
- return;
-
- mail_tool_send_via_transport(xport, (CamelMedium *)message, ex);
- camel_object_unref((CamelObject *)xport);
- if (camel_exception_is_set(ex))
- return;
-
- /* post-process */
- info = camel_message_info_new();
- info->flags = CAMEL_MESSAGE_SEEN;
-
- if (driver)
- camel_filter_driver_filter_message(driver, message, info, "", ex);
-
- if (sent_folder)
- camel_folder_append_message(sent_folder, message, info, ex);
-
- camel_message_info_free(info);
-}
-
-/* ********************************************************************** */
-
-struct _send_mail_msg {
- struct _mail_msg msg;
-
- CamelFilterDriver *driver;
- char *destination;
- CamelMimeMessage *message;
-
- void (*done)(char *uri, CamelMimeMessage *message, gboolean sent, void *data);
- void *data;
-};
-
-static char *send_mail_desc(struct _mail_msg *mm, int done)
-{
- struct _send_mail_msg *m = (struct _send_mail_msg *)mm;
- const char *subject;
-
- subject = camel_mime_message_get_subject(m->message);
- if (subject && subject[0])
- return g_strdup_printf (_("Sending \"%s\""), subject);
- else
- return g_strdup(_("Sending message"));
-}
-
-static void send_mail_send(struct _mail_msg *mm)
-{
- struct _send_mail_msg *m = (struct _send_mail_msg *)mm;
-
- camel_cancel_register(mm->cancel);
- mail_send_message(m->message, m->destination, m->driver, &mm->ex);
- camel_cancel_unregister(mm->cancel);
-}
-
-static void send_mail_sent(struct _mail_msg *mm)
-{
- struct _send_mail_msg *m = (struct _send_mail_msg *)mm;
-
- if (m->done)
- m->done(m->destination, m->message, !camel_exception_is_set(&mm->ex), m->data);
-}
-
-static void send_mail_free(struct _mail_msg *mm)
-{
- struct _send_mail_msg *m = (struct _send_mail_msg *)mm;
-
- camel_object_unref((CamelObject *)m->message);
- g_free(m->destination);
-}
-
-static struct _mail_msg_op send_mail_op = {
- send_mail_desc,
- send_mail_send,
- send_mail_sent,
- send_mail_free,
-};
-
-int
-mail_send_mail(const char *uri, CamelMimeMessage *message, void (*done) (char *uri, CamelMimeMessage *message, gboolean sent, void *data), void *data)
-{
- struct _send_mail_msg *m;
- int id;
- FilterContext *fc;
-
- m = mail_msg_new(&send_mail_op, NULL, sizeof(*m));
- m->destination = g_strdup(uri);
- m->message = message;
- camel_object_ref((CamelObject *)message);
- m->data = data;
- m->done = done;
-
- id = m->msg.seq;
-
- m->driver = camel_filter_driver_new(filter_get_folder, NULL);
- fc = load_context();
- setup_filter_driver(m->driver, fc, FILTER_SOURCE_OUTGOING);
- gtk_object_unref((GtkObject *)fc);
-
- e_thread_put(mail_thread_new, (EMsg *)m);
- return id;
-}
-
-/* ** SEND MAIL QUEUE ***************************************************** */
-
-struct _send_queue_msg {
- struct _mail_msg msg;
-
- CamelFolder *queue;
- char *destination;
-
- CamelFilterDriver *driver;
- CamelCancel *cancel;
-
- /* we use camelfilterstatusfunc, even though its not the filter doing it */
- CamelFilterStatusFunc *status;
- void *status_data;
-
- void (*done)(char *destination, void *data);
- void *data;
-};
-
-static void
-report_status(struct _send_queue_msg *m, enum camel_filter_status_t status, int pc, const char *desc, ...)
-{
- va_list ap;
- char *str;
-
- if (m->status) {
- va_start(ap, desc);
- str = g_strdup_vprintf(desc, ap);
- m->status(m->driver, status, pc, str, m->status_data);
- g_free(str);
- }
-}
-
-static void
-send_queue_send(struct _mail_msg *mm)
-{
- struct _send_queue_msg *m = (struct _send_queue_msg *)mm;
- GPtrArray *uids;
- int i;
- extern CamelFolder *sent_folder; /* FIXME */
-
- printf("sending queue\n");
-
- uids = camel_folder_get_uids(m->queue);
- if (uids == NULL || uids->len == 0)
- return;
-
- if (m->cancel)
- camel_cancel_register(m->cancel);
-
- for (i=0; i<uids->len; i++) {
- CamelMimeMessage *message;
- char *destination;
- int pc = (100 * i)/uids->len;
-
- report_status(m, FILTER_STATUS_START, pc, "Sending message %d of %d", i+1, uids->len);
-
- message = camel_folder_get_message(m->queue, uids->pdata[i], &mm->ex);
- if (camel_exception_is_set(&mm->ex))
- break;
-
- /* Get the preferred transport URI */
- destination = (char *)camel_medium_get_header(CAMEL_MEDIUM(message), "X-Evolution-Transport");
- if (destination) {
- destination = g_strdup(destination);
- camel_medium_remove_header(CAMEL_MEDIUM(message), "X-Evolution-Transport");
- mail_send_message(message, g_strstrip(destination), m->driver, &mm->ex);
- g_free(destination);
- } else
- mail_send_message(message, m->destination, m->driver, &mm->ex);
-
- if (camel_exception_is_set(&mm->ex))
- break;
-
- camel_folder_set_message_flags(m->queue, uids->pdata[i], CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
- }
-
- if (camel_exception_is_set(&mm->ex))
- report_status(m, FILTER_STATUS_END, 100, "Failed on message %d of %d", i+1, uids->len);
- else
- report_status(m, FILTER_STATUS_END, 100, "Complete.");
-
- camel_folder_free_uids(m->queue, uids);
-
- if (!camel_exception_is_set(&mm->ex))
- camel_folder_expunge(m->queue, &mm->ex);
-
- if (sent_folder)
- camel_folder_sync(sent_folder, FALSE, &mm->ex);
-
- if (m->cancel)
- camel_cancel_unregister(m->cancel);
-}
-
-static void
-send_queue_sent(struct _mail_msg *mm)
-{
- struct _send_queue_msg *m = (struct _send_queue_msg *)mm;
-
- if (m->done)
- m->done(m->destination, m->data);
-}
-
-static void
-send_queue_free(struct _mail_msg *mm)
-{
- struct _send_queue_msg *m = (struct _send_queue_msg *)mm;
-
- camel_object_unref((CamelObject *)m->queue);
- g_free(m->destination);
- if (m->cancel)
- camel_cancel_unref(m->cancel);
-}
-
-static struct _mail_msg_op send_queue_op = {
- NULL, /* do our own reporting, as with fetch mail */
- send_queue_send,
- send_queue_sent,
- send_queue_free,
-};
-
-/* same interface as fetch_mail, just 'cause i'm lazy today (and we need to run it from the same spot?) */
-void
-mail_send_queue(CamelFolder *queue, const char *destination,
- FilterContext *fc, const char *type,
- CamelCancel *cancel,
- CamelFilterGetFolderFunc get_folder, void *get_data,
- CamelFilterStatusFunc *status, void *status_data,
- void (*done)(char *destination, void *data), void *data)
-{
- struct _send_queue_msg *m;
-
- m = mail_msg_new(&send_queue_op, NULL, sizeof(*m));
- m->queue = queue;
- camel_object_ref((CamelObject *)queue);
- m->destination = g_strdup(destination);
- if (cancel) {
- m->cancel = cancel;
- camel_cancel_ref(cancel);
- }
- m->status = status;
- m->status_data = status_data;
- m->done = done;
- m->data = data;
-
- m->driver = camel_filter_driver_new(get_folder, get_data);
- setup_filter_driver(m->driver, fc, type);
-
- e_thread_put(mail_thread_new, (EMsg *)m);
-}
-
-
/* ********************************************************************** */
/* This stuff below is independent of the stuff above */
@@ -1101,7 +444,7 @@ void mail_send_receive(void)
if (!account || !account->transport)
return;
- fc = load_context();
+ fc = mail_load_filter_context();
/* what to do about pop before smtp ?
Well, probably hook into receive_done or receive_status on
@@ -1155,12 +498,3 @@ void mail_send_receive(void)
gtk_object_unref((GtkObject *)fc);
}
-void mail_filter_on_demand(CamelFolder *folder, GPtrArray *uids)
-{
- FilterContext *fc;
-
- fc = load_context();
- mail_filter_folder(folder, uids, fc, FILTER_SOURCE_INCOMING, NULL);
- gtk_object_unref((GtkObject *)fc);
-}
-