[evolution/mail-mt-cleanup: 3/7] Huge mail-mt refactoring



commit deb44993531319d6f6b8af2b1a241bb0e1f17ea9
Author: Jonathon Jongsma <jonathon quotidian org>
Date:   Thu Dec 31 15:20:15 2009 -0600

    Huge mail-mt refactoring
    
    The root problem is that the functions in mail-mt had hard dependencies on
    EShell for tracking activity/task status and reporting errors to the shell. This
    dependency is blocking the mail backend split, so I needed to refactor it.
    Removing this dependency turned out to be a significant amount of work.  At a
    high level, all that is done in this patch is to change the mail-mt stuff so
    that it uses proper objects so we can use GObject signals to provide loose
    coupling between the components.  A more detailed explanation follows:
    - MailMsg was a simple struct, but has been refactored to be a proper GObject so
      that it can emit signals.  I named this object EMailMsg, but am considering
      renaming it something like EMailTask, which I think is less confusing and
      matches its function more closely.  I presume the 'Msg' terminology comes from
      the days of EMsgPort, but this class has nothing to do with email messages, so
      I think it just creates confusion right now.
    - Previously, when a MailMsg was created, it was automatically added to a hash
      table of active msgs so that we can track and cancel them, etc.
      - In addition, MailMsg pushed its associated EActivity (if any) to the
        EShellBackend so that the UI could track active activities.
    - The refactored code follows the same basic pattern, but instead of adding new
      EmailMsg objects to a simple hash table, they are added to a new singleton
      object (EMailTaskManager) which will then emit a "task-added" signal
      - EMailBackend will listen for the "task-added" signal on the task manager and
        then add the associated activity to the UI.
    
    One additional side-effect to these changes is that mail_in_main_thread() is now
    e_in_main_thread()
      - There is a new wrapper function called e_thread_init() which keeps track of
        the main thread rather than assuming that the first person to call
        mail_msg_init() is the main thread.
      - This results in libeutil linking against gthread-2.0, which might be
        contentious, but seems OK to me.

 configure.ac                                       |    2 +-
 e-util/e-marshal.list                              |    1 +
 e-util/e-util.c                                    |   28 +
 e-util/e-util.h                                    |    3 +
 mail/Makefile.am                                   |    4 +
 mail/e-mail-backend.c                              |  102 ++-
 mail/e-mail-msg.c                                  |  533 +++++++
 mail/e-mail-msg.h                                  |   96 ++
 mail/e-mail-reader-utils.c                         |   30 +-
 mail/e-mail-reader.c                               |   15 +-
 mail/e-mail-task-manager.c                         |  449 ++++++
 mail/e-mail-task-manager.h                         |   93 ++
 mail/em-account-editor.c                           |   12 +-
 mail/em-composer-utils.c                           |   60 +-
 mail/em-folder-properties.c                        |   12 +-
 mail/em-folder-tree.c                              |  185 ++-
 mail/em-folder-utils.c                             |  233 ++-
 mail/em-format-html-print.c                        |   18 +-
 mail/em-format-html.c                              |   86 +-
 mail/em-subscribe-editor.c                         |  183 ++-
 mail/em-sync-stream.c                              |    8 +-
 mail/em-utils.c                                    |   32 +-
 mail/importers/elm-importer.c                      |   91 +-
 mail/importers/mail-importer.c                     |   83 +-
 mail/importers/pine-importer.c                     |   89 +-
 mail/mail-folder-cache.c                           |   67 +-
 mail/mail-mt.c                                     |  810 +---------
 mail/mail-mt.h                                     |   57 +-
 mail/mail-ops.c                                    | 1600 ++++++++++++++------
 mail/mail-ops.h                                    |   10 +-
 mail/mail-send-recv.c                              |   62 +-
 mail/mail-session.c                                |   76 +-
 mail/mail-vfolder.c                                |  171 ++-
 mail/message-list.c                                |  154 ++-
 modules/mail/e-mail-shell-backend.c                |   10 +-
 modules/mail/e-mail-shell-view-actions.c           |    3 +-
 modules/mail/e-mail-shell-view-private.c           |   12 +-
 plugins/groupwise-features/share-folder-common.c   |   78 +-
 plugins/itip-formatter/itip-formatter.c            |   53 +-
 .../mailing-list-actions/mailing-list-actions.c    |   10 +-
 plugins/mark-all-read/mark-all-read.c              |   10 +-
 plugins/templates/templates.c                      |   11 +-
 shell/main.c                                       |    3 +-
 43 files changed, 3759 insertions(+), 1886 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d060f37..c41d0a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1174,7 +1174,7 @@ AC_SUBST(CERT_UI_LIBS)
 dnl ************
 dnl E_UTIL Flags
 dnl ************
-EVO_SET_COMPILE_FLAGS(E_UTIL, libedataserverui-1.2 camel-1.2 $mozilla_nspr, $MANUAL_NSPR_CFLAGS $MANUAL_NSPR_LIBS)
+EVO_SET_COMPILE_FLAGS(E_UTIL, libedataserverui-1.2 camel-1.2 gthread-2.0 $mozilla_nspr, $MANUAL_NSPR_CFLAGS $MANUAL_NSPR_LIBS)
 AC_SUBST(E_UTIL_CFLAGS)
 AC_SUBST(E_UTIL_LIBS)
 
diff --git a/e-util/e-marshal.list b/e-util/e-marshal.list
index b0be6ab..c30a8e6 100644
--- a/e-util/e-marshal.list
+++ b/e-util/e-marshal.list
@@ -37,6 +37,7 @@ NONE:LONG,LONG
 NONE:OBJECT,BOOLEAN
 NONE:OBJECT,DOUBLE,DOUBLE,BOOLEAN
 NONE:OBJECT,OBJECT
+NONE:OBJECT,UINT
 NONE:POINTER,INT
 NONE:POINTER,INT,INT,INT,INT
 NONE:POINTER,INT,OBJECT
diff --git a/e-util/e-util.c b/e-util/e-util.c
index ade2b38..dfbd934 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -54,6 +54,34 @@
 #include "e-util.h"
 #include "e-util-private.h"
 
+static gpointer main_thread = NULL;
+/**
+ * e_thread_init:
+ *
+ * initializes the glib threading subsystem and also remembers which thread is
+ * the main thread
+ */
+void
+e_thread_init (void)
+{
+	if (g_thread_get_initialized ())
+		return;
+
+	g_thread_init (NULL);
+	main_thread = g_thread_self ();
+}
+
+/**
+ * e_in_main_thread:
+ *
+ * determines whether the current thread is the main thread or not
+ */
+gboolean
+e_in_main_thread (void)
+{
+	return main_thread == g_thread_self ();
+}
+
 /**
  * e_get_user_data_dir:
  *
diff --git a/e-util/e-util.h b/e-util/e-util.h
index 276d20f..01c16fb 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -53,6 +53,9 @@ typedef enum {
 
 typedef void (*ETypeFunc) (GType type, gpointer user_data);
 
+void e_thread_init (void);
+gboolean e_in_main_thread (void);
+
 const gchar *	e_get_user_data_dir		(void);
 const gchar *	e_get_accels_filename		(void);
 void		e_show_uri			(GtkWindow *parent,
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 2e6a69a..032983c 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -46,12 +46,14 @@ mailinclude_HEADERS =					\
 	e-mail-label-tree-view.h			\
 	e-mail-local.h					\
 	e-mail-migrate.h				\
+	e-mail-msg.h					\
 	e-mail-reader.h					\
 	e-mail-reader-utils.h				\
 	e-mail-search-bar.h				\
 	e-mail-sidebar.h				\
 	e-mail-store.h					\
 	e-mail-tag-editor.h				\
+	e-mail-task-manager.h				\
 	e-searching-tokenizer.h				\
 	em-account-editor.h				\
 	em-composer-utils.h				\
@@ -105,12 +107,14 @@ libevolution_mail_la_SOURCES =				\
 	e-mail-label-tree-view.c			\
 	e-mail-local.c					\
 	e-mail-migrate.c				\
+	e-mail-msg.c					\
 	e-mail-reader.c					\
 	e-mail-reader-utils.c				\
 	e-mail-search-bar.c				\
 	e-mail-sidebar.c				\
 	e-mail-store.c					\
 	e-mail-tag-editor.c				\
+	e-mail-task-manager.c				\
 	e-searching-tokenizer.c				\
 	em-account-editor.c				\
 	em-composer-utils.c				\
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index 4ab4440..c8459af 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -27,23 +27,27 @@
 #include <camel/camel.h>
 
 #include "e-util/e-account-utils.h"
+#include "e-util/e-alert-activity.h"
 #include "e-util/e-alert-dialog.h"
 
 #include "misc/e-account-combo-box.h"
 
 #include "shell/e-shell.h"
 
-#include "mail/e-mail-local.h"
-#include "mail/e-mail-migrate.h"
-#include "mail/e-mail-store.h"
-#include "mail/em-event.h"
-#include "mail/em-folder-tree-model.h"
-#include "mail/em-utils.h"
-#include "mail/mail-autofilter.h"
-#include "mail/mail-folder-cache.h"
-#include "mail/mail-ops.h"
-#include "mail/mail-session.h"
-#include "mail/mail-vfolder.h"
+#include "e-mail-local.h"
+#include "e-mail-migrate.h"
+#include "e-mail-msg.h"
+#include "e-mail-store.h"
+#include "e-mail-task-manager.h"
+#include "em-event.h"
+#include "em-folder-tree-model.h"
+#include "em-utils.h"
+#include "mail-autofilter.h"
+#include "mail-folder-cache.h"
+#include "mail-mt.h"
+#include "mail-ops.h"
+#include "mail-session.h"
+#include "mail-vfolder.h"
 
 #define E_MAIL_BACKEND_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -120,7 +124,7 @@ mail_backend_prepare_for_offline_cb (EShell *shell,
 			window, NULL, "mail:ask-quick-offline", NULL);
 
 	if (!synchronize) {
-		mail_cancel_all ();
+		e_mail_task_manager_cancel_all ();
 		camel_session_set_network_state (session, FALSE);
 	}
 
@@ -206,7 +210,8 @@ mail_backend_final_sync (CamelStore *store,
 static gboolean
 mail_backend_poll_to_quit (EActivity *activity)
 {
-	return mail_msg_active ((guint) -1);
+	return e_mail_task_manager_num_tasks
+		(e_mail_task_manager_get_default ()) > 0;
 }
 
 /* Helper for mail_backend_prepare_for_quit_cb() */
@@ -254,12 +259,12 @@ mail_backend_prepare_for_quit_cb (EShell *shell,
 	e_mail_store_foreach ((GHFunc) mail_backend_final_sync, &sync_data);
 
 	/* Cancel all activities. */
-	mail_cancel_all ();
+	e_mail_task_manager_cancel_all ();
 
 	/* Now we poll until all activities are actually cancelled.
 	 * Reffing the activity delays quitting; the reference count
 	 * acts like a counting semaphore. */
-	if (mail_msg_active ((guint) -1))
+	if (e_mail_task_manager_num_tasks (e_mail_task_manager_get_default ()) > 0)
 		g_timeout_add_seconds_full (
 			G_PRIORITY_DEFAULT, QUIT_POLL_INTERVAL,
 			(GSourceFunc) mail_backend_poll_to_quit,
@@ -375,6 +380,62 @@ mail_backend_folder_changed_cb (MailFolderCache *folder_cache,
 }
 
 static void
+error_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer data)
+{
+	gtk_widget_destroy ((GtkWidget*) dialog);
+}
+
+static void
+mail_msg_error_response_cb (EMailMsg *msg, EAlert *alert, gpointer data)
+{
+	EActivity *activity = NULL;
+	GtkWindow *parent = NULL;
+	GtkWidget *dialog = NULL;
+	EShell *shell = NULL;
+	EMailBackend *backend = E_MAIL_BACKEND (data);
+
+	g_return_if_fail (alert);
+	g_return_if_fail (data);
+
+	/* FIXME: check to see if we have dialogue already running for this
+	 * operation ??
+	 */
+
+	shell = e_shell_backend_get_shell ((EShellBackend*)backend);
+	parent = e_shell_get_active_window (shell);
+	dialog = e_alert_dialog_new (parent, alert);
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (error_dialog_response_cb), NULL);
+
+	if (e_mail_msg_get_cancellable (msg)) {
+		activity = e_alert_activity_new_warning (dialog);
+		e_shell_backend_add_activity ((EShellBackend*)backend, activity);
+	} else {
+		gtk_widget_show (dialog);
+	}
+}
+
+static void
+mail_msg_activity_created_cb (EMailMsg *msg, EActivity *activity, gpointer data)
+{
+	EShellBackend *shell_backend = (EShellBackend*) data;
+
+	g_return_if_fail (activity);
+	g_return_if_fail (data);
+
+	e_shell_backend_add_activity (shell_backend, activity);
+}
+
+static void
+task_mgr_task_added_cb (EMailTaskManager *mgr, EMailMsg *msg, guint id, gpointer data)
+{
+	g_signal_connect (msg, "activity-created",
+			  G_CALLBACK (mail_msg_activity_created_cb), data);
+	g_signal_connect (msg, "error-response",
+			  G_CALLBACK (mail_msg_error_response_cb), data);
+}
+
+static void
 mail_backend_constructed (GObject *object)
 {
 	EShell *shell;
@@ -433,13 +494,23 @@ mail_backend_constructed (GObject *object)
 		G_CALLBACK (mail_backend_folder_changed_cb), shell);
 
 	mail_config_init ();
+
 	mail_msg_init ();
+	g_signal_connect (
+		e_mail_task_manager_get_default (),
+		"task-added", G_CALLBACK (task_mgr_task_added_cb), shell_backend);
 
 	data_dir = e_shell_backend_get_data_dir (shell_backend);
 	e_mail_store_init (data_dir);
 }
 
 static void
+mail_backend_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
 mail_backend_class_init (EMailBackendClass *class)
 {
 	GObjectClass *object_class;
@@ -450,6 +521,7 @@ mail_backend_class_init (EMailBackendClass *class)
 
 	object_class = G_OBJECT_CLASS (class);
 	object_class->constructed = mail_backend_constructed;
+	object_class->finalize = mail_backend_finalize;
 
 	shell_backend_class = E_SHELL_BACKEND_CLASS (class);
 	shell_backend_class->migrate = e_mail_migrate;
diff --git a/mail/e-mail-msg.c b/mail/e-mail-msg.c
new file mode 100644
index 0000000..e2b23f4
--- /dev/null
+++ b/mail/e-mail-msg.c
@@ -0,0 +1,533 @@
+/*
+ * e-mail-msg.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
+ *
+ * Copyright (C) 2009 Intel Coporation
+ *
+ */
+
+#include <string.h>
+
+#include <camel/camel-exception.h>
+#include <camel/camel-object.h>
+#include <camel/camel-operation.h>
+
+#include "e-util/e-alert.h"
+#include "e-util/e-alert-activity.h"
+#include "e-util/e-activity.h"
+#include "e-util/e-util.h"
+
+#include "e-mail-msg.h"
+#include "e-mail-task-manager.h"
+#include "mail-mt.h"
+
+G_DEFINE_TYPE (EMailMsg, e_mail_msg, G_TYPE_OBJECT)
+
+#define MAIL_MSG_PRIVATE(o) \
+		(G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_MAIL_MSG, EMailMsgPrivate))
+
+#define d(x)
+
+enum {
+	ACTIVITY_CREATED,
+	ERROR_RESPONSE,
+	LAST_SIGNAL
+};
+
+enum {
+	PROP0,
+	PROP_ID,
+	PROP_ACTIVITY,
+	PROP_ALERT
+};
+
+enum
+{
+	ACTIVITY_STATE_UNINITIALIZED = 0,
+	ACTIVITY_STATE_INITIALIZING,
+	ACTIVITY_STATE_ACTIVE,
+	ACTIVITY_STATE_REMOVED
+};
+
+static guint signals[LAST_SIGNAL];
+static guint mail_msg_seq; /* sequence number of each message */
+G_LOCK_DEFINE_STATIC (mail_msg);
+
+typedef struct _OpStatusMsg OpStatusMsg;
+struct _EMailMsgPrivate
+{
+	volatile gint ref_count;
+	guint seq;	/* seq number for synchronisation */
+	gint priority;		/* priority (default = 0) */
+	CamelOperation *cancel;	/* a cancellation/status handle */
+	CamelException ex;	/* an initialised camel exception, upto the caller to use this */
+
+	/* ex-MailMsgPriv */
+	gint activity_state;	/* sigh sigh sigh, we need to keep track of the state external to the
+				   pointer itself for locking/race conditions */
+	EActivity *activity;
+	EAlert *error;
+	OpStatusMsg *status_msg;
+	gboolean cancellable;
+};
+
+
+/* private derived msg object */
+struct _OpStatusMsg {
+	EMailMsg base;
+
+	EMailMsg *parent_msg;
+	gchar *what;
+	gint pc;
+	gpointer data;
+};
+typedef struct _OpStatusMsgClass OpStatusMsgClass;
+struct _OpStatusMsgClass {
+	EMailMsgClass parent_class;
+};
+
+GType op_status_msg_get_type (void);
+G_DEFINE_TYPE (OpStatusMsg, op_status_msg, E_TYPE_MAIL_MSG)
+
+static void
+op_cancelled_cb (EActivity *activity,
+                 gpointer user_data)
+{
+	e_mail_msg_cancel ((EMailMsg*) user_data);
+}
+
+static void
+op_status_exec (OpStatusMsg *status)
+{
+	/* the parent message that we're tracking the status of */
+	EMailMsg *msg;
+	gchar *out, *p, *o, c;
+	gint pc;
+
+	g_return_if_fail (e_in_main_thread ());
+
+	G_LOCK (mail_msg);
+
+	msg = status->parent_msg;
+	if (!msg) {
+		G_UNLOCK (mail_msg);
+		return;
+	}
+	/* hold a reference to the tracked msg so it doesn't get destroyed while
+	 * the callback is executing */
+	g_object_ref (msg);
+
+	out = g_alloca (strlen (status->what) * 2 + 1);
+	o = out;
+	p = status->what;
+	while ((c = *p++)) {
+		if (c == '%')
+			*o++ = '%';
+		*o++ = c;
+	}
+	*o = 0;
+
+	pc = status->pc;
+
+	if (msg->priv->activity == NULL) {
+		gchar *what = NULL;
+
+		/* activity is being created/removed?  well leave it be */
+		if (msg->priv->activity_state == ACTIVITY_STATE_INITIALIZING ||
+		    msg->priv->activity_state == ACTIVITY_STATE_REMOVED) {
+			G_UNLOCK (mail_msg);
+		} else {
+			EMailMsgClass *klass = E_MAIL_MSG_GET_CLASS (msg);
+			msg->priv->activity_state = ACTIVITY_STATE_INITIALIZING;
+
+			G_UNLOCK (mail_msg);
+			if (klass->desc)
+				what = klass->desc (msg);
+			else if (status->what)
+				what = g_strdup (status->what);
+			/* message is not very useful for a user, see bug 271734*/
+			else {
+				what = g_strdup("");
+			}
+
+			msg->priv->activity = e_activity_new (what);
+			e_activity_set_allow_cancel (msg->priv->activity, TRUE);
+			e_activity_set_percent (msg->priv->activity, 0.0);
+			g_signal_emit (msg, signals[ACTIVITY_CREATED], 0, msg->priv->activity);
+
+			g_signal_connect (msg->priv->activity, "cancelled",
+					  G_CALLBACK (op_cancelled_cb), msg);
+
+			g_free (what);
+			G_LOCK (mail_msg);
+			msg->priv->activity_state = ACTIVITY_STATE_ACTIVE;
+			G_UNLOCK (mail_msg);
+		}
+	} else if (msg->priv->activity != NULL) {
+		G_UNLOCK (mail_msg);
+		e_activity_set_primary_text (msg->priv->activity, out);
+		e_activity_set_percent (msg->priv->activity, pc / 100.0);
+	} else {
+		G_UNLOCK (mail_msg);
+	}
+
+	g_object_unref (msg);
+}
+
+static void
+op_status_msg_finalize (GObject *object)
+{
+	OpStatusMsg *msg = (OpStatusMsg*) object;
+	g_free (msg->what);
+
+	if (msg->parent_msg)
+		g_object_remove_weak_pointer ((GObject*) msg->parent_msg,
+					      (gpointer*) &msg->parent_msg);
+
+	G_OBJECT_CLASS (op_status_msg_parent_class)->finalize (object);
+}
+
+static void
+op_status_msg_class_init (OpStatusMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = op_status_msg_finalize;
+
+	klass->parent_class.desc = NULL;
+	klass->parent_class.exec = (MailMsgExecFunc) op_status_exec;
+	klass->parent_class.done = NULL;
+}
+
+static void
+op_status_msg_init (OpStatusMsg *msg)
+{
+}
+
+static void
+mail_operation_status (CamelOperation *op, const gchar *what, gint pc, gpointer data)
+{
+	OpStatusMsg *m;
+
+	d(printf("got operation statys: %s %d%%\n", what, pc));
+
+	m = g_object_new (op_status_msg_get_type (), NULL);
+	m->parent_msg = data;
+	g_object_add_weak_pointer ((GObject*) m->parent_msg,
+				   (gpointer*) &m->parent_msg);
+	m->what = g_strdup(what);
+	switch (pc) {
+	case CAMEL_OPERATION_START:
+		pc = 0;
+		break;
+	case CAMEL_OPERATION_END:
+		pc = 100;
+		break;
+	}
+	m->pc = pc;
+	e_mail_task_manager_main_loop_push(e_mail_task_manager_get_default (),
+					   (EMailMsg*) m);
+}
+
+
+void
+e_mail_msg_finish (EMailMsg *msg)
+{
+	EAlert *alert = NULL;
+	gchar *what = NULL;
+	EMailMsgClass *klass = E_MAIL_MSG_GET_CLASS (msg);
+	CamelException *ex = &msg->priv->ex;
+
+	if (camel_exception_is_set(ex)
+	    && ex->id != CAMEL_EXCEPTION_USER_CANCEL
+	    && ex->id != CAMEL_EXCEPTION_FOLDER_INVALID_UID
+	    && !(msg->priv->cancel && camel_operation_cancel_check (msg->priv->cancel))) {
+
+		if (klass->desc
+		    && (what = klass->desc (msg))) {
+			alert = e_alert_new ("mail:async-error", what, camel_exception_get_description(ex), NULL);
+			g_free(what);
+		} else
+			alert = e_alert_new ("mail:async-error-nodescribe", camel_exception_get_description(ex), NULL);
+	}
+
+	msg->priv->error = alert;
+
+	g_return_if_fail (e_in_main_thread ());
+
+	if (alert)
+		g_signal_emit (msg, signals[ERROR_RESPONSE], 0, alert);
+	if (msg->priv->activity)
+		e_activity_complete (msg->priv->activity);
+}
+
+void
+e_mail_msg_cancel (EMailMsg *msg)
+{
+	if (msg && msg->priv->cancel)
+		camel_operation_cancel(msg->priv->cancel);
+}
+
+static void
+e_mail_msg_get_property (GObject *object, guint property_id,
+			       GValue *value, GParamSpec *pspec)
+{
+	EMailMsg *msg = (EMailMsg*) object;
+	switch (property_id)
+	{
+		case PROP_ID:
+			g_value_set_uint (value, msg->priv->seq);
+			break;
+		case PROP_ACTIVITY:
+			g_value_set_object (value, msg->priv->activity);
+			break;
+		case PROP_ALERT:
+			g_value_set_object (value, msg->priv->error);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+	}
+}
+
+static void
+e_mail_msg_set_property (GObject *object, guint property_id,
+			       const GValue *value, GParamSpec *pspec)
+{
+	switch (property_id)
+	{
+		case PROP_ID:
+		case PROP_ACTIVITY:
+		case PROP_ALERT:
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+	}
+}
+
+static void
+e_mail_msg_dispose (GObject *object)
+{
+	EMailMsg *msg = (EMailMsg*) object;
+
+	if (msg->priv->activity) {
+		g_warn_if_fail (e_activity_is_completed (msg->priv->activity) ||
+				e_activity_is_cancelled (msg->priv->activity));
+		g_object_unref (msg->priv->activity);
+		msg->priv->activity = NULL;
+	}
+
+	if (msg->priv->error) {
+		g_object_unref (msg->priv->error);
+		msg->priv->error = NULL;
+	}
+
+	if (msg->priv->cancel != NULL) {
+		camel_operation_mute (msg->priv->cancel);
+		camel_operation_unref (msg->priv->cancel);
+		msg->priv->cancel = NULL;
+	}
+
+	camel_exception_clear (&msg->priv->ex);
+
+	G_OBJECT_CLASS (e_mail_msg_parent_class)->dispose (object);
+}
+
+static void
+e_mail_msg_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (e_mail_msg_parent_class)->finalize (object);
+}
+
+static void
+e_mail_msg_constructed (GObject *object)
+{
+	EMailMsg *msg = (EMailMsg*) object;
+	G_LOCK (mail_msg);
+	msg->priv->seq = mail_msg_seq++;
+	G_UNLOCK (mail_msg);
+	/* It might seem like this next line would cause an infinite loop (since
+	 * mail_operation_status() also calls creates a new EMailMsg), but it
+	 * won't. The callback passed to camel_operation_new() only gets called
+	 * if somebody calls camel_operation_start(), camel_operation_end(), or
+	 * camel_operation_progress() on the returned CamelOperation. Since
+	 * op_status_exec() does not call any camel functions, this callback
+	 * will never be triggered for that particular operation. */
+	msg->priv->cancel = camel_operation_new(mail_operation_status, msg);
+
+	camel_exception_init(&msg->priv->ex);
+	msg->priv->cancellable = TRUE;
+	msg->priv->activity_state = ACTIVITY_STATE_UNINITIALIZED;
+}
+
+
+static void
+e_mail_msg_class_init (EMailMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (EMailMsgPrivate));
+
+	object_class->get_property = e_mail_msg_get_property;
+	object_class->set_property = e_mail_msg_set_property;
+	object_class->constructed = e_mail_msg_constructed;
+	object_class->dispose = e_mail_msg_dispose;
+	object_class->finalize = e_mail_msg_finalize;
+
+	signals[ACTIVITY_CREATED] =
+		g_signal_new ("activity-created",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      0, /* struct offset */
+			      NULL, NULL, /* accumulator */
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1,
+			      E_TYPE_ACTIVITY);
+
+	signals[ERROR_RESPONSE] =
+		g_signal_new ("error-response",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      0, /* struct offset */
+			      NULL, NULL, /* accumulator */
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1,
+			      E_TYPE_ALERT);
+
+	g_object_class_install_property (object_class,
+					 PROP_ID,
+					 g_param_spec_uint ("id", "id",
+							    "id of the msg",
+							    0, G_MAXUINT, 0,
+							    G_PARAM_READABLE |
+							    G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (object_class,
+					 PROP_ACTIVITY,
+					 g_param_spec_object ("activity", "activity",
+							      "An optional EActivity associated with the msg",
+							      E_TYPE_ACTIVITY,
+							      G_PARAM_READABLE |
+							      G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (object_class,
+					 PROP_ACTIVITY,
+					 g_param_spec_object ("alert", "alert",
+							      "An EAlert associated with the msg",
+							      E_TYPE_ALERT,
+							      G_PARAM_READABLE |
+							      G_PARAM_STATIC_STRINGS));
+
+}
+
+static void
+e_mail_msg_init (EMailMsg *self)
+{
+	self->priv = MAIL_MSG_PRIVATE (self);
+
+	e_mail_task_manager_add_task (e_mail_task_manager_get_default (),
+				      self);
+}
+
+EMailMsg*
+e_mail_msg_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_MSG, NULL);
+}
+
+gchar*
+e_mail_msg_desc (EMailMsg *msg)
+{
+	EMailMsgClass *klass = E_MAIL_MSG_GET_CLASS (msg);
+
+	if (klass->desc)
+		return klass->desc (msg);
+
+	return NULL;
+}
+
+void
+e_mail_msg_exec (EMailMsg *msg)
+{
+	EMailMsgClass *klass = E_MAIL_MSG_GET_CLASS (msg);
+
+	if (klass->exec)
+		klass->exec (msg);
+}
+
+void
+e_mail_msg_done(EMailMsg *msg)
+{
+	EMailMsgClass *klass = E_MAIL_MSG_GET_CLASS (msg);
+
+	if (klass->done)
+		klass->done (msg);
+}
+
+gint
+e_mail_msg_get_priority (const EMailMsg *msg)
+{
+	return msg->priv->priority;
+}
+
+void
+e_mail_msg_set_cancellable (EMailMsg *msg, gboolean status)
+{
+	msg->priv->cancellable = status;
+}
+
+gboolean
+e_mail_msg_get_cancellable (EMailMsg *msg)
+{
+	return msg->priv->cancellable;
+}
+
+guint e_mail_msg_get_id (const EMailMsg *msg)
+{
+	return msg->priv->seq;
+}
+
+CamelOperation *
+e_mail_msg_get_operation (EMailMsg *msg)
+{
+	return msg->priv->cancel;
+}
+
+void
+e_mail_msg_set_operation (EMailMsg *msg, CamelOperation *op)
+{
+	if (msg->priv->cancel)
+		camel_operation_unref (msg->priv->cancel);
+
+	msg->priv->cancel = op;
+	if (op)
+		camel_operation_ref (op);
+	else
+		e_mail_msg_set_cancellable (msg, FALSE);
+}
+
+CamelException *
+e_mail_msg_get_exception (EMailMsg *msg)
+{
+	return &msg->priv->ex;
+}
+
+gboolean
+e_mail_msg_exception_is_set (const EMailMsg *msg)
+{
+	return camel_exception_is_set (&msg->priv->ex);
+}
+
diff --git a/mail/e-mail-msg.h b/mail/e-mail-msg.h
new file mode 100644
index 0000000..6b7ab98
--- /dev/null
+++ b/mail/e-mail-msg.h
@@ -0,0 +1,96 @@
+/*
+ * e-mail-msg.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
+ *
+ * Copyright (C) 2009 Intel Coporation
+ *
+ */
+
+#ifndef _E_MAIL_MSG_H
+#define _E_MAIL_MSG_H
+
+#include <glib-object.h>
+#include <camel/camel-operation.h>
+#include <camel/camel-exception.h>
+#include "e-util/e-alert.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_MAIL_MSG e_mail_msg_get_type()
+#define E_MAIL_MSG(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	 ((obj), E_TYPE_MAIL_MSG, EMailMsg))
+#define E_MAIL_MSG_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	 ((klass), E_TYPE_MAIL_MSG, EMailMsgClass))
+#define E_IS_MAIL_MSG(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	 ((obj), E_TYPE_MAIL_MSG))
+#define E_IS_MAIL_MSG_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	 ((klass), E_TYPE_MAIL_MSG))
+#define E_MAIL_MSG_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	 ((obj), E_TYPE_MAIL_MSG, EMailMsgClass))
+
+typedef struct _EMailMsg EMailMsg;
+typedef struct _EMailMsgClass EMailMsgClass;
+typedef struct _EMailMsgPrivate EMailMsgPrivate;
+
+typedef gchar *	(*MailMsgDescFunc)	(EMailMsg *msg);
+typedef void	(*MailMsgExecFunc)	(EMailMsg *msg);
+typedef void	(*MailMsgDoneFunc)	(EMailMsg *msg);
+
+struct _EMailMsg
+{
+	GObject parent;
+	EMailMsgPrivate *priv;
+};
+
+struct _EMailMsgClass
+{
+	GObjectClass parent_class;
+
+	MailMsgDescFunc desc;
+	MailMsgExecFunc exec;
+	MailMsgDoneFunc done;
+};
+
+GType e_mail_msg_get_type (void);
+
+EMailMsg* e_mail_msg_new (void);
+
+void e_mail_msg_finish (EMailMsg *msg);
+void e_mail_msg_cancel (EMailMsg *msg);
+
+gchar* e_mail_msg_desc (EMailMsg *msg);
+void e_mail_msg_exec (EMailMsg *msg);
+void e_mail_msg_done(EMailMsg *msg);
+gint e_mail_msg_get_priority (const EMailMsg *msg);
+void e_mail_msg_set_cancellable (EMailMsg *msg, gboolean status);
+gboolean e_mail_msg_get_cancellable (EMailMsg *msg);
+guint e_mail_msg_get_id (const EMailMsg *msg);
+
+CamelOperation *e_mail_msg_get_operation (EMailMsg *msg);
+void e_mail_msg_set_operation (EMailMsg *msg, CamelOperation *op);
+CamelException *e_mail_msg_get_exception (EMailMsg *msg);
+gboolean e_mail_msg_exception_is_set (const EMailMsg *msg);
+
+G_END_DECLS
+
+#endif /* _E_MAIL_MSG_H */
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 8249187..cf86d32 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -32,15 +32,23 @@
 #include "e-util/e-alert-dialog.h"
 #include "filter/e-filter-rule.h"
 
-#include "mail/e-mail-browser.h"
-#include "mail/em-composer-utils.h"
-#include "mail/em-format-html-print.h"
-#include "mail/em-utils.h"
-#include "mail/mail-autofilter.h"
-#include "mail/mail-ops.h"
-#include "mail/mail-tools.h"
-#include "mail/mail-vfolder.h"
-#include "mail/message-list.h"
+#include "e-mail-browser.h"
+#include "e-mail-task-manager.h"
+#include "em-composer-utils.h"
+#include "em-format-html-print.h"
+#include "em-utils.h"
+#include "mail-autofilter.h"
+#include "mail-ops.h"
+#include "mail-tools.h"
+#include "mail-vfolder.h"
+#include "message-list.h"
+
+static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
 
 void
 e_mail_reader_activate (EMailReader *reader,
@@ -500,7 +508,7 @@ e_mail_reader_create_filter_from_selected (EMailReader *reader,
 		mail_get_message (
 			folder, uids->pdata[0],
 			mail_reader_create_filter_cb,
-			filter_data, mail_msg_unordered_push);
+			filter_data, default_unordered_push);
 	}
 
 	em_utils_uids_free (uids);
@@ -553,7 +561,7 @@ e_mail_reader_create_vfolder_from_selected (EMailReader *reader,
 		mail_get_message (
 			folder, uids->pdata[0],
 			mail_reader_create_vfolder_cb,
-			vfolder_data, mail_msg_unordered_push);
+			vfolder_data, default_unordered_push);
 	}
 
 	em_utils_uids_free (uids);
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 74b4f1a..fc94e27 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -20,6 +20,7 @@
  */
 
 #include "e-mail-reader.h"
+#include "e-mail-task-manager.h"
 
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
@@ -64,6 +65,13 @@ static gchar *default_xfer_messages_uri;
 static guint signals[LAST_SIGNAL];
 
 static void
+default_fast_ordered_push (EMailMsg* msg)
+{
+	e_mail_task_manager_fast_ordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
+static void
 action_mail_add_sender_cb (GtkAction *action,
                            EMailReader *reader)
 {
@@ -1867,7 +1875,7 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
 				folder, cursor_uid,
 				mail_reader_message_loaded_cb,
 				g_object_ref (reader),
-				mail_msg_fast_ordered_push);
+				default_fast_ordered_push);
 
 			g_object_set_data (
 				G_OBJECT (reader),
@@ -1896,7 +1904,8 @@ mail_reader_message_selected_cb (EMailReader *reader,
 	key = "preview-get-message-op-id";
 	data = g_object_get_data (G_OBJECT (reader), key);
 	if (data != NULL)
-		mail_msg_cancel (GPOINTER_TO_INT (data));
+		e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+						 GPOINTER_TO_INT (data));
 
 	/* then cancel the seen timer */
 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
@@ -2971,7 +2980,7 @@ e_mail_reader_set_folder_uri (EMailReader *reader,
 	/* Fetch the CamelFolder asynchronously. */
 	mail_get_folder (
 		folder_uri, 0, mail_reader_got_folder_cb,
-		reader, mail_msg_fast_ordered_push);
+		reader, default_fast_ordered_push);
 }
 
 void
diff --git a/mail/e-mail-task-manager.c b/mail/e-mail-task-manager.c
new file mode 100644
index 0000000..bfa33a0
--- /dev/null
+++ b/mail/e-mail-task-manager.c
@@ -0,0 +1,449 @@
+/*
+ * e-mail-task-manager.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
+ *
+ * Copyright (C) 2009 Intel Coporation
+ *
+ */
+
+#include "e-util/e-util.h"
+#include "e-util/e-marshal.h"
+#include "e-mail-task-manager.h"
+
+G_DEFINE_TYPE (EMailTaskManager, e_mail_task_manager, G_TYPE_OBJECT)
+
+#define MAIL_TASK_MANAGER_PRIVATE(o) \
+		(G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_MAIL_TASK_MANAGER, EMailTaskManagerPrivate))
+
+struct _EMailTaskManagerPrivate
+{
+	GHashTable *active_tasks; /* table of active messages, must hold mutex to access */
+	GCond *task_cond;
+	guint idle_source_id;
+	GAsyncQueue *main_loop_queue;
+	GAsyncQueue *msg_reply_queue;
+	GMutex *mutex;
+};
+
+enum {
+	TASK_ADDED,
+	LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL];
+
+static void
+e_mail_task_manager_get_property (GObject *object, guint property_id,
+				  GValue *value, GParamSpec *pspec)
+{
+	switch (property_id)
+	{
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+	}
+}
+
+static void
+e_mail_task_manager_set_property (GObject *object, guint property_id,
+				  const GValue *value, GParamSpec *pspec)
+{
+	switch (property_id)
+	{
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+	}
+}
+
+static void
+e_mail_task_manager_dispose (GObject *object)
+{
+	G_OBJECT_CLASS (e_mail_task_manager_parent_class)->dispose (object);
+}
+
+static void
+lock (EMailTaskManager *self)
+{
+	g_mutex_lock (self->priv->mutex);
+}
+
+static void
+unlock (EMailTaskManager *self)
+{
+	g_mutex_unlock (self->priv->mutex);
+}
+
+static void
+e_mail_task_manager_finalize (GObject *object)
+{
+	EMailTaskManager *self = (EMailTaskManager*) object;
+
+	g_hash_table_destroy (self->priv->active_tasks);
+	g_cond_free (self->priv->task_cond);
+	g_async_queue_unref (self->priv->main_loop_queue);
+	g_async_queue_unref (self->priv->msg_reply_queue);
+
+	lock (self);
+	if (self->priv->idle_source_id != 0) {
+		GSource *source;
+
+		/* Cancel the idle source. */
+		source = g_main_context_find_source_by_id (
+			g_main_context_default (), self->priv->idle_source_id);
+		g_source_destroy (source);
+		self->priv->idle_source_id = 0;
+	}
+	unlock (self);
+
+	g_mutex_free (self->priv->mutex);
+	G_OBJECT_CLASS (e_mail_task_manager_parent_class)->finalize (object);
+}
+
+static void
+e_mail_task_manager_class_init (EMailTaskManagerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (EMailTaskManagerPrivate));
+
+	object_class->get_property = e_mail_task_manager_get_property;
+	object_class->set_property = e_mail_task_manager_set_property;
+	object_class->dispose = e_mail_task_manager_dispose;
+	object_class->finalize = e_mail_task_manager_finalize;
+
+	signals[TASK_ADDED] =
+		g_signal_new ("task-added",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      0, /* struct offset */
+			      NULL, NULL, /* accumulator */
+			      e_marshal_VOID__OBJECT_UINT,
+			      G_TYPE_NONE, 2,
+			      E_TYPE_MAIL_MSG, G_TYPE_UINT);
+}
+
+static void
+e_mail_task_manager_init (EMailTaskManager *self)
+{
+	self->priv = MAIL_TASK_MANAGER_PRIVATE (self);
+	self->priv->active_tasks = g_hash_table_new (NULL, NULL);
+	self->priv->task_cond = g_cond_new ();
+	self->priv->main_loop_queue = g_async_queue_new ();
+	self->priv->msg_reply_queue = g_async_queue_new ();
+	self->priv->mutex = g_mutex_new ();
+}
+
+EMailTaskManager*
+e_mail_task_manager_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_TASK_MANAGER, NULL);
+}
+
+G_LOCK_DEFINE_STATIC (task_manager);
+EMailTaskManager*
+e_mail_task_manager_get_default (void)
+{
+	static EMailTaskManager *_default = NULL;
+
+	G_LOCK (task_manager);
+	if (!_default)
+		_default =  g_object_new (E_TYPE_MAIL_TASK_MANAGER, NULL);
+	G_UNLOCK (task_manager);
+
+	return _default;
+}
+
+typedef struct
+{
+	EMailTaskManager *task_mgr;
+	guint id;
+} RemoveTaskData;
+
+static void
+remove_task (gpointer data, GObject *msg)
+{
+	RemoveTaskData *rtd = (RemoveTaskData*) data;
+	lock (rtd->task_mgr);
+	g_hash_table_remove (rtd->task_mgr->priv->active_tasks,
+			     GINT_TO_POINTER (rtd->id));
+	g_cond_broadcast (rtd->task_mgr->priv->task_cond);
+	unlock (rtd->task_mgr);
+
+	g_slice_free (RemoveTaskData, rtd);
+}
+
+void
+e_mail_task_manager_add_task (EMailTaskManager *self, EMailMsg *msg)
+{
+	RemoveTaskData *data = g_slice_new (RemoveTaskData);
+	data->task_mgr = self;
+	data->id = e_mail_msg_get_id (msg);
+	g_object_weak_ref ((GObject*) msg, remove_task, data);
+	lock (self);
+	g_hash_table_insert(self->priv->active_tasks, GINT_TO_POINTER(data->id), msg);
+	unlock (self);
+	g_signal_emit (self, signals[TASK_ADDED], 0, msg, data->id);
+}
+
+static EMailMsg*
+e_mail_task_manager_lookup_task_unlocked (EMailTaskManager *self, gint id)
+{
+	return g_hash_table_lookup(self->priv->active_tasks, GINT_TO_POINTER(id));
+}
+EMailMsg*
+e_mail_task_manager_lookup_task (EMailTaskManager *self, gint id)
+{
+	EMailMsg *task;
+
+	lock (self);
+	task = e_mail_task_manager_lookup_task_unlocked (self, id);
+	unlock (self);
+
+	return task;
+}
+
+void
+e_mail_task_manager_cancel_task (EMailTaskManager *self, guint id)
+{
+	EMailMsg *task = e_mail_task_manager_lookup_task (self, id);
+	if (task)
+		e_mail_msg_cancel (task);
+}
+
+gint
+e_mail_task_manager_num_tasks (EMailTaskManager *self)
+{
+	gint num_tasks;
+	lock (self);
+	num_tasks = g_hash_table_size(self->priv->active_tasks) > 0;
+	unlock (self);
+	return num_tasks;
+}
+
+static GHookList cancel_hook_list;
+
+GHook *
+e_mail_task_manager_cancel_hook_add (GHookFunc func, gpointer data)
+{
+	GHook *hook;
+
+	G_LOCK (task_manager);
+
+	if (!cancel_hook_list.is_setup)
+		g_hook_list_init (&cancel_hook_list, sizeof (GHook));
+
+	hook = g_hook_alloc (&cancel_hook_list);
+	hook->func = func;
+	hook->data = data;
+
+	g_hook_append (&cancel_hook_list, hook);
+
+	G_UNLOCK (task_manager);
+
+	return hook;
+}
+
+void
+e_mail_task_manager_cancel_hook_remove (GHook *hook)
+{
+	G_LOCK (task_manager);
+
+	g_return_if_fail (cancel_hook_list.is_setup);
+	g_hook_destroy_link (&cancel_hook_list, hook);
+
+	G_UNLOCK (task_manager);
+}
+
+void
+e_mail_task_manager_cancel_all ()
+{
+	camel_operation_cancel (NULL);
+
+	G_LOCK (task_manager);
+
+	if (cancel_hook_list.is_setup)
+		g_hook_list_invoke (&cancel_hook_list, FALSE);
+
+	G_UNLOCK (task_manager);
+}
+
+void
+e_mail_task_manager_task_wait(EMailTaskManager *self, guint msgid)
+{
+	EMailMsg *m;
+
+	if (e_in_main_thread ()) {
+		while ((m = e_mail_task_manager_lookup_task(self, msgid))) {
+			gtk_main_iteration();
+		}
+	} else {
+		lock (self);
+		while ((m = e_mail_task_manager_lookup_task_unlocked (self, msgid))) {
+			g_cond_wait (self->priv->task_cond, self->priv->mutex);
+		}
+		unlock (self);
+	}
+}
+
+void
+e_mail_task_manager_task_wait_all(EMailTaskManager *self)
+{
+	if (e_in_main_thread ()) {
+		while (e_mail_task_manager_num_tasks (self) > 0) {
+			gtk_main_iteration();
+		}
+	} else {
+		lock (self);
+		while (g_hash_table_size(self->priv->active_tasks) > 0) {
+			g_cond_wait (self->priv->task_cond, self->priv->mutex);
+		}
+		unlock (self);
+	}
+}
+
+static gboolean
+mail_msg_idle_cb (EMailTaskManager *self)
+{
+	EMailMsg *msg;
+
+	g_return_val_if_fail (self->priv->main_loop_queue != NULL, FALSE);
+	g_return_val_if_fail (self->priv->msg_reply_queue != NULL, FALSE);
+
+	lock (self);
+	self->priv->idle_source_id = 0;
+	unlock (self);
+	/* check the main loop queue */
+	while ((msg = g_async_queue_try_pop (self->priv->main_loop_queue)) != NULL) {
+		e_mail_msg_exec (msg);
+		e_mail_msg_done (msg);
+		g_object_unref (msg);
+	}
+
+	/* check the reply queue */
+	while ((msg = g_async_queue_try_pop (self->priv->msg_reply_queue)) != NULL) {
+		e_mail_msg_done (msg);
+		e_mail_msg_finish (msg);
+		g_object_unref (msg);
+	}
+	return FALSE;
+}
+
+static void
+mail_msg_proxy (EMailMsg *msg, EMailTaskManager *self)
+{
+	EMailMsgClass *klass = E_MAIL_MSG_GET_CLASS (msg);
+	CamelOperation *cancel = e_mail_msg_get_operation (msg);
+	if (klass->desc != NULL && cancel) {
+		gchar *text = klass->desc (msg);
+		camel_operation_register (cancel);
+		camel_operation_start (cancel, "%s", text);
+		g_free (text);
+	}
+
+	e_mail_msg_exec (msg);
+
+	if (klass->desc != NULL && cancel) {
+		camel_operation_end (cancel);
+		camel_operation_unregister (cancel);
+	}
+
+	g_async_queue_push (self->priv->msg_reply_queue, msg);
+
+	lock (self);
+	if (self->priv->idle_source_id == 0)
+		self->priv->idle_source_id =
+			g_idle_add ((GSourceFunc) mail_msg_idle_cb, self);
+	unlock (self);
+}
+
+typedef struct
+{
+	EMailTaskManager *task_mgr;
+	int max_threads;
+} CreateThreadpoolData;
+
+static gint
+mail_msg_compare (const EMailMsg *msg1, const EMailMsg *msg2)
+{
+	gint priority1 = e_mail_msg_get_priority (msg1);
+	gint priority2 = e_mail_msg_get_priority (msg2);
+
+	if (priority1 == priority2)
+		return 0;
+
+	return (priority1 < priority2) ? 1 : -1;
+}
+
+static gpointer
+create_thread_pool (CreateThreadpoolData *data)
+{
+	GThreadPool *thread_pool;
+
+	/* once created, run forever */
+	thread_pool = g_thread_pool_new (
+		(GFunc) mail_msg_proxy, data->task_mgr, data->max_threads, FALSE, NULL);
+	g_thread_pool_set_sort_function (
+		thread_pool, (GCompareDataFunc) mail_msg_compare, NULL);
+
+	return thread_pool;
+}
+
+void
+e_mail_task_manager_main_loop_push (EMailTaskManager *self, EMailMsg *msg)
+{
+	g_async_queue_push_sorted (self->priv->main_loop_queue, msg,
+				   (GCompareDataFunc) mail_msg_compare, NULL);
+
+	lock (self);
+	if (self->priv->idle_source_id == 0)
+		self->priv->idle_source_id =
+			g_idle_add ((GSourceFunc) mail_msg_idle_cb, self);
+	unlock (self);
+}
+
+void
+e_mail_task_manager_unordered_push (EMailTaskManager *self, EMailMsg* msg)
+{
+	static GOnce once = G_ONCE_INIT;
+
+	CreateThreadpoolData data = {self, 10};
+	g_once (&once, (GThreadFunc) create_thread_pool, &data);
+
+	g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
+}
+
+void
+e_mail_task_manager_fast_ordered_push (EMailTaskManager *self, EMailMsg* msg)
+{
+	static GOnce once = G_ONCE_INIT;
+
+	CreateThreadpoolData data = {self, 1};
+	g_once (&once, (GThreadFunc) create_thread_pool, &data);
+
+	g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
+}
+
+void
+e_mail_task_manager_slow_ordered_push (EMailTaskManager *self, EMailMsg* msg)
+{
+	static GOnce once = G_ONCE_INIT;
+
+	CreateThreadpoolData data = {self, 1};
+	g_once (&once, (GThreadFunc) create_thread_pool, &data);
+
+	g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
+}
+
diff --git a/mail/e-mail-task-manager.h b/mail/e-mail-task-manager.h
new file mode 100644
index 0000000..bf1cd03
--- /dev/null
+++ b/mail/e-mail-task-manager.h
@@ -0,0 +1,93 @@
+/*
+ * e-mail-task-manager.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
+ *
+ * Copyright (C) 2009 Intel Coporation
+ *
+ */
+
+#ifndef _E_MAIL_TASK_MANAGER_H
+#define _E_MAIL_TASK_MANAGER_H
+
+#include <glib-object.h>
+#include "e-mail-msg.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_MAIL_TASK_MANAGER e_mail_task_manager_get_type()
+
+#define E_MAIL_TASK_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  E_TYPE_MAIL_TASK_MANAGER, EMailTaskManager))
+
+#define E_MAIL_TASK_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  E_TYPE_MAIL_TASK_MANAGER, EMailTaskManagerClass))
+
+#define E_IS_MAIL_TASK_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  E_TYPE_MAIL_TASK_MANAGER))
+
+#define E_IS_MAIL_TASK_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  E_TYPE_MAIL_TASK_MANAGER))
+
+#define E_MAIL_TASK_MANAGER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  E_TYPE_MAIL_TASK_MANAGER, EMailTaskManagerClass))
+
+typedef struct _EMailTaskManager EMailTaskManager;
+typedef struct _EMailTaskManagerClass EMailTaskManagerClass;
+typedef struct _EMailTaskManagerPrivate EMailTaskManagerPrivate;
+
+struct _EMailTaskManager
+{
+  GObject parent;
+  EMailTaskManagerPrivate *priv;
+};
+
+struct _EMailTaskManagerClass
+{
+  GObjectClass parent_class;
+};
+
+GType e_mail_task_manager_get_type (void);
+
+EMailTaskManager* e_mail_task_manager_new (void);
+EMailTaskManager* e_mail_task_manager_get_default (void);
+
+void e_mail_task_manager_add_task (EMailTaskManager *self, EMailMsg *msg);
+EMailMsg* e_mail_task_manager_lookup_task (EMailTaskManager *self, gint id);
+
+void e_mail_task_manager_cancel_task (EMailTaskManager *self, guint id);
+gint e_mail_task_manager_num_tasks (EMailTaskManager *self);
+void e_mail_task_manager_task_wait(EMailTaskManager *self, guint msgid);
+void e_mail_task_manager_task_wait_all(EMailTaskManager *self);
+
+void e_mail_task_manager_main_loop_push (EMailTaskManager *self, EMailMsg *msg);
+void e_mail_task_manager_unordered_push (EMailTaskManager *self, EMailMsg *msg);
+void e_mail_task_manager_fast_ordered_push (EMailTaskManager *self, EMailMsg *msg);
+void e_mail_task_manager_slow_ordered_push (EMailTaskManager *self, EMailMsg *msg);
+
+GHook* e_mail_task_manager_cancel_hook_add (GHookFunc func, gpointer data);
+void e_mail_task_manager_cancel_hook_remove (GHook *hook);
+void e_mail_task_manager_cancel_all ();
+
+G_END_DECLS
+
+#endif /* _E_MAIL_TASK_MANAGER_H */
diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c
index e3e9613..6bd012e 100644
--- a/mail/em-account-editor.c
+++ b/mail/em-account-editor.c
@@ -57,15 +57,16 @@
 
 #include "e-mail-local.h"
 #include "e-mail-store.h"
+#include "e-mail-task-manager.h"
+#include "em-account-editor.h"
 #include "em-config.h"
 #include "em-folder-selection-button.h"
-#include "em-account-editor.h"
-#include "mail-session.h"
-#include "mail-send-recv.h"
 #include "em-utils.h"
 #include "mail-config.h"
-#include "mail-ops.h"
 #include "mail-mt.h"
+#include "mail-ops.h"
+#include "mail-send-recv.h"
+#include "mail-session.h"
 
 #if defined (HAVE_NSS)
 #include "smime/gui/e-cert-selector.h"
@@ -1883,7 +1884,8 @@ static void emae_check_authtype_done (const gchar *uri, CamelProviderType type,
 
 static void emae_check_authtype_response (GtkWidget *d, gint button, EMAccountEditorService *service)
 {
-	mail_msg_cancel (service->check_id);
+	e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+					 service->check_id);
 	gtk_widget_destroy (service->check_dialog);
 	service->check_dialog = NULL;
 
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 1e2ceb0..e404aae 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -32,12 +32,13 @@
 #include <libedataserver/e-data-server-util.h>
 #include <glib/gi18n.h>
 
-#include "mail-mt.h"
-#include "mail-ops.h"
-#include "mail-tools.h"
-#include "mail-config.h"
-#include "mail-session.h"
-#include "mail-send-recv.h"
+#include <camel/camel-folder.h>
+#include <camel/camel-multipart.h>
+#include <camel/camel-string-utils.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-nntp-address.h>
+#include <camel/camel-vee-folder.h>
+
 
 #include "e-util/e-account-utils.h"
 #include "e-util/e-alert-dialog.h"
@@ -45,26 +46,27 @@
 
 #include "shell/e-shell.h"
 
-#include "e-mail-local.h"
-#include "em-utils.h"
-#include "em-composer-utils.h"
 #include "composer/e-msg-composer.h"
 #include "composer/e-composer-actions.h"
 #include "composer/e-composer-autosave.h"
 #include "composer/e-composer-post-header.h"
+
+#include "e-mail-local.h"
+#include "e-mail-task-manager.h"
+#include "em-composer-utils.h"
+#include "em-event.h"
 #include "em-folder-selector.h"
 #include "em-folder-tree.h"
-#include "em-format-html.h"
 #include "em-format-html-print.h"
+#include "em-format-html.h"
 #include "em-format-quote.h"
-#include "em-event.h"
-
-#include <camel/camel-folder.h>
-#include <camel/camel-multipart.h>
-#include <camel/camel-string-utils.h>
-#include <camel/camel-stream-mem.h>
-#include <camel/camel-nntp-address.h>
-#include <camel/camel-vee-folder.h>
+#include "em-utils.h"
+#include "mail-config.h"
+#include "mail-mt.h"
+#include "mail-ops.h"
+#include "mail-send-recv.h"
+#include "mail-session.h"
+#include "mail-tools.h"
 
 #ifdef G_OS_WIN32
 /* Undef the similar macro from pthread.h, it doesn't check if
@@ -78,6 +80,13 @@
 
 #define GCONF_KEY_TEMPLATE_PLACEHOLDERS "/apps/evolution/mail/template_placeholders"
 
+static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
 static void em_utils_composer_send_cb (EMsgComposer *composer);
 static void em_utils_composer_save_draft_cb (EMsgComposer *composer);
 
@@ -651,8 +660,8 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer)
 	EAccount *account;
 
 	/* need to get stuff from the composer here, since it could
-	 * get destroyed while we're in mail_msg_wait() a little lower
-	 * down, waiting for the folder to open */
+	 * get destroyed while we're in e_mail_task_manager_task_wait() a little
+	 * lower down, waiting for the folder to open */
 
 	local_drafts_folder =
 		e_mail_local_get_folder (E_MAIL_FOLDER_DRAFTS);
@@ -674,8 +683,9 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer)
 	    strcmp (account->drafts_folder_uri, local_drafts_folder_uri) != 0) {
 		gint id;
 
-		id = mail_get_folder (account->drafts_folder_uri, 0, save_draft_folder, &folder, mail_msg_unordered_push);
-		mail_msg_wait (id);
+		id = mail_get_folder (account->drafts_folder_uri, 0, save_draft_folder, &folder, default_unordered_push);
+		e_mail_task_manager_task_wait
+			(e_mail_task_manager_get_default (), id);
 
 		if (!folder || !account->enabled) {
 			if (e_alert_run_dialog_for_args ((GtkWindow *)composer, "mail:ask-default-drafts", NULL) != GTK_RESPONSE_YES) {
@@ -1448,7 +1458,7 @@ em_utils_redirect_message_by_uid (CamelFolder *folder, const gchar *uid)
 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
 	g_return_if_fail (uid != NULL);
 
-	mail_get_message (folder, uid, redirect_msg, NULL, mail_msg_unordered_push);
+	mail_get_message (folder, uid, redirect_msg, NULL, default_unordered_push);
 }
 
 static void
@@ -1479,7 +1489,7 @@ em_utils_handle_receipt (CamelFolder *folder, const gchar *uid, CamelMimeMessage
 	}
 
 	if (msg == NULL) {
-		mail_get_messagex(folder, uid, emu_handle_receipt_message, NULL, mail_msg_unordered_push);
+		mail_get_messagex(folder, uid, emu_handle_receipt_message, NULL, default_unordered_push);
 		camel_message_info_free(info);
 		return;
 	}
@@ -2244,7 +2254,7 @@ em_utils_reply_to_message(CamelFolder *folder, const gchar *uid, CamelMimeMessag
 		rd->source = source;
 		if (rd->source)
 			g_object_ref(rd->source);
-		mail_get_message(folder, uid, reply_to_message, rd, mail_msg_unordered_push);
+		mail_get_message(folder, uid, reply_to_message, rd, default_unordered_push);
 
 		return NULL;
 	}
diff --git a/mail/em-folder-properties.c b/mail/em-folder-properties.c
index 7b79571..b745df2 100644
--- a/mail/em-folder-properties.c
+++ b/mail/em-folder-properties.c
@@ -40,11 +40,19 @@
 #include "em-config.h"
 
 #include "e-mail-local.h"
+#include "e-mail-task-manager.h"
 #include "mail-ops.h"
 #include "mail-mt.h"
 #include "mail-vfolder.h"
 #include "mail-config.h"
 
+static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
 struct _prop_data {
 	gpointer object;
 	CamelArgV *argv;
@@ -439,7 +447,7 @@ emfp_dialog_got_folder (gchar *uri, CamelFolder *folder, gpointer data)
 	/* this should be called in a thread too */
 	mail_get_folder_quota (
 		folder, uri, emfp_dialog_got_folder_quota,
-		shell_view, mail_msg_unordered_push);
+		shell_view, default_unordered_push);
 }
 
 /**
@@ -477,7 +485,7 @@ em_folder_properties_show (EShellView *shell_view,
 	}
 
 	if (folder == NULL)
-		mail_get_folder(uri, 0, emfp_dialog_got_folder, shell_view, mail_msg_unordered_push);
+		mail_get_folder(uri, 0, emfp_dialog_got_folder, shell_view, default_unordered_push);
 	else
 		emfp_dialog_got_folder((gchar *)uri, folder, shell_view);
 }
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index c439961..0c0e555 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -14,9 +14,11 @@
  *
  *
  * Authors:
- *		Jeffrey Stedfast <fejj ximian com>
+ *   Jeffrey Stedfast <fejj ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -54,24 +56,22 @@
 #include "e-util/e-alert-dialog.h"
 #include "e-util/e-util.h"
 
+#include "e-mail-local.h"
+#include "e-mail-task-manager.h"
+#include "em-event.h"
+#include "em-folder-properties.h"
+#include "em-folder-selector.h"
+#include "em-folder-tree.h"
+#include "em-folder-utils.h"
+#include "em-utils.h"
 #include "em-vfolder-rule.h"
-
+#include "mail-config.h"
 #include "mail-mt.h"
 #include "mail-ops.h"
-#include "mail-tools.h"
-#include "mail-config.h"
 #include "mail-send-recv.h"
+#include "mail-tools.h"
 #include "mail-vfolder.h"
 
-#include "em-utils.h"
-#include "em-folder-tree.h"
-#include "em-folder-utils.h"
-#include "em-folder-selector.h"
-#include "em-folder-properties.h"
-#include "em-event.h"
-
-#include "e-mail-local.h"
-
 #define d(x)
 
 #define EM_FOLDER_TREE_GET_PRIVATE(obj) \
@@ -165,8 +165,9 @@ struct _folder_tree_selection_data {
 
 static gpointer parent_class = NULL;
 
+typedef struct _EMFolderTreeGetFolderInfo EMFolderTreeGetFolderInfo;
 struct _EMFolderTreeGetFolderInfo {
-	MailMsg base;
+	EMailMsg base;
 
 	/* input data */
 	GtkTreeRowReference *root;
@@ -178,9 +179,15 @@ struct _EMFolderTreeGetFolderInfo {
 	/* output data */
 	CamelFolderInfo *fi;
 };
+typedef struct _EMFolderTreeGetFolderInfoClass EMFolderTreeGetFolderInfoClass;
+struct _EMFolderTreeGetFolderInfoClass {
+	EMailMsgClass parent_class;
+};
+GType em_folder_tree_get_folder_info_get_type (void);
+G_DEFINE_TYPE (EMFolderTreeGetFolderInfo, em_folder_tree_get_folder_info, E_TYPE_MAIL_MSG)
 
 static gchar *
-folder_tree_get_folder_info__desc (struct _EMFolderTreeGetFolderInfo *m)
+folder_tree_get_folder_info__desc (EMFolderTreeGetFolderInfo *m)
 {
 	gchar *ret, *name;
 
@@ -191,15 +198,16 @@ folder_tree_get_folder_info__desc (struct _EMFolderTreeGetFolderInfo *m)
 }
 
 static void
-folder_tree_get_folder_info__exec (struct _EMFolderTreeGetFolderInfo *m)
+folder_tree_get_folder_info__exec (EMFolderTreeGetFolderInfo *m)
 {
 	guint32 flags = m->flags | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
 
-	m->fi = camel_store_get_folder_info (m->store, m->top, flags, &m->base.ex);
+	m->fi = camel_store_get_folder_info (m->store, m->top, flags,
+					     e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-folder_tree_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m)
+folder_tree_get_folder_info__done (EMFolderTreeGetFolderInfo *m)
 {
 	struct _EMFolderTreeModelStoreInfo *si;
 	GtkTreeIter root, iter, titer;
@@ -230,7 +238,7 @@ folder_tree_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m)
 	gtk_tree_model_get_iter (model, &root, path);
 
 	/* if we had an error, then we need to re-set the load subdirs state and collapse the node */
-	if (!m->fi && camel_exception_is_set(&m->base.ex)) {
+	if (!m->fi && e_mail_msg_exception_is_set((EMailMsg*) m)) {
 		gtk_tree_store_set(
 			GTK_TREE_STORE (model), &root,
 			COL_BOOL_LOAD_SUBDIRS, TRUE, -1);
@@ -305,23 +313,44 @@ folder_tree_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m)
 }
 
 static void
-folder_tree_get_folder_info__free (struct _EMFolderTreeGetFolderInfo *m)
+folder_tree_get_folder_info__free (GObject *object)
 {
-	camel_store_free_folder_info (m->store, m->fi);
+	EMFolderTreeGetFolderInfo *m = (EMFolderTreeGetFolderInfo*) object;
 
 	gtk_tree_row_reference_free (m->root);
-	g_object_unref(m->folder_tree);
-	camel_object_unref (m->store);
+	m->root = NULL;
+
+	if (m->folder_tree) {
+		g_object_unref(m->folder_tree);
+		m->folder_tree = NULL;
+	}
+
+	if (m->store) {
+		camel_store_free_folder_info (m->store, m->fi);
+		camel_object_unref (m->store);
+		m->store = NULL;
+		m->fi = NULL;
+	}
+
 	g_free (m->top);
+	m->top = NULL;
 }
 
-static MailMsgInfo get_folder_info_info = {
-	sizeof (struct _EMFolderTreeGetFolderInfo),
-	(MailMsgDescFunc) folder_tree_get_folder_info__desc,
-	(MailMsgExecFunc) folder_tree_get_folder_info__exec,
-	(MailMsgDoneFunc) folder_tree_get_folder_info__done,
-	(MailMsgFreeFunc) folder_tree_get_folder_info__free
-};
+static void
+em_folder_tree_get_folder_info_class_init (EMFolderTreeGetFolderInfoClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = folder_tree_get_folder_info__free;
+	klass->parent_class.desc = (MailMsgDescFunc) folder_tree_get_folder_info__desc;
+	klass->parent_class.exec = (MailMsgExecFunc) folder_tree_get_folder_info__exec;
+	klass->parent_class.done = (MailMsgDoneFunc) folder_tree_get_folder_info__done;
+}
+
+static void
+em_folder_tree_get_folder_info_init (EMFolderTreeGetFolderInfo *msg)
+{
+}
 
 static void
 folder_tree_emit_popup_event (EMFolderTree *folder_tree,
@@ -895,7 +924,7 @@ folder_tree_row_expanded (GtkTreeView *tree_view,
                           GtkTreeIter *iter,
                           GtkTreePath *path)
 {
-	struct _EMFolderTreeGetFolderInfo *msg;
+	EMFolderTreeGetFolderInfo *msg;
 	GtkTreeModel *model;
 	CamelStore *store;
 	gchar *full_name;
@@ -918,7 +947,7 @@ folder_tree_row_expanded (GtkTreeView *tree_view,
 		GTK_TREE_STORE (model), iter,
 		COL_BOOL_LOAD_SUBDIRS, FALSE, -1);
 
-	msg = mail_msg_new (&get_folder_info_info);
+	msg = g_object_new (em_folder_tree_get_folder_info_get_type (), NULL);
 	msg->root = gtk_tree_row_reference_new (model, path);
 	camel_object_ref (store);
 	msg->store = store;
@@ -928,7 +957,8 @@ folder_tree_row_expanded (GtkTreeView *tree_view,
 		CAMEL_STORE_FOLDER_INFO_RECURSIVE |
 		CAMEL_STORE_FOLDER_INFO_FAST;
 
-	mail_msg_unordered_push (msg);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) msg);
 }
 
 static void
@@ -1435,8 +1465,10 @@ fail:
 
 /* TODO: Merge the drop handling code/menu's into one spot using a popup target for details */
 /* Drop handling */
+
+typedef struct _DragDataReceivedAsync DragDataReceivedAsync;
 struct _DragDataReceivedAsync {
-	MailMsg base;
+	EMailMsg base;
 
 	/* input data */
 	GdkDragContext *context;
@@ -1453,15 +1485,23 @@ struct _DragDataReceivedAsync {
 	guint moved:1;
 	guint aborted:1;
 };
+typedef struct _DragDataReceivedAsyncClass DragDataReceivedAsyncClass;
+struct _DragDataReceivedAsyncClass
+{
+	EMailMsgClass parent_class;
+};
+GType drag_data_received_async_get_type (void);
+G_DEFINE_TYPE (DragDataReceivedAsync, drag_data_received_async, E_TYPE_MAIL_MSG)
 
 static void
-folder_tree_drop_folder(struct _DragDataReceivedAsync *m)
+folder_tree_drop_folder(DragDataReceivedAsync *m)
 {
 	CamelFolder *src;
 
 	d(printf(" * Drop folder '%s' onto '%s'\n", m->selection->data, m->full_name));
 
-	if (!(src = mail_tool_uri_to_folder((gchar *)m->selection->data, 0, &m->base.ex)))
+	if (!(src = mail_tool_uri_to_folder((gchar *)m->selection->data, 0,
+					    e_mail_msg_get_exception ((EMailMsg*) m))))
 		return;
 
 	em_folder_utils_copy_folders(src->parent_store, src->full_name, m->store, m->full_name?m->full_name:"", m->move);
@@ -1469,7 +1509,7 @@ folder_tree_drop_folder(struct _DragDataReceivedAsync *m)
 }
 
 static gchar *
-folder_tree_drop_async__desc (struct _DragDataReceivedAsync *m)
+folder_tree_drop_async__desc (DragDataReceivedAsync *m)
 {
 	CamelURL *url;
 	gchar *buf;
@@ -1494,7 +1534,7 @@ folder_tree_drop_async__desc (struct _DragDataReceivedAsync *m)
 }
 
 static void
-folder_tree_drop_async__exec (struct _DragDataReceivedAsync *m)
+folder_tree_drop_async__exec (DragDataReceivedAsync *m)
 {
 	CamelFolder *folder;
 
@@ -1503,14 +1543,16 @@ folder_tree_drop_async__exec (struct _DragDataReceivedAsync *m)
 		/* copy or move (aka rename) a folder */
 		folder_tree_drop_folder(m);
 	} else if (m->full_name == NULL) {
-		camel_exception_set (&m->base.ex, CAMEL_EXCEPTION_SYSTEM,
+		camel_exception_set (e_mail_msg_get_exception ((EMailMsg*) m), CAMEL_EXCEPTION_SYSTEM,
 				     _("Cannot drop message(s) into toplevel store"));
-	} else if ((folder = camel_store_get_folder (m->store, m->full_name, 0, &m->base.ex))) {
+	} else if ((folder = camel_store_get_folder (m->store, m->full_name, 0,
+						     e_mail_msg_get_exception ((EMailMsg*) m)))) {
 		switch (m->info) {
 		case DND_DROP_TYPE_UID_LIST:
 			/* import a list of uids from another evo folder */
-			em_utils_selection_get_uidlist(m->selection, folder, m->move, &m->base.ex);
-			m->moved = m->move && !camel_exception_is_set(&m->base.ex);
+			em_utils_selection_get_uidlist(m->selection, folder, m->move,
+						       e_mail_msg_get_exception ((EMailMsg*) m));
+			m->moved = m->move && !e_mail_msg_exception_is_set((EMailMsg*) m);
 			break;
 		case DND_DROP_TYPE_MESSAGE_RFC822:
 			/* import a message/rfc822 stream */
@@ -1528,29 +1570,54 @@ folder_tree_drop_async__exec (struct _DragDataReceivedAsync *m)
 }
 
 static void
-folder_tree_drop_async__free (struct _DragDataReceivedAsync *m)
+folder_tree_drop_async__free (GObject *object)
 {
-	g_object_unref(m->context);
-	camel_object_unref(m->store);
-	g_free(m->full_name);
+	DragDataReceivedAsync *msg = (DragDataReceivedAsync*) object;
 
-	g_free(m->selection->data);
-	g_free(m->selection);
+	if (msg->context) {
+		g_object_unref(msg->context);
+		msg->context = NULL;
+	}
+
+	if (msg->store) {
+		camel_object_unref(msg->store);
+		msg->store = NULL;
+	}
+
+	g_free(msg->full_name);
+	msg->full_name = NULL;
+
+	if (msg->selection) {
+		g_free(msg->selection->data);
+		g_free(msg->selection);
+		msg->selection = NULL;
+	}
+
+	G_OBJECT_CLASS (drag_data_received_async_parent_class)->dispose (object);
 }
 
-static MailMsgInfo folder_tree_drop_async_info = {
-	sizeof (struct _DragDataReceivedAsync),
-	(MailMsgDescFunc) folder_tree_drop_async__desc,
-	(MailMsgExecFunc) folder_tree_drop_async__exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) folder_tree_drop_async__free
-};
+static void
+drag_data_received_async_class_init (DragDataReceivedAsyncClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = folder_tree_drop_async__free;
+	klass->parent_class.desc = (MailMsgDescFunc) folder_tree_drop_async__desc;
+	klass->parent_class.exec = (MailMsgExecFunc) folder_tree_drop_async__exec;
+	klass->parent_class.done = NULL;
+}
+
+static void
+drag_data_received_async_init (DragDataReceivedAsync *msg)
+{
+}
 
 static void
-tree_drag_data_action(struct _DragDataReceivedAsync *m)
+tree_drag_data_action(DragDataReceivedAsync *m)
 {
 	m->move = m->action == GDK_ACTION_MOVE;
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 static void
@@ -1560,7 +1627,7 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint
 	GtkTreeModel *model;
 	GtkTreeView *tree_view;
 	GtkTreePath *dest_path;
-	struct _DragDataReceivedAsync *m;
+	DragDataReceivedAsync *m;
 	gboolean is_store;
 	CamelStore *store;
 	GtkTreeIter iter;
@@ -1595,7 +1662,7 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint
 		return;
 	}
 
-	m = mail_msg_new (&folder_tree_drop_async_info);
+	m = g_object_new (drag_data_received_async_get_type (), NULL);
 	m->context = context;
 	g_object_ref(context);
 	m->store = store;
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index 2838e82..e0b035e 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -14,9 +14,11 @@
  *
  *
  * Authors:
- *		Jeffrey Stedfast <fejj ximian com>
+ *   Jeffrey Stedfast <fejj ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -46,28 +48,25 @@
 #include <camel/camel-file-utils.h>
 #include <camel/camel-stream-fs.h>
 
-#include "e-util/e-mktemp.h"
-
 #include "e-util/e-alert-dialog.h"
+#include "e-util/e-mktemp.h"
 
+#include "e-mail-local.h"
+#include "e-mail-store.h"
+#include "e-mail-task-manager.h"
+#include "em-folder-properties.h"
+#include "em-folder-selector.h"
+#include "em-folder-tree-model.h"
+#include "em-folder-tree.h"
+#include "em-folder-utils.h"
+#include "em-utils.h"
 #include "em-vfolder-rule.h"
-
+#include "mail-config.h"
+#include "mail-folder-cache.h"
 #include "mail-mt.h"
 #include "mail-ops.h"
 #include "mail-tools.h"
-#include "mail-config.h"
 #include "mail-vfolder.h"
-#include "mail-folder-cache.h"
-
-#include "em-utils.h"
-#include "em-folder-tree.h"
-#include "em-folder-tree-model.h"
-#include "em-folder-utils.h"
-#include "em-folder-selector.h"
-#include "em-folder-properties.h"
-
-#include "e-mail-local.h"
-#include "e-mail-store.h"
 
 #define d(x)
 
@@ -79,8 +78,9 @@ emfu_is_special_local_folder (const gchar *name)
 	return (!strcmp (name, "Drafts") || !strcmp (name, "Inbox") || !strcmp (name, "Outbox") || !strcmp (name, "Sent") || !strcmp (name, "Templates"));
 }
 
+typedef struct _EMCopyFolders EMCopyFolders;
 struct _EMCopyFolders {
-	MailMsg base;
+	EMailMsg base;
 
 	/* input data */
 	CamelStore *fromstore;
@@ -91,15 +91,21 @@ struct _EMCopyFolders {
 
 	gint delete;
 };
+typedef struct _EMCopyFoldersClass EMCopyFoldersClass;
+struct _EMCopyFoldersClass {
+	EMailMsgClass parent_class;
+};
+GType em_copy_folders_get_type (void);
+G_DEFINE_TYPE (EMCopyFolders, em_copy_folders, E_TYPE_MAIL_MSG)
 
 static gchar *
-emft_copy_folders__desc (struct _EMCopyFolders *m, gint complete)
+emft_copy_folders__desc (EMCopyFolders *m, gint complete)
 {
 	return g_strdup_printf (_("Copying `%s' to `%s'"), m->frombase, m->tobase);
 }
 
 static void
-emft_copy_folders__exec (struct _EMCopyFolders *m)
+emft_copy_folders__exec (EMCopyFolders *m)
 {
 	guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
 	GList *pending = NULL, *deleting = NULL, *l;
@@ -108,7 +114,8 @@ emft_copy_folders__exec (struct _EMCopyFolders *m)
 	const gchar *tmp;
 	gint fromlen;
 
-	if (!(fi = camel_store_get_folder_info (m->fromstore, m->frombase, flags, &m->base.ex)))
+	if (!(fi = camel_store_get_folder_info (m->fromstore, m->frombase, flags,
+						e_mail_msg_get_exception ((EMailMsg*) m))))
 		return;
 
 	pending = g_list_append (pending, fi);
@@ -148,8 +155,9 @@ emft_copy_folders__exec (struct _EMCopyFolders *m)
 			if ((info->flags & CAMEL_FOLDER_NOSELECT) == 0) {
 				d(printf ("this folder is selectable\n"));
 				if (m->tostore == m->fromstore && m->delete) {
-					camel_store_rename_folder (m->fromstore, info->full_name, toname->str, &m->base.ex);
-					if (camel_exception_is_set (&m->base.ex))
+					camel_store_rename_folder (m->fromstore, info->full_name, toname->str,
+								   e_mail_msg_get_exception ((EMailMsg*) m));
+					if (e_mail_msg_exception_is_set ((EMailMsg*) m))
 						goto exception;
 
 					/* this folder no longer exists, unsubscribe it */
@@ -158,19 +166,22 @@ emft_copy_folders__exec (struct _EMCopyFolders *m)
 
 					deleted = 1;
 				} else {
-					if (!(fromfolder = camel_store_get_folder (m->fromstore, info->full_name, 0, &m->base.ex)))
+					if (!(fromfolder = camel_store_get_folder (m->fromstore, info->full_name, 0,
+										   e_mail_msg_get_exception ((EMailMsg*) m))))
 						goto exception;
 
-					if (!(tofolder = camel_store_get_folder (m->tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, &m->base.ex))) {
+					if (!(tofolder = camel_store_get_folder (m->tostore, toname->str, CAMEL_STORE_FOLDER_CREATE,
+										 e_mail_msg_get_exception ((EMailMsg*) m)))) {
 						camel_object_unref (fromfolder);
 						goto exception;
 					}
 
 					uids = camel_folder_get_uids (fromfolder);
-					camel_folder_transfer_messages_to (fromfolder, uids, tofolder, NULL, m->delete, &m->base.ex);
+					camel_folder_transfer_messages_to (fromfolder, uids, tofolder, NULL, m->delete,
+									   e_mail_msg_get_exception ((EMailMsg*) m));
 					camel_folder_free_uids (fromfolder, uids);
 
-					if (m->delete && !camel_exception_is_set (&m->base.ex))
+					if (m->delete && !e_mail_msg_exception_is_set ((EMailMsg*) m))
 						camel_folder_sync(fromfolder, TRUE, NULL);
 
 					camel_object_unref (fromfolder);
@@ -178,7 +189,7 @@ emft_copy_folders__exec (struct _EMCopyFolders *m)
 				}
 			}
 
-			if (camel_exception_is_set (&m->base.ex))
+			if (e_mail_msg_exception_is_set ((EMailMsg*) m))
 				goto exception;
 			else if (m->delete && !deleted)
 				deleting = g_list_prepend (deleting, info);
@@ -219,30 +230,48 @@ emft_copy_folders__exec (struct _EMCopyFolders *m)
 }
 
 static void
-emft_copy_folders__free (struct _EMCopyFolders *m)
+emft_copy_folders__free (GObject *object)
 {
-	camel_object_unref (m->fromstore);
-	camel_object_unref (m->tostore);
+	EMCopyFolders *m = (EMCopyFolders*) object;
+	if (m->fromstore) {
+		camel_object_unref (m->fromstore);
+		m->frombase = NULL;
+	}
+	if (m->tostore) {
+		camel_object_unref (m->tostore);
+		m->tostore = NULL;
+	}
 
 	g_free (m->frombase);
+	m->frombase = NULL;
 	g_free (m->tobase);
+	m->tobase = NULL;
+
+	G_OBJECT_CLASS (em_copy_folders_parent_class)->dispose (object);
 }
 
-static MailMsgInfo copy_folders_info = {
-	sizeof (struct _EMCopyFolders),
-	(MailMsgDescFunc) emft_copy_folders__desc,
-	(MailMsgExecFunc) emft_copy_folders__exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) emft_copy_folders__free
-};
+static void
+em_copy_folders_class_init (EMCopyFoldersClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = emft_copy_folders__free;
+	klass->parent_class.desc = (MailMsgDescFunc) emft_copy_folders__desc;
+	klass->parent_class.exec = (MailMsgExecFunc) emft_copy_folders__exec;
+	klass->parent_class.done = NULL;
+}
+
+static void
+em_copy_folders_init (EMCopyFolders *msg)
+{
+}
 
 gint
 em_folder_utils_copy_folders(CamelStore *fromstore, const gchar *frombase, CamelStore *tostore, const gchar *tobase, gint delete)
 {
-	struct _EMCopyFolders *m;
-	gint seq;
+	EMCopyFolders *m;
 
-	m = mail_msg_new (&copy_folders_info);
+	m = g_object_new (em_copy_folders_get_type (), NULL);
 	camel_object_ref (fromstore);
 	m->fromstore = fromstore;
 	camel_object_ref (tostore);
@@ -250,11 +279,11 @@ em_folder_utils_copy_folders(CamelStore *fromstore, const gchar *frombase, Camel
 	m->frombase = g_strdup (frombase);
 	m->tobase = g_strdup (tobase);
 	m->delete = delete;
-	seq = m->base.seq;
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
-	return seq;
+	return e_mail_msg_get_id ((EMailMsg*) m);
 }
 
 struct _copy_folder_data {
@@ -464,8 +493,9 @@ em_folder_utils_delete_folder (CamelFolder *folder)
 	gtk_widget_show (dialog);
 }
 
+typedef struct _EMCreateFolder EMCreateFolder;
 struct _EMCreateFolder {
-	MailMsg base;
+	EMailMsg base;
 
 	/* input data */
 	CamelStore *store;
@@ -480,6 +510,12 @@ struct _EMCreateFolder {
 	void (* done) (CamelFolderInfo *fi, gpointer user_data);
 	gpointer user_data;
 };
+typedef struct _EMCreateFolderClass EMCreateFolderClass;
+struct _EMCreateFolderClass {
+	EMailMsgClass parent_class;
+};
+GType em_create_folder_get_type ();
+G_DEFINE_TYPE (EMCreateFolder, em_create_folder, E_TYPE_MAIL_MSG);
 
 /* Temporary Structure to hold data to pass across function */
 struct _EMCreateFolderTempData
@@ -490,54 +526,71 @@ struct _EMCreateFolderTempData
 };
 
 static gchar *
-emfu_create_folder__desc (struct _EMCreateFolder *m)
+emfu_create_folder__desc (EMCreateFolder *m)
 {
 	return g_strdup_printf (_("Creating folder `%s'"), m->full_name);
 }
 
 static void
-emfu_create_folder__exec (struct _EMCreateFolder *m)
+emfu_create_folder__exec (EMCreateFolder *m)
 {
 	d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name));
 
-	if ((m->fi = camel_store_create_folder (m->store, m->parent, m->name, &m->base.ex))) {
+	if ((m->fi = camel_store_create_folder (m->store, m->parent, m->name,
+						e_mail_msg_get_exception ((EMailMsg*) m)))) {
 		if (camel_store_supports_subscriptions (m->store))
-			camel_store_subscribe_folder (m->store, m->full_name, &m->base.ex);
+			camel_store_subscribe_folder (m->store, m->full_name,
+						      e_mail_msg_get_exception ((EMailMsg*) m));
 	}
 }
 
 static void
-emfu_create_folder__done (struct _EMCreateFolder *m)
+emfu_create_folder__done (EMCreateFolder *m)
 {
 	if (m->done)
 		m->done (m->fi, m->user_data);
 }
 
 static void
-emfu_create_folder__free (struct _EMCreateFolder *m)
+emfu_create_folder__free (GObject *object)
 {
-	camel_store_free_folder_info (m->store, m->fi);
-	camel_object_unref (m->store);
+	EMCreateFolder *m = (EMCreateFolder*) object;
+
+	if (m->store) {
+		camel_store_free_folder_info (m->store, m->fi);
+		camel_object_unref (m->store);
+		m->store = NULL;
+	}
 	g_free (m->full_name);
+	m->full_name = NULL;
 	g_free (m->parent);
+	m->parent = NULL;
 	g_free (m->name);
+	m->name = NULL;
 }
 
-static MailMsgInfo create_folder_info = {
-	sizeof (struct _EMCreateFolder),
-	(MailMsgDescFunc) emfu_create_folder__desc,
-	(MailMsgExecFunc) emfu_create_folder__exec,
-	(MailMsgDoneFunc) emfu_create_folder__done,
-	(MailMsgFreeFunc) emfu_create_folder__free
-};
+static void
+em_create_folder_class_init (EMCreateFolderClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = emfu_create_folder__free;
+	klass->parent_class.desc = (MailMsgDescFunc) emfu_create_folder__desc;
+	klass->parent_class.exec = (MailMsgExecFunc) emfu_create_folder__exec;
+	klass->parent_class.done = (MailMsgDoneFunc) emfu_create_folder__done;
+}
+
+static void
+em_create_folder_init (EMCreateFolder *msg)
+{
+}
 
 static gint
 emfu_create_folder_real (CamelStore *store, const gchar *full_name, void (* done) (CamelFolderInfo *fi, gpointer user_data), gpointer user_data)
 {
 	gchar *name, *namebuf = NULL;
-	struct _EMCreateFolder *m;
+	EMCreateFolder *m;
 	const gchar *parent;
-	gint id;
 
 	namebuf = g_strdup (full_name);
 	if (!(name = strrchr (namebuf, '/'))) {
@@ -548,7 +601,7 @@ emfu_create_folder_real (CamelStore *store, const gchar *full_name, void (* done
 		parent = namebuf;
 	}
 
-	m = mail_msg_new (&create_folder_info);
+	m = g_object_new (em_create_folder_get_type (), NULL);
 	camel_object_ref (store);
 	m->store = store;
 	m->full_name = g_strdup (full_name);
@@ -559,10 +612,10 @@ emfu_create_folder_real (CamelStore *store, const gchar *full_name, void (* done
 
 	g_free (namebuf);
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
-	return id;
+	return e_mail_msg_get_id ((EMailMsg*) m);
 }
 
 static void
@@ -662,10 +715,17 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft,
 	gtk_widget_show (dialog);
 }
 
+typedef struct _folder_unsub_t FolderUnsubMsg;
 struct _folder_unsub_t {
-	MailMsg base;
+	EMailMsg base;
 	gchar *folder_uri;
 };
+typedef struct _FolderUnsubMsgClass FolderUnsubMsgClass;
+struct _FolderUnsubMsgClass {
+	EMailMsgClass parent_class;
+};
+GType folder_unsub_msg_get_type (void);
+G_DEFINE_TYPE (FolderUnsubMsg, folder_unsub_msg, E_TYPE_MAIL_MSG)
 
 static gchar *
 emfu_unsubscribe_folder__desc (struct _folder_unsub_t *msg)
@@ -682,8 +742,8 @@ emfu_unsubscribe_folder__exec (struct _folder_unsub_t *msg)
 	const gchar *path = NULL;
 	gint url_flags;
 
-	store = camel_session_get_store (
-		session, msg->folder_uri, &msg->base.ex);
+	store = camel_session_get_store (session, msg->folder_uri,
+					 e_mail_msg_get_exception ((EMailMsg*) msg));
 	if (store == NULL)
 		return;
 
@@ -696,36 +756,49 @@ emfu_unsubscribe_folder__exec (struct _folder_unsub_t *msg)
 		path = url->path + 1;
 
 	if (path != NULL)
-		camel_store_unsubscribe_folder (store, path, &msg->base.ex);
+		camel_store_unsubscribe_folder (store, path,
+						e_mail_msg_get_exception ((EMailMsg*) msg));
 
 	camel_url_free (url);
 }
 
 static void
-emfu_unsubscribe_folder__free (struct _folder_unsub_t *msg)
+emfu_unsubscribe_folder__free (GObject *object)
 {
+	FolderUnsubMsg *msg = (FolderUnsubMsg *) object;
 	g_free (msg->folder_uri);
+
+	G_OBJECT_CLASS (folder_unsub_msg_parent_class)->finalize (object);
 }
 
-static MailMsgInfo unsubscribe_info = {
-	sizeof (struct _folder_unsub_t),
-	(MailMsgDescFunc) emfu_unsubscribe_folder__desc,
-	(MailMsgExecFunc) emfu_unsubscribe_folder__exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) emfu_unsubscribe_folder__free
-};
+static void
+folder_unsub_msg_class_init (FolderUnsubMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = emfu_unsubscribe_folder__free;
+	klass->parent_class.desc = (MailMsgDescFunc) emfu_unsubscribe_folder__desc;
+	klass->parent_class.exec = (MailMsgExecFunc) emfu_unsubscribe_folder__exec;
+	klass->parent_class.done = NULL;
+}
+
+static void
+folder_unsub_msg_init (FolderUnsubMsg *msg)
+{
+}
 
 void
 em_folder_utils_unsubscribe_folder (const gchar *folder_uri)
 {
-	struct _folder_unsub_t *unsub;
+	FolderUnsubMsg *unsub;
 
 	g_return_if_fail (folder_uri != NULL);
 
-	unsub = mail_msg_new (&unsubscribe_info);
+	unsub = g_object_new (folder_unsub_msg_get_type (), NULL);
 	unsub->folder_uri = g_strdup (folder_uri);
 
-	mail_msg_unordered_push (unsub);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) unsub);
 }
 
 const gchar *
diff --git a/mail/em-format-html-print.c b/mail/em-format-html-print.c
index fb9b1a7..f8acb82 100644
--- a/mail/em-format-html-print.c
+++ b/mail/em-format-html-print.c
@@ -30,14 +30,24 @@
 #include <gtkhtml/gtkhtml.h>
 
 #include <camel/camel-i18n.h>
-#include "mail-ops.h"
-#include "mail-mt.h"
-#include "em-format-html-print.h"
+
 #include <e-util/e-print.h>
 
+#include "e-mail-task-manager.h"
+#include "em-format-html-print.h"
+#include "mail-mt.h"
+#include "mail-ops.h"
+
 static gpointer parent_class = NULL;
 
 static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
+static void
 efhp_finalize (GObject *object)
 {
 	EMFormatHTMLPrint *efhp = (EMFormatHTMLPrint *)object;
@@ -239,7 +249,7 @@ em_format_html_print_message (EMFormatHTMLPrint *efhp,
 		EM_FORMAT_HTML_HEADER_BCC;
 
 	mail_get_message (
-		folder, uid, emfhp_got_message, efhp, mail_msg_unordered_push);
+		folder, uid, emfhp_got_message, efhp, default_unordered_push);
 }
 
 void
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index b9db3d1..e2c17af 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -14,9 +14,11 @@
  *
  *
  * Authors:
- *		Michael Zucchi <notzed ximian com>
+ *   Michael Zucchi <notzed ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -78,6 +80,7 @@
 #include "em-format-html.h"
 #include "em-html-stream.h"
 #include "em-utils.h"
+#include "e-mail-task-manager.h"
 
 #define d(x)
 
@@ -148,8 +151,9 @@ static CamelDataCache *emfh_http_cache;
 #define EMFH_HTTP_CACHE_PATH "http"
 
 /* Sigh, this is so we have a cancellable, async rendering thread */
+typedef struct _format_msg FormatMsg;
 struct _format_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	EMFormatHTML *format;
 	EMFormat *format_source;
@@ -158,6 +162,12 @@ struct _format_msg {
 	gchar *uid;
 	CamelMimeMessage *message;
 };
+typedef struct _FormatMsgClass FormatMsgClass;
+struct _FormatMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType format_msg_get_type ();
+G_DEFINE_TYPE (FormatMsg, format_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
 efh_format_desc (struct _format_msg *m)
@@ -283,30 +293,53 @@ efh_format_done (struct _format_msg *m)
 }
 
 static void
-efh_format_free (struct _format_msg *m)
+efh_format_free (GObject *object)
 {
+	FormatMsg *m = (FormatMsg *) object;
+
 	d(printf("formatter freed\n"));
-	g_object_unref(m->format);
+	if (m->format) {
+		g_object_unref(m->format);
+		m->format = NULL;
+	}
 	if (m->estream) {
 		camel_stream_close((CamelStream *)m->estream);
 		camel_object_unref(m->estream);
+		m->estream = NULL;
 	}
-	if (m->folder)
+	if (m->folder) {
 		camel_object_unref(m->folder);
-	g_free(m->uid);
-	if (m->message)
+		m->folder = NULL;
+	}
+	if (m->message) {
 		camel_object_unref(m->message);
-	if (m->format_source)
+		m->message = NULL;
+	}
+	if (m->format_source) {
 		g_object_unref(m->format_source);
+		m->format_source = NULL;
+	}
+	g_free(m->uid);
+	m->uid = NULL;
+
+	G_OBJECT_CLASS (format_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo efh_format_info = {
-	sizeof (struct _format_msg),
-	(MailMsgDescFunc) efh_format_desc,
-	(MailMsgExecFunc) efh_format_exec,
-	(MailMsgDoneFunc) efh_format_done,
-	(MailMsgFreeFunc) efh_format_free
-};
+static void
+format_msg_class_init (FormatMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = efh_format_free;
+
+	klass->parent_class.desc = (MailMsgDescFunc) efh_format_desc;
+	klass->parent_class.exec = (MailMsgExecFunc) efh_format_exec;
+	klass->parent_class.done = (MailMsgDoneFunc) efh_format_done;
+}
+static void
+format_msg_init (FormatMsg *msg)
+{
+}
 
 static gboolean
 efh_format_timeout(struct _format_msg *m)
@@ -316,7 +349,7 @@ efh_format_timeout(struct _format_msg *m)
 	struct _EMFormatHTMLPrivate *p = efh->priv;
 
 	if (m->format->html == NULL) {
-		mail_msg_unref(m);
+		g_object_unref (m);
 		return FALSE;
 	}
 
@@ -346,7 +379,7 @@ efh_format_timeout(struct _format_msg *m)
 	if (m->message == NULL) {
 		hstream = gtk_html_begin(efh->html);
 		gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK);
-		mail_msg_unref(m);
+		g_object_unref (m);
 		p->last_part = NULL;
 	} else {
 		efh->state = EM_FORMAT_HTML_STATE_RENDERING;
@@ -371,8 +404,9 @@ efh_format_timeout(struct _format_msg *m)
 			p->last_part = m->message;
 		}
 
-		efh->priv->format_id = m->base.seq;
-		mail_msg_unordered_push (m);
+		efh->priv->format_id = e_mail_msg_get_id ((EMailMsg*) m);
+		e_mail_task_manager_unordered_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) m);
 	}
 
 	efh->priv->format_timeout_id = 0;
@@ -395,13 +429,14 @@ efh_gtkhtml_destroy(GtkHTML *html, EMFormatHTML *efh)
 	if (efh->priv->format_timeout_id != 0) {
 		g_source_remove(efh->priv->format_timeout_id);
 		efh->priv->format_timeout_id = 0;
-		mail_msg_unref(efh->priv->format_timeout_msg);
+		g_object_unref (efh->priv->format_timeout_msg);
 		efh->priv->format_timeout_msg = NULL;
 	}
 
 	/* This probably works ... */
 	if (efh->priv->format_id != -1)
-		mail_msg_cancel(efh->priv->format_id);
+		e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+						 efh->priv->format_id);
 
 	if (efh->html != NULL) {
 		g_object_unref (efh->html);
@@ -620,7 +655,7 @@ efh_format_clone (EMFormat *emf,
                   EMFormat *emfsource)
 {
 	EMFormatHTML *efh = EM_FORMAT_HTML (emf);
-	struct _format_msg *m;
+	FormatMsg *m;
 
 	/* How to sub-class ?  Might need to adjust api ... */
 
@@ -632,7 +667,7 @@ efh_format_clone (EMFormat *emf,
 		d(printf(" timeout for last still active, removing ...\n"));
 		g_source_remove(efh->priv->format_timeout_id);
 		efh->priv->format_timeout_id = 0;
-		mail_msg_unref(efh->priv->format_timeout_msg);
+		g_object_unref (efh->priv->format_timeout_msg);
 		efh->priv->format_timeout_msg = NULL;
 	}
 
@@ -645,7 +680,7 @@ efh_format_clone (EMFormat *emf,
 	if (msg != NULL)
 		camel_object_ref (msg);
 
-	m = mail_msg_new (&efh_format_info);
+	m = g_object_new (format_msg_get_type (), NULL);
 	m->format = g_object_ref (emf);
 	m->format_source = emfsource;
 	m->folder = folder;
@@ -658,7 +693,8 @@ efh_format_clone (EMFormat *emf,
 	} else {
 		d(printf(" still busy, cancelling and queuing wait\n"));
 		/* cancel and poll for completion */
-		mail_msg_cancel (efh->priv->format_id);
+		e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+						 efh->priv->format_id);
 		efh->priv->format_timeout_msg = m;
 		efh->priv->format_timeout_id = g_timeout_add (
 			100, (GSourceFunc) efh_format_timeout, m);
diff --git a/mail/em-subscribe-editor.c b/mail/em-subscribe-editor.c
index 76fec73..1944b28 100644
--- a/mail/em-subscribe-editor.c
+++ b/mail/em-subscribe-editor.c
@@ -14,9 +14,11 @@
  *
  *
  * Authors:
- *		Michael Zucchi <notzed ximian com>
+ *   Michael Zucchi <notzed ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -26,23 +28,22 @@
 
 #include <string.h>
 
-#include "mail-tools.h"
-#include "mail-ops.h"
-#include "mail-mt.h"
-/*#include "mail-folder-cache.h"*/
+#include <glib/gi18n.h>
+
 #include "camel/camel-exception.h"
 #include "camel/camel-store.h"
 #include "camel/camel-session.h"
 
-#include "e-util/e-util.h"
 #include "e-util/e-account-utils.h"
 #include "e-util/e-util-private.h"
+#include "e-util/e-util.h"
 
+#include "e-mail-task-manager.h"
 #include "em-subscribe-editor.h"
-
 #include "mail-config.h"
-
-#include <glib/gi18n.h>
+#include "mail-mt.h"
+#include "mail-ops.h"
+#include "mail-tools.h"
 
 #define d(x)
 
@@ -104,7 +105,7 @@ struct _EMSubscribeNode {
 
 typedef struct _MailMsgListNode MailMsgListNode;
 struct _MailMsgListNode {
-	MailMsg *msg;
+	EMailMsg *msg;
 };
 
 static void sub_editor_busy(EMSubscribeEditor *se, gint dir);
@@ -155,28 +156,37 @@ sub_unref(EMSubscribe *sub)
 
 /* ** Subscribe folder operation **************************************** */
 
+typedef struct _zsubscribe_msg ZsubscribeMsg;
 struct _zsubscribe_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	EMSubscribe *sub;
 	EMSubscribeNode *node;
 	gint subscribe;
 	gchar *path;
 };
+typedef struct _ZsubscribeMsgClass ZsubscribeMsgClass;
+struct _ZsubscribeMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType zsubscribe_msg_get_type ();
+G_DEFINE_TYPE (ZsubscribeMsg, zsubscribe_msg, E_TYPE_MAIL_MSG);
 
 static void
-sub_folder_exec (struct _zsubscribe_msg *m)
+sub_folder_exec (ZsubscribeMsg *m)
 {
 	if (m->subscribe)
-		camel_store_subscribe_folder (m->sub->store, m->node->info->full_name, &m->base.ex);
+		camel_store_subscribe_folder (m->sub->store, m->node->info->full_name,
+					      e_mail_msg_get_exception ((EMailMsg*) m));
 	else
-		camel_store_unsubscribe_folder (m->sub->store, m->node->info->full_name, &m->base.ex);
+		camel_store_unsubscribe_folder (m->sub->store, m->node->info->full_name,
+						e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-sub_folder_done (struct _zsubscribe_msg *m)
+sub_folder_done (ZsubscribeMsg *m)
 {
-	struct _zsubscribe_msg *next;
+	ZsubscribeMsg *next;
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 	EMSubscribeNode *node;
@@ -187,7 +197,7 @@ sub_folder_done (struct _zsubscribe_msg *m)
 	if (m->sub->cancel)
 		return;
 
-	if (!camel_exception_is_set(&m->base.ex)) {
+	if (!e_mail_msg_exception_is_set((EMailMsg*) m)) {
 		if (m->subscribe)
 			m->node->info->flags |= CAMEL_FOLDER_SUBSCRIBED;
 		else
@@ -209,11 +219,12 @@ sub_folder_done (struct _zsubscribe_msg *m)
 	/* queue any further ones, or if out, update the ui */
 	msgListNode = g_queue_pop_head (&m->sub->subscribe);
 	if (msgListNode) {
-		next = (struct _zsubscribe_msg *) msgListNode->msg;
+		next = (ZsubscribeMsg *) msgListNode->msg;
 		/* Free the memory of the MailMsgListNode which won't be used anymore. */
 		g_free(msgListNode);
-		next->sub->subscribe_id = next->base.seq;
-                mail_msg_unordered_push (next);
+		next->sub->subscribe_id = e_mail_msg_get_id ((EMailMsg*) next);
+                e_mail_task_manager_unordered_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) next);
 	} else {
 		/* should it go off the model instead? */
 		sub_selection_changed(gtk_tree_view_get_selection(m->sub->tree), m->sub);
@@ -221,43 +232,63 @@ sub_folder_done (struct _zsubscribe_msg *m)
 }
 
 static void
-sub_folder_free (struct _zsubscribe_msg *m)
+sub_folder_free (GObject *object)
 {
+	ZsubscribeMsg *m = (ZsubscribeMsg *) object;
+
 	g_free(m->path);
-	sub_unref(m->sub);
+	m->path = NULL;
+
+	if (m->sub) {
+		sub_unref(m->sub);
+		m->sub = NULL;
+	}
+
+	G_OBJECT_CLASS (zsubscribe_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo sub_subscribe_folder_info = {
-	sizeof (struct _zsubscribe_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) sub_folder_exec,
-	(MailMsgDoneFunc) sub_folder_done,
-	(MailMsgFreeFunc) sub_folder_free
-};
+static void
+zsubscribe_msg_class_init (ZsubscribeMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = sub_folder_free;
+
+	klass->parent_class.desc = NULL;
+	klass->parent_class.exec = (MailMsgExecFunc) sub_folder_exec;
+	klass->parent_class.done = (MailMsgDoneFunc) sub_folder_done;
+}
+
+static void
+zsubscribe_msg_init (ZsubscribeMsg *msg)
+{
+}
 
 /* spath is tree path in string form */
 static gint
 sub_subscribe_folder (EMSubscribe *sub, EMSubscribeNode *node, gint state, const gchar *spath)
 {
-	struct _zsubscribe_msg *m;
+	ZsubscribeMsg *m;
 	MailMsgListNode *msgListNode;
 	gint id;
 
-	m = mail_msg_new (&sub_subscribe_folder_info);
+	m = g_object_new (zsubscribe_msg_get_type (), NULL);
 	m->sub = sub;
 	sub_ref(sub);
 	m->node = node;
 	m->subscribe = state;
 	m->path = g_strdup(spath);
 
-	id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
 	if (sub->subscribe_id == -1) {
 		sub->subscribe_id = id;
 		d(printf("running subscribe folder '%s'\n", spath));
-		mail_msg_unordered_push (m);
+		e_mail_task_manager_unordered_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) m);
 	} else {
+		/* FIXME: add to active msg hashtable? */
 		msgListNode = g_malloc0(sizeof(MailMsgListNode));
-		msgListNode->msg = (MailMsg *) m;
+		msgListNode->msg = (EMailMsg *) m;
 		d(printf("queueing subscribe folder '%s'\n", spath));
 		g_queue_push_tail (&sub->subscribe, msgListNode);
 	}
@@ -331,8 +362,9 @@ sub_fill_level(EMSubscribe *sub, CamelFolderInfo *info,  GtkTreeIter *parent, gi
 
 /* async query of folderinfo */
 
+typedef struct _emse_folderinfo_msg FolderInfoMsg;
 struct _emse_folderinfo_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gint seq;
 
@@ -340,22 +372,31 @@ struct _emse_folderinfo_msg {
 	EMSubscribeNode *node;
 	CamelFolderInfo *info;
 };
+typedef struct _FolderInfoMsgClass FolderInfoMsgClass;
+struct _FolderInfoMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType folder_info_msg_get_type ();
+G_DEFINE_TYPE (FolderInfoMsg, folder_info_msg, E_TYPE_MAIL_MSG);
 
 static void
-sub_folderinfo_exec (struct _emse_folderinfo_msg *m)
+sub_folderinfo_exec (FolderInfoMsg *m)
 {
 	gchar *pub_full_name=NULL;
 
 	if (m->seq == m->sub->seq) {
-		camel_operation_register(m->base.cancel);
-		m->info = camel_store_get_folder_info(m->sub->store, m->node?m->node->info->full_name:pub_full_name,
-						      CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL | CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST, &m->base.ex);
-		camel_operation_unregister(m->base.cancel);
+		camel_operation_register(e_mail_msg_get_operation ((EMailMsg*) m));
+		m->info = camel_store_get_folder_info(m->sub->store,
+						      m->node ? m->node->info->full_name : pub_full_name,
+						      CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL |
+						      CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST,
+						      e_mail_msg_get_exception ((EMailMsg*) m));
+		camel_operation_unregister(e_mail_msg_get_operation ((EMailMsg*) m));
 	}
 }
 
 static void
-sub_folderinfo_done (struct _emse_folderinfo_msg *m)
+sub_folderinfo_done (FolderInfoMsg *m)
 {
 	EMSubscribeNode *node;
 
@@ -363,9 +404,10 @@ sub_folderinfo_done (struct _emse_folderinfo_msg *m)
 	if (m->sub->cancel || m->seq != m->sub->seq)
 		return;
 
-	if (camel_exception_is_set (&m->base.ex)) {
+	if (e_mail_msg_exception_is_set ((EMailMsg*) m)) {
 		g_warning ("Error getting folder info from store: %s",
-			   camel_exception_get_description (&m->base.ex));
+			   camel_exception_get_description
+			   (e_mail_msg_get_exception ((EMailMsg*) m)));
 	}
 
 	if (m->info) {
@@ -386,8 +428,10 @@ sub_folderinfo_done (struct _emse_folderinfo_msg *m)
 }
 
 static void
-sub_folderinfo_free (struct _emse_folderinfo_msg *m)
+sub_folderinfo_free (GObject *object)
 {
+	FolderInfoMsg *m = (FolderInfoMsg*) object;
+
 	if (m->info)
 		m->sub->info_list = g_slist_prepend(m->sub->info_list, m->info);
 
@@ -401,38 +445,49 @@ sub_folderinfo_free (struct _emse_folderinfo_msg *m)
 		gtk_tree_view_expand_row(m->sub->tree, m->node->path, FALSE);
 
 	sub_unref(m->sub);
+
+	G_OBJECT_CLASS (folder_info_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo sub_folderinfo_info = {
-	sizeof (struct _emse_folderinfo_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) sub_folderinfo_exec,
-	(MailMsgDoneFunc) sub_folderinfo_done,
-	(MailMsgFreeFunc) sub_folderinfo_free
-};
+static void
+folder_info_msg_class_init (FolderInfoMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = sub_folderinfo_free;
+
+	klass->parent_class.desc = NULL;
+	klass->parent_class.exec = (MailMsgExecFunc) sub_folderinfo_exec;
+	klass->parent_class.done = (MailMsgDoneFunc) sub_folderinfo_done;
+}
+
+static void
+folder_info_msg_init (FolderInfoMsg *msg)
+{
+}
 
 static gint
 sub_queue_fill_level(EMSubscribe *sub, EMSubscribeNode *node)
 {
-	struct _emse_folderinfo_msg *m;
+	FolderInfoMsg *m;
 	gint id;
 
 	d(printf("%s:%s: Starting get folderinfo of '%s'\n", G_STRLOC, G_STRFUNC,
 		 node?node->info->full_name:"<root>"));
 
-	m = mail_msg_new (&sub_folderinfo_info);
+	m = g_object_new (folder_info_msg_get_type (), NULL);
 	sub_ref(sub);
 	m->sub = sub;
 	m->node = node;
 	m->seq = sub->seq;
 
-	sub->pending_id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	sub->pending_id = id;
 
 	sub_editor_busy(sub->editor, 1);
 
-	id = m->base.seq;
-
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 	return id;
 }
 
@@ -557,16 +612,18 @@ sub_destroy(GtkWidget *w, EMSubscribe *sub)
 	sub->cancel = TRUE;
 
 	if (sub->pending_id != -1)
-		mail_msg_cancel(sub->pending_id);
+		e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+						 sub->pending_id);
 
 	if (sub->subscribe_id != -1)
-		mail_msg_cancel(sub->subscribe_id);
+		e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+						 sub->subscribe_id);
 
 	while ((msgListNode = g_queue_pop_head (&sub->subscribe)) != NULL) {
 		m = (struct _zsubscribe_msg *) msgListNode->msg;
 		/* Free the memory of MailMsgListNode which won't be used anymore. */
 		g_free(msgListNode);
-		mail_msg_unref(m);
+		g_object_unref (m);
 	}
 
 	sub_unref(sub);
@@ -682,8 +739,10 @@ sub_editor_refresh(GtkWidget *w, EMSubscribeEditor *se)
 
 	/* drop any currently pending */
 	if (sub->pending_id != -1) {
-		mail_msg_cancel(sub->pending_id);
-		mail_msg_wait(sub->pending_id);
+		e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+						 sub->pending_id);
+		e_mail_task_manager_task_wait
+			(e_mail_task_manager_get_default (), sub->pending_id);
 	}
 
 	gtk_tree_store_clear((GtkTreeStore *)gtk_tree_view_get_model(sub->tree));
diff --git a/mail/em-sync-stream.c b/mail/em-sync-stream.c
index 982a56c..f0d1936 100644
--- a/mail/em-sync-stream.c
+++ b/mail/em-sync-stream.c
@@ -32,6 +32,8 @@
 #include <camel/camel-object.h>
 #include <libedataserver/e-flag.h>
 
+#include "e-util/e-util.h"
+
 #include "mail-mt.h"
 
 #define EMSS_CLASS(x) ((EMSyncStreamClass *)(((CamelObject *)(x))->klass))
@@ -127,7 +129,7 @@ emss_stream_write (CamelStream *stream, const gchar *string, gsize len)
 	if (emss->cancel)
 		return -1;
 
-	if (mail_in_main_thread ()) {
+	if (e_in_main_thread ()) {
 		EMSS_CLASS (emss)->sync_write (stream, string, len);
 	} else if (emss->buffer != NULL) {
 		if (len < (emss->buffer->allocated_len - emss->buffer->len))
@@ -149,7 +151,7 @@ emss_stream_flush (CamelStream *stream)
 	if (emss->cancel)
 		return -1;
 
-	if (mail_in_main_thread ())
+	if (e_in_main_thread ())
 		return EMSS_CLASS (emss)->sync_flush (stream);
 	else
 		emss_sync_op (emss, EMSS_FLUSH, NULL, 0);
@@ -167,7 +169,7 @@ emss_stream_close (CamelStream *stream)
 
 	emss->idle_id = 0;
 
-	if (mail_in_main_thread ())
+	if (e_in_main_thread ())
 		return EMSS_CLASS (emss)->sync_close (stream);
 	else
 		emss_sync_op (emss, EMSS_CLOSE, NULL, 0);
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 63d3234..94fee19 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -55,12 +55,6 @@
 
 #include <gio/gio.h>
 
-#include "mail-mt.h"
-#include "mail-ops.h"
-#include "mail-tools.h"
-#include "mail-config.h"
-#include "e-mail-tag-editor.h"
-
 #include <libedataserver/e-data-server-util.h>
 #include <libedataserver/e-flag.h>
 #include <libedataserver/e-proxy.h>
@@ -75,11 +69,17 @@
 #include "shell/e-shell.h"
 #include "widgets/misc/e-attachment.h"
 
-#include "em-utils.h"
+#include "e-mail-local.h"
+#include "e-mail-tag-editor.h"
+#include "e-mail-task-manager.h"
 #include "em-composer-utils.h"
 #include "em-format-quote.h"
-#include "e-mail-local.h"
+#include "em-utils.h"
+#include "mail-config.h"
+#include "mail-mt.h"
+#include "mail-ops.h"
 #include "mail-session.h"
+#include "mail-tools.h"
 
 /* XXX This is a dirty hack on a dirty hack.  We really need
  *     to rework or get rid of the functions that use this. */
@@ -943,9 +943,13 @@ em_utils_temp_save_part(GtkWidget *parent, CamelMimePart *part, gboolean mode)
 
 	/* FIXME: This doesn't handle default charsets */
 	if (mode)
-		mail_msg_wait(mail_save_part(part, path, emu_save_part_done, &done, TRUE));
+		e_mail_task_manager_task_wait
+			(e_mail_task_manager_get_default (),
+			 mail_save_part(part, path, emu_save_part_done, &done, TRUE));
 	else
-		mail_msg_wait(mail_save_part(part, path, emu_save_part_done, &done, FALSE));
+		e_mail_task_manager_task_wait
+			(e_mail_task_manager_get_default (),
+			 mail_save_part(part, path, emu_save_part_done, &done, FALSE));
 	if (!done) {
 		/* mail_save_part should popup an error box automagically */
 		g_free(path);
@@ -1671,8 +1675,8 @@ search_address_in_addressbooks (const gchar *address, gboolean local_only, gbool
 
 		d(printf(" checking '%s'\n", e_source_get_uri(source)));
 
-		hook_book = mail_cancel_hook_add (emu_addr_cancel_book, book);
-		hook_stop = mail_cancel_hook_add (emu_addr_cancel_stop, &stop);
+		hook_book = e_mail_task_manager_cancel_hook_add (emu_addr_cancel_book, book);
+		hook_stop = e_mail_task_manager_cancel_hook_add (emu_addr_cancel_stop, &stop);
 
 		book = g_hash_table_lookup (emu_books_hash, e_source_peek_uid (source));
 		if (!book) {
@@ -1742,8 +1746,8 @@ search_address_in_addressbooks (const gchar *address, gboolean local_only, gbool
 			g_clear_error (&err);
 		}
 
-		mail_cancel_hook_remove (hook_book);
-		mail_cancel_hook_remove (hook_stop);
+		e_mail_task_manager_cancel_hook_remove (hook_book);
+		e_mail_task_manager_cancel_hook_remove (hook_stop);
 
 		stop = stop || camel_operation_cancel_check (NULL);
 
diff --git a/mail/importers/elm-importer.c b/mail/importers/elm-importer.c
index c2d45a2..70b85af 100644
--- a/mail/importers/elm-importer.c
+++ b/mail/importers/elm-importer.c
@@ -40,15 +40,17 @@
 
 #include <camel/camel-operation.h>
 
-#include "mail-importer.h"
-
-#include "mail/mail-mt.h"
 #include "e-util/e-import.h"
+#include "mail/mail-mt.h"
+#include "mail/e-mail-task-manager.h"
+
+#include "mail-importer.h"
 
 #define d(x)
 
+typedef struct _elm_import_msg ElmImportMsg;
 struct _elm_import_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	EImport *import;
 	EImportTargetHome *target;
@@ -59,6 +61,12 @@ struct _elm_import_msg {
 	gint status_timeout_id;
 	CamelOperation *status;
 };
+typedef struct _ElmImportMsgClass ElmImportMsgClass;
+struct _ElmImportMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType elm_import_msg_get_type ();
+G_DEFINE_TYPE (ElmImportMsg, elm_import_msg, E_TYPE_MAIL_MSG);
 
 static GHashTable *
 parse_elm_rc(const gchar *elmrc)
@@ -173,7 +181,7 @@ elm_supported(EImport *ei, EImportTarget *target, EImportImporter *im)
 }
 
 static gchar *
-elm_import_desc (struct _elm_import_msg *m)
+elm_import_desc (ElmImportMsg *m)
 {
 	return g_strdup (_("Importing Elm data"));
 }
@@ -184,7 +192,7 @@ static MailImporterSpecial elm_special_folders[] = {
 };
 
 static void
-elm_import_exec (struct _elm_import_msg *m)
+elm_import_exec (ElmImportMsg *m)
 {
 	const gchar *maildir;
 	gchar *elmdir;
@@ -203,11 +211,11 @@ elm_import_exec (struct _elm_import_msg *m)
 }
 
 static void
-elm_import_done(struct _elm_import_msg *m)
+elm_import_done(ElmImportMsg *m)
 {
 	printf("importing complete\n");
 
-	if (!camel_exception_is_set(&m->base.ex)) {
+	if (!e_mail_msg_exception_is_set((EMailMsg*)m)) {
 		GConfClient *gconf;
 
 		gconf = gconf_client_get_default();
@@ -219,23 +227,40 @@ elm_import_done(struct _elm_import_msg *m)
 }
 
 static void
-elm_import_free(struct _elm_import_msg *m)
+elm_import_msg_dispose (GObject *object)
 {
-	camel_operation_unref(m->status);
+	ElmImportMsg *m = (ElmImportMsg*) object;
+
+	if (m->status) {
+		camel_operation_unref(m->status);
+		m->status = NULL;
+	}
 
 	g_free(m->status_what);
-	g_mutex_free(m->status_lock);
+	m->status_what = NULL;
+
+	if (m->status_lock) {
+		g_mutex_free(m->status_lock);
+		m->status_lock = NULL;
+	}
+
+	if (m->status_timeout_id) {
+		g_source_remove(m->status_timeout_id);
+		m->status_timeout_id = 0;
+	}
 
-	g_source_remove(m->status_timeout_id);
-	m->status_timeout_id = 0;
+	if (m->import) {
+		g_object_unref(m->import);
+		m->import = NULL;
+	}
 
-	g_object_unref(m->import);
+	G_OBJECT_CLASS (elm_import_msg_parent_class)->dispose (object);
 }
 
 static void
 elm_status(CamelOperation *op, const gchar *what, gint pc, gpointer data)
 {
-	struct _elm_import_msg *importer = data;
+	ElmImportMsg *importer = data;
 
 	if (pc == CAMEL_OPERATION_START)
 		pc = 0;
@@ -252,7 +277,7 @@ elm_status(CamelOperation *op, const gchar *what, gint pc, gpointer data)
 static gboolean
 elm_status_timeout(gpointer data)
 {
-	struct _elm_import_msg *importer = data;
+	ElmImportMsg *importer = data;
 	gint pc;
 	gchar *what;
 
@@ -269,21 +294,30 @@ elm_status_timeout(gpointer data)
 	return TRUE;
 }
 
-static MailMsgInfo elm_import_info = {
-	sizeof (struct _elm_import_msg),
-	(MailMsgDescFunc) elm_import_desc,
-	(MailMsgExecFunc) elm_import_exec,
-	(MailMsgDoneFunc) elm_import_done,
-	(MailMsgFreeFunc) elm_import_free
-};
+static void
+elm_import_msg_class_init (ElmImportMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = elm_import_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) elm_import_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) elm_import_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) elm_import_done;
+}
+
+static void
+elm_import_msg_init (ElmImportMsg *msg)
+{
+}
 
 static gint
 mail_importer_elm_import(EImport *ei, EImportTarget *target)
 {
-	struct _elm_import_msg *m;
+	ElmImportMsg *m;
 	gint id;
 
-	m = mail_msg_new(&elm_import_info);
+	m = g_object_new (elm_import_msg_get_type (), NULL);
 	g_datalist_set_data(&target->data, "elm-msg", m);
 	m->import = ei;
 	g_object_ref(m->import);
@@ -292,9 +326,10 @@ mail_importer_elm_import(EImport *ei, EImportTarget *target)
 	m->status_lock = g_mutex_new();
 	m->status = camel_operation_new(elm_status, m);
 
-	id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
 
-	mail_msg_fast_ordered_push (m);
+	e_mail_task_manager_fast_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
@@ -342,7 +377,7 @@ elm_import(EImport *ei, EImportTarget *target, EImportImporter *im)
 static void
 elm_cancel(EImport *ei, EImportTarget *target, EImportImporter *im)
 {
-	struct _elm_import_msg *m = g_datalist_get_data(&target->data, "elm-msg");
+	ElmImportMsg *m = g_datalist_get_data(&target->data, "elm-msg");
 
 	if (m)
 		camel_operation_cancel(m->status);
diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c
index ee1c958..8591c0b 100644
--- a/mail/importers/mail-importer.c
+++ b/mail/importers/mail-importer.c
@@ -47,15 +47,16 @@
 #include "e-util/e-util-private.h"
 #include "shell/e-shell-backend.h"
 
-#include "mail-mt.h"
-#include "mail-tools.h"
 #include "e-mail-local.h"
-#include "mail-session.h"
-
+#include "e-mail-task-manager.h"
 #include "mail-importer.h"
+#include "mail-mt.h"
+#include "mail-session.h"
+#include "mail-tools.h"
 
+typedef struct _import_mbox_msg ImportMboxMsg;
 struct _import_mbox_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gchar *path;
 	gchar *uri;
@@ -64,9 +65,15 @@ struct _import_mbox_msg {
 	void (*done)(gpointer data, CamelException *ex);
 	gpointer done_data;
 };
+typedef struct _ImportMboxMsgClass ImportMboxMsgClass;
+struct _ImportMboxMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType import_mbox_msg_get_type ();
+G_DEFINE_TYPE (ImportMboxMsg, import_mbox_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-import_mbox_desc (struct _import_mbox_msg *m)
+import_mbox_desc (ImportMboxMsg *m)
 {
 	return g_strdup (_("Importing mailbox"));
 }
@@ -113,7 +120,7 @@ decode_mozilla_status(const gchar *tmp)
 }
 
 static void
-import_mbox_exec (struct _import_mbox_msg *m)
+import_mbox_exec (ImportMboxMsg *m)
 {
 	CamelFolder *folder;
 	CamelMimeParser *mp = NULL;
@@ -129,7 +136,8 @@ import_mbox_exec (struct _import_mbox_msg *m)
 	if (m->uri == NULL || m->uri[0] == 0)
 		folder = e_mail_local_get_folder (E_MAIL_FOLDER_INBOX);
 	else
-		folder = mail_tool_uri_to_folder(m->uri, CAMEL_STORE_FOLDER_CREATE, &m->base.ex);
+		folder = mail_tool_uri_to_folder(m->uri, CAMEL_STORE_FOLDER_CREATE,
+						 e_mail_msg_get_exception ((EMailMsg*) m));
 
 	if (folder == NULL)
 		return;
@@ -184,11 +192,12 @@ import_mbox_exec (struct _import_mbox_msg *m)
 				flags |= decode_status(tmp);
 
 			camel_message_info_set_flags(info, flags, ~0);
-			camel_folder_append_message(folder, msg, info, NULL, &m->base.ex);
+			camel_folder_append_message(folder, msg, info, NULL,
+						    e_mail_msg_get_exception ((EMailMsg*) m));
 			camel_message_info_free(info);
 			camel_object_unref(msg);
 
-			if (camel_exception_is_set(&m->base.ex))
+			if (e_mail_msg_exception_is_set((EMailMsg*) m))
 				break;
 
 			camel_mime_parser_step(mp, NULL, NULL);
@@ -208,36 +217,53 @@ fail1:
 }
 
 static void
-import_mbox_done (struct _import_mbox_msg *m)
+import_mbox_done (ImportMboxMsg *m)
 {
 	if (m->done)
-		m->done(m->done_data, &m->base.ex);
+		m->done(m->done_data, e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-import_mbox_free (struct _import_mbox_msg *m)
+import_mbox_msg_dispose (GObject *object)
 {
-	if (m->cancel)
+	ImportMboxMsg *m = (ImportMboxMsg*) object;
+
+	if (m->cancel) {
 		camel_operation_unref(m->cancel);
+		m->cancel = NULL;
+	}
 	g_free(m->uri);
+	m->uri = NULL;
 	g_free(m->path);
+	m->path = NULL;
+
+	G_OBJECT_CLASS (import_mbox_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo import_mbox_info = {
-	sizeof (struct _import_mbox_msg),
-	(MailMsgDescFunc) import_mbox_desc,
-	(MailMsgExecFunc) import_mbox_exec,
-	(MailMsgDoneFunc) import_mbox_done,
-	(MailMsgFreeFunc) import_mbox_free
-};
+static void
+import_mbox_msg_class_init (ImportMboxMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = import_mbox_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) import_mbox_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) import_mbox_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) import_mbox_done;
+}
+
+static void
+import_mbox_msg_init (ImportMboxMsg *msg)
+{
+}
 
 gint
 mail_importer_import_mbox(const gchar *path, const gchar *folderuri, CamelOperation *cancel, void (*done)(gpointer data, CamelException *), gpointer data)
 {
-	struct _import_mbox_msg *m;
+	ImportMboxMsg *m;
 	gint id;
 
-	m = mail_msg_new(&import_mbox_info);
+	m = g_object_new (import_mbox_msg_get_type (), NULL);
 	m->path = g_strdup(path);
 	m->uri = g_strdup(folderuri);
 	m->done = done;
@@ -247,8 +273,9 @@ mail_importer_import_mbox(const gchar *path, const gchar *folderuri, CamelOperat
 		camel_operation_ref(cancel);
 	}
 
-	id = m->base.seq;
-	mail_msg_fast_ordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_fast_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
@@ -256,9 +283,9 @@ mail_importer_import_mbox(const gchar *path, const gchar *folderuri, CamelOperat
 void
 mail_importer_import_mbox_sync(const gchar *path, const gchar *folderuri, CamelOperation *cancel)
 {
-	struct _import_mbox_msg *m;
+	ImportMboxMsg *m;
 
-	m = mail_msg_new(&import_mbox_info);
+	m = g_object_new (import_mbox_msg_get_type (), NULL);
 	m->path = g_strdup(path);
 	m->uri = g_strdup(folderuri);
 	if (cancel) {
@@ -268,7 +295,7 @@ mail_importer_import_mbox_sync(const gchar *path, const gchar *folderuri, CamelO
 
 	import_mbox_exec(m);
 	import_mbox_done(m);
-	mail_msg_unref(m);
+	g_object_unref (m);
 }
 
 struct _import_folders_data {
diff --git a/mail/importers/pine-importer.c b/mail/importers/pine-importer.c
index c3d4b15..c7c99d9 100644
--- a/mail/importers/pine-importer.c
+++ b/mail/importers/pine-importer.c
@@ -43,15 +43,17 @@
 
 #include <camel/camel-operation.h>
 
-#include "mail-importer.h"
-
+#include "mail/e-mail-task-manager.h"
 #include "mail/mail-mt.h"
 #include "e-util/e-import.h"
 
+#include "mail-importer.h"
+
 #define d(x)
 
+typedef struct _pine_import_msg PineImportMsg;
 struct _pine_import_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	EImport *import;
 	EImportTarget *target;
@@ -62,6 +64,12 @@ struct _pine_import_msg {
 	gint status_timeout_id;
 	CamelOperation *status;
 };
+typedef struct _PineImportMsgClass PineImportMsgClass;
+struct _PineImportMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType pine_import_msg_get_type ();
+G_DEFINE_TYPE (PineImportMsg, pine_import_msg, E_TYPE_MAIL_MSG);
 
 static gboolean
 pine_supported(EImport *ei, EImportTarget *target, EImportImporter *im)
@@ -219,7 +227,7 @@ import_contacts(void)
 }
 
 static gchar *
-pine_import_desc (struct _pine_import_msg *m)
+pine_import_desc (PineImportMsg *m)
 {
 	return g_strdup (_("Importing Pine data"));
 }
@@ -231,7 +239,7 @@ static MailImporterSpecial pine_special_folders[] = {
 };
 
 static void
-pine_import_exec(struct _pine_import_msg *m)
+pine_import_exec(PineImportMsg *m)
 {
 	if (GPOINTER_TO_INT(g_datalist_get_data(&m->target->data, "pine-do-addr")))
 		import_contacts();
@@ -246,11 +254,11 @@ pine_import_exec(struct _pine_import_msg *m)
 }
 
 static void
-pine_import_done(struct _pine_import_msg *m)
+pine_import_done(PineImportMsg *m)
 {
 	printf("importing complete\n");
 
-	if (!camel_exception_is_set(&m->base.ex)) {
+	if (!e_mail_msg_exception_is_set((EMailMsg*) m)) {
 		GConfClient *gconf;
 
 		gconf = gconf_client_get_default();
@@ -265,23 +273,40 @@ pine_import_done(struct _pine_import_msg *m)
 }
 
 static void
-pine_import_free(struct _pine_import_msg *m)
+pine_import_msg_dispose (GObject *object)
 {
-	camel_operation_unref(m->status);
+	PineImportMsg *m = (PineImportMsg*) object;
+
+	if (m->status) {
+		camel_operation_unref(m->status);
+		m->status = NULL;
+	}
 
 	g_free(m->status_what);
-	g_mutex_free(m->status_lock);
+	m->status_what = NULL;
+
+	if (m->status_lock) {
+		g_mutex_free(m->status_lock);
+		m->status_lock = NULL;
+	}
+
+	if (m->status_timeout_id > 0) {
+		g_source_remove(m->status_timeout_id);
+		m->status_timeout_id = 0;
+	}
 
-	g_source_remove(m->status_timeout_id);
-	m->status_timeout_id = 0;
+	if (m->import) {
+		g_object_unref(m->import);
+		m->import = NULL;
+	}
 
-	g_object_unref(m->import);
+	G_OBJECT_CLASS (pine_import_msg_parent_class)->dispose (object);
 }
 
 static void
 pine_status(CamelOperation *op, const gchar *what, gint pc, gpointer data)
 {
-	struct _pine_import_msg *importer = data;
+	PineImportMsg *importer = data;
 
 	if (pc == CAMEL_OPERATION_START)
 		pc = 0;
@@ -298,7 +323,7 @@ pine_status(CamelOperation *op, const gchar *what, gint pc, gpointer data)
 static gboolean
 pine_status_timeout(gpointer data)
 {
-	struct _pine_import_msg *importer = data;
+	PineImportMsg *importer = data;
 	gint pc;
 	gchar *what;
 
@@ -315,21 +340,30 @@ pine_status_timeout(gpointer data)
 	return TRUE;
 }
 
-static MailMsgInfo pine_import_info = {
-	sizeof (struct _pine_import_msg),
-	(MailMsgDescFunc) pine_import_desc,
-	(MailMsgExecFunc) pine_import_exec,
-	(MailMsgDoneFunc) pine_import_done,
-	(MailMsgFreeFunc) pine_import_free
-};
+static void
+pine_import_msg_class_init (PineImportMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = pine_import_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) pine_import_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) pine_import_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) pine_import_done;
+}
+
+static void
+pine_import_msg_init (PineImportMsg *msg)
+{
+}
 
 static gint
 mail_importer_pine_import(EImport *ei, EImportTarget *target)
 {
-	struct _pine_import_msg *m;
+	PineImportMsg *m;
 	gint id;
 
-	m = mail_msg_new(&pine_import_info);
+	m = g_object_new (pine_import_msg_get_type (), NULL);
 	g_datalist_set_data(&target->data, "pine-msg", m);
 	m->import = ei;
 	g_object_ref(m->import);
@@ -338,9 +372,10 @@ mail_importer_pine_import(EImport *ei, EImportTarget *target)
 	m->status_lock = g_mutex_new();
 	m->status = camel_operation_new(pine_status, m);
 
-	id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
 
-	mail_msg_fast_ordered_push (m);
+	e_mail_task_manager_fast_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
@@ -402,7 +437,7 @@ pine_import(EImport *ei, EImportTarget *target, EImportImporter *im)
 static void
 pine_cancel(EImport *ei, EImportTarget *target, EImportImporter *im)
 {
-	struct _pine_import_msg *m = g_datalist_get_data(&target->data, "pine-msg");
+	PineImportMsg *m = g_datalist_get_data(&target->data, "pine-msg");
 
 	if (m)
 		camel_operation_cancel(m->status);
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index 10a66a4..9094357 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -38,8 +38,8 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <glib/gstdio.h>
-
 #include <glib/gi18n.h>
+
 #include <camel/camel-store.h>
 #include <camel/camel-folder.h>
 #include <camel/camel-vtrash-folder.h>
@@ -48,18 +48,19 @@
 #include <camel/camel-disco-store.h>
 
 #include <libedataserver/e-data-server-util.h>
+
 #include "e-util/e-marshal.h"
 #include "e-util/e-util.h"
 
-#include "mail-mt.h"
+#include "e-mail-local.h"
+#include "e-mail-task-manager.h"
+#include "em-utils.h"
 #include "mail-folder-cache.h"
+#include "mail-mt.h"
 #include "mail-ops.h"
 #include "mail-session.h"
 #include "mail-tools.h"
 
-#include "em-utils.h"
-#include "e-mail-local.h"
-
 #define w(x)
 #define d(x)
 
@@ -834,7 +835,8 @@ mail_folder_cache_note_store_remove(MailFolderCache *self, CamelStore *store)
 			struct _update_data *ud = link->data;
 
 			d(printf("Cancelling outstanding folderinfo update %d\n", ud->id));
-			mail_msg_cancel(ud->id);
+			e_mail_task_manager_cancel_task (e_mail_task_manager_get_default (),
+							 ud->id);
 			ud->cancel = 1;
 
 			link = g_list_next (link);
@@ -878,11 +880,18 @@ update_folders(CamelStore *store, CamelFolderInfo *fi, gpointer data)
 	return res;
 }
 
+typedef struct _ping_store_msg PingStoreMsg;
 struct _ping_store_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelStore *store;
 };
+typedef struct _PingStoreMsgClass PingStoreMsgClass;
+struct _PingStoreMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType ping_store_msg_get_type ();
+G_DEFINE_TYPE (PingStoreMsg, ping_store_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
 ping_store_desc (struct _ping_store_msg *m)
@@ -910,37 +919,53 @@ ping_store_exec (struct _ping_store_msg *m)
 			online = TRUE;
 	}
 	if (online)
-		camel_store_noop (m->store, &m->base.ex);
+		camel_store_noop (m->store, e_mail_msg_get_exception ((EMailMsg*) m));
+}
+
+static void
+ping_store_free (GObject *object)
+{
+	PingStoreMsg *m = (PingStoreMsg*) object;
+	if (m->store) {
+		camel_object_unref (m->store);
+		m->store = NULL;
+	}
+
+	G_OBJECT_CLASS (ping_store_msg_parent_class)->dispose (object);
 }
 
 static void
-ping_store_free (struct _ping_store_msg *m)
+ping_store_msg_class_init (PingStoreMsgClass *klass)
 {
-	camel_object_unref (m->store);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = ping_store_free;
+
+	klass->parent_class.desc = (MailMsgDescFunc) ping_store_desc;
+	klass->parent_class.exec = (MailMsgExecFunc) ping_store_exec;
+	klass->parent_class.done = NULL;
 }
 
-static MailMsgInfo ping_store_info = {
-	sizeof (struct _ping_store_msg),
-	(MailMsgDescFunc) ping_store_desc,
-	(MailMsgExecFunc) ping_store_exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) ping_store_free
-};
+static void
+ping_store_msg_init (PingStoreMsg *msg)
+{
+}
 
 static void
 ping_store (gpointer key, gpointer val, gpointer user_data)
 {
 	CamelStore *store = (CamelStore *) key;
-	struct _ping_store_msg *m;
+	PingStoreMsg *m;
 
 	if (CAMEL_SERVICE (store)->status != CAMEL_SERVICE_CONNECTED)
 		return;
 
-	m = mail_msg_new (&ping_store_info);
+	m = g_object_new (ping_store_msg_get_type (), NULL);
 	m->store = store;
 	camel_object_ref (store);
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 static gboolean
@@ -991,7 +1016,7 @@ mail_folder_cache_note_store(MailFolderCache *self, CamelStore *store, CamelOper
 	gint hook = 0;
 
 	g_return_if_fail (CAMEL_IS_STORE(store));
-	g_return_if_fail (mail_in_main_thread());
+	g_return_if_fail (e_in_main_thread());
 
 	g_mutex_lock (self->priv->stores_mutex);
 
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index 69a1eab..69ab7bd 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -12,7 +12,11 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  *
+ * Authors:
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
+ *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  */
 
 #include <config.h>
@@ -33,7 +37,9 @@
 #include "shell/e-shell.h"
 #include "e-util/e-alert-activity.h"
 #include "e-util/e-alert-dialog.h"
+#include "e-util/e-util.h"
 
+#include "e-mail-task-manager.h"
 #include "mail-mt.h"
 
 /*#define MALLOC_CHECK*/
@@ -43,563 +49,29 @@
  *     to rework or get rid of the functions that use this. */
 const gchar *shell_builtin_backend = "mail";
 
-static void mail_operation_status(CamelOperation *op, const gchar *what, gint pc, gpointer data);
-
-enum
-{
-	ACTIVITY_STATE_UNINITIALIZED = 0,
-	ACTIVITY_STATE_INITIALIZING,
-	ACTIVITY_STATE_ACTIVE,
-	ACTIVITY_STATE_REMOVED
-};
-
-/* background operation status stuff */
-struct _MailMsgPrivate {
-	gint activity_state;	/* sigh sigh sigh, we need to keep track of the state external to the
-				   pointer itself for locking/race conditions */
-	EActivity *activity;
-	GtkWidget *error;
-	gboolean cancelable;
-};
-
-static guint mail_msg_seq; /* sequence number of each message */
-static GHashTable *mail_msg_active_table; /* table of active messages, must hold mail_msg_lock to access */
-static GMutex *mail_msg_lock;
-static GCond *mail_msg_cond;
-
 MailAsyncEvent *mail_async_event;
 
-gpointer
-mail_msg_new (MailMsgInfo *info)
-{
-	MailMsg *msg;
-
-	g_mutex_lock (mail_msg_lock);
-
-	msg = g_slice_alloc0 (info->size);
-	msg->info = info;
-	msg->ref_count = 1;
-	msg->seq = mail_msg_seq++;
-	msg->cancel = camel_operation_new(mail_operation_status, GINT_TO_POINTER(msg->seq));
-	camel_exception_init(&msg->ex);
-	msg->priv = g_slice_new0 (MailMsgPrivate);
-	msg->priv->cancelable = TRUE;
-	msg->priv->activity_state = ACTIVITY_STATE_UNINITIALIZED;
-
-	g_hash_table_insert(mail_msg_active_table, GINT_TO_POINTER(msg->seq), msg);
-
-	d(printf("New message %p\n", msg));
-
-	g_mutex_unlock (mail_msg_lock);
-
-	return msg;
-}
-
-static void
-end_event_callback (CamelObject *o, EActivity *activity, gpointer error)
-{
-	EShell *shell;
-	EShellBackend *shell_backend;
-
-	shell = e_shell_get_default ();
-	shell_backend = e_shell_get_backend_by_name (
-		shell, shell_builtin_backend);
-
-	if (activity != NULL) {
-		e_activity_complete (activity);
-		g_object_unref (activity);
-	}
-
-	if (error != NULL) {
-		activity = e_alert_activity_new_warning (error);
-		e_shell_backend_add_activity (shell_backend, activity);
-		g_object_unref (activity);
-	}
-}
-
-#ifdef MALLOC_CHECK
-#include <mcheck.h>
-
-static void
-checkmem(gpointer p)
-{
-	if (p) {
-		gint status = mprobe(p);
-
-		switch (status) {
-		case MCHECK_HEAD:
-			printf("Memory underrun at %p\n", p);
-			abort();
-		case MCHECK_TAIL:
-			printf("Memory overrun at %p\n", p);
-			abort();
-		case MCHECK_FREE:
-			printf("Double free %p\n", p);
-			abort();
-		}
-	}
-}
-#endif
-
-static void
-mail_msg_free (MailMsg *mail_msg)
-{
-	if (mail_msg->priv->activity != NULL)
-		g_object_unref (mail_msg->priv->activity);
-
-	if (mail_msg->cancel != NULL) {
-		camel_operation_mute (mail_msg->cancel);
-		camel_operation_unref (mail_msg->cancel);
-	}
-
-	camel_exception_clear (&mail_msg->ex);
-	g_slice_free (MailMsgPrivate, mail_msg->priv);
-	g_slice_free1 (mail_msg->info->size, mail_msg);
-}
-
-gpointer
-mail_msg_ref (gpointer msg)
-{
-	MailMsg *mail_msg = msg;
-
-	g_return_val_if_fail (mail_msg != NULL, msg);
-	g_return_val_if_fail (mail_msg->ref_count > 0, msg);
-
-	g_atomic_int_add (&mail_msg->ref_count, 1);
-	return msg;
-}
-
-void
-mail_msg_unref (gpointer msg)
-{
-	MailMsg *mail_msg = msg;
-	EActivity *activity = NULL;
-	GtkWidget *error = NULL;
-
-	g_return_if_fail (mail_msg != NULL);
-	g_return_if_fail (mail_msg->ref_count > 0);
-
-	if (g_atomic_int_exchange_and_add (&mail_msg->ref_count, -1) > 1)
-		return;
-
-#ifdef MALLOC_CHECK
-	checkmem(mail_msg);
-	checkmem(mail_msg->cancel);
-	checkmem(mail_msg->priv);
-#endif
-	d(printf("Free message %p\n", msg));
-
-	if (mail_msg->info->free)
-		mail_msg->info->free(mail_msg);
-
-	g_mutex_lock (mail_msg_lock);
-
-	g_hash_table_remove (
-		mail_msg_active_table, GINT_TO_POINTER (mail_msg->seq));
-	g_cond_broadcast (mail_msg_cond);
-
-	/* We need to make sure we dont lose a reference here YUCK YUCK */
-	/* This is tightly integrated with the code in op_status_exec,
-	   as it closely relates to the CamelOperation setup in mail_msg_new() above */
-	if (mail_msg->priv->activity_state == ACTIVITY_STATE_INITIALIZING) {
-		/* tell the other to free it itself */
-		mail_msg->priv->activity_state = ACTIVITY_STATE_REMOVED;
-		g_mutex_unlock (mail_msg_lock);
-		return;
-	} else {
-		activity = mail_msg->priv->activity;
-		if (activity != NULL)
-			g_object_ref (activity);
-		error = mail_msg->priv->error;
-	}
-
-	g_mutex_unlock (mail_msg_lock);
-
-	mail_msg_free (mail_msg);
-
-	if (activity != NULL)
-		mail_async_event_emit (
-			mail_async_event, MAIL_ASYNC_GUI,
-			(MailAsyncFunc) end_event_callback,
-			NULL, activity, error);
-}
-
-/* hash table of ops->dialogue of active errors */
-static GHashTable *active_errors = NULL;
-
-static void error_destroy(GtkObject *o, gpointer data)
-{
-	g_hash_table_remove(active_errors, data);
-}
-
-static void error_response(GtkObject *o, gint button, gpointer data)
-{
-	gtk_widget_destroy((GtkWidget *)o);
-}
-
-void
-mail_msg_check_error (gpointer msg)
-{
-	GtkWindow *parent;
-	MailMsg *m = msg;
-	gchar *what;
-	GtkDialog *gd;
-
-#ifdef MALLOC_CHECK
-	checkmem(m);
-	checkmem(m->cancel);
-	checkmem(m->priv);
-#endif
-
-	if (!camel_exception_is_set(&m->ex)
-	    || m->ex.id == CAMEL_EXCEPTION_USER_CANCEL
-	    || m->ex.id == CAMEL_EXCEPTION_FOLDER_INVALID_UID
-	    || (m->cancel && camel_operation_cancel_check (m->cancel)))
-		return;
-
-	if (active_errors == NULL)
-		active_errors = g_hash_table_new(NULL, NULL);
-
-	/* check to see if we have dialogue already running for this operation */
-	/* we key on the operation pointer, which is at least accurate enough
-	   for the operation type, although it could be on a different object. */
-	if (g_hash_table_lookup(active_errors, m->info)) {
-		g_message("Error occurred while existing dialogue active:\n%s", camel_exception_get_description(&m->ex));
-		return;
-	}
-
-	parent = e_shell_get_active_window (NULL);
-
-	if (m->info->desc
-	    && (what = m->info->desc (m))) {
-		gd = (GtkDialog *)e_alert_dialog_new_for_args (parent, "mail:async-error", what, camel_exception_get_description(&m->ex), NULL);
-		g_free(what);
-	} else
-		gd = (GtkDialog *)e_alert_dialog_new_for_args (parent, "mail:async-error-nodescribe", camel_exception_get_description(&m->ex), NULL);
-
-	g_hash_table_insert(active_errors, m->info, gd);
-	g_signal_connect(gd, "response", G_CALLBACK(error_response), m->info);
-	g_signal_connect(gd, "destroy", G_CALLBACK(error_destroy), m->info);
-	if (m->priv->cancelable)
-		m->priv->error = (GtkWidget *) gd;
-	else
-		gtk_widget_show((GtkWidget *)gd);
-
-}
-
-void mail_msg_cancel(guint msgid)
-{
-	MailMsg *m;
-
-	g_mutex_lock (mail_msg_lock);
-
-	m = g_hash_table_lookup(mail_msg_active_table, GINT_TO_POINTER(msgid));
-
-	if (m && m->cancel)
-		camel_operation_cancel(m->cancel);
-
-	g_mutex_unlock (mail_msg_lock);
-}
-
-/* waits for a message to be finished processing (freed)
-   the messageid is from MailMsg->seq */
-void mail_msg_wait(guint msgid)
-{
-	MailMsg *m;
-
-	if (mail_in_main_thread ()) {
-		g_mutex_lock (mail_msg_lock);
-		m = g_hash_table_lookup(mail_msg_active_table, GINT_TO_POINTER(msgid));
-		while (m) {
-			g_mutex_unlock (mail_msg_lock);
-			gtk_main_iteration();
-			g_mutex_lock (mail_msg_lock);
-			m = g_hash_table_lookup(mail_msg_active_table, GINT_TO_POINTER(msgid));
-		}
-		g_mutex_unlock (mail_msg_lock);
-	} else {
-		g_mutex_lock (mail_msg_lock);
-		m = g_hash_table_lookup(mail_msg_active_table, GINT_TO_POINTER(msgid));
-		while (m) {
-			g_cond_wait (mail_msg_cond, mail_msg_lock);
-			m = g_hash_table_lookup(mail_msg_active_table, GINT_TO_POINTER(msgid));
-		}
-		g_mutex_unlock (mail_msg_lock);
-	}
-}
-
-gint mail_msg_active(guint msgid)
-{
-	gint active;
-
-	g_mutex_lock (mail_msg_lock);
-	if (msgid == (guint)-1)
-		active = g_hash_table_size(mail_msg_active_table) > 0;
-	else
-		active = g_hash_table_lookup(mail_msg_active_table, GINT_TO_POINTER(msgid)) != NULL;
-	g_mutex_unlock (mail_msg_lock);
-
-	return active;
-}
-
-void mail_msg_wait_all(void)
-{
-	if (mail_in_main_thread ()) {
-		g_mutex_lock (mail_msg_lock);
-		while (g_hash_table_size(mail_msg_active_table) > 0) {
-			g_mutex_unlock (mail_msg_lock);
-			gtk_main_iteration();
-			g_mutex_lock (mail_msg_lock);
-		}
-		g_mutex_unlock (mail_msg_lock);
-	} else {
-		g_mutex_lock (mail_msg_lock);
-		while (g_hash_table_size(mail_msg_active_table) > 0) {
-			g_cond_wait (mail_msg_cond, mail_msg_lock);
-		}
-		g_mutex_unlock (mail_msg_lock);
-	}
-}
-
 /* **************************************** */
 
-static GHookList cancel_hook_list;
-
-GHook *
-mail_cancel_hook_add (GHookFunc func, gpointer data)
-{
-	GHook *hook;
-
-	g_mutex_lock (mail_msg_lock);
-
-	if (!cancel_hook_list.is_setup)
-		g_hook_list_init (&cancel_hook_list, sizeof (GHook));
-
-	hook = g_hook_alloc (&cancel_hook_list);
-	hook->func = func;
-	hook->data = data;
-
-	g_hook_append (&cancel_hook_list, hook);
-
-	g_mutex_unlock (mail_msg_lock);
-
-	return hook;
-}
-
-void
-mail_cancel_hook_remove (GHook *hook)
-{
-	g_mutex_lock (mail_msg_lock);
-
-	g_return_if_fail (cancel_hook_list.is_setup);
-	g_hook_destroy_link (&cancel_hook_list, hook);
-
-	g_mutex_unlock (mail_msg_lock);
-}
-
-void
-mail_cancel_all (void)
-{
-	camel_operation_cancel (NULL);
-
-	g_mutex_lock (mail_msg_lock);
-
-	if (cancel_hook_list.is_setup)
-		g_hook_list_invoke (&cancel_hook_list, FALSE);
-
-	g_mutex_unlock (mail_msg_lock);
-}
-
-void
-mail_msg_set_cancelable (gpointer msg, gboolean status)
-{
-	MailMsg *mail_msg = msg;
-
-	mail_msg->priv->cancelable = status;
-}
-
-static guint idle_source_id = 0;
-G_LOCK_DEFINE_STATIC (idle_source_id);
-static GAsyncQueue *main_loop_queue = NULL;
-static GAsyncQueue *msg_reply_queue = NULL;
-static GThread *main_thread = NULL;
-
-static gboolean
-mail_msg_idle_cb (void)
-{
-	MailMsg *msg;
-
-	g_return_val_if_fail (main_loop_queue != NULL, FALSE);
-	g_return_val_if_fail (msg_reply_queue != NULL, FALSE);
-
-	G_LOCK (idle_source_id);
-	idle_source_id = 0;
-	G_UNLOCK (idle_source_id);
-	/* check the main loop queue */
-	while ((msg = g_async_queue_try_pop (main_loop_queue)) != NULL) {
-		if (msg->info->exec != NULL)
-			msg->info->exec (msg);
-		if (msg->info->done != NULL)
-			msg->info->done (msg);
-		mail_msg_unref (msg);
-	}
-
-	/* check the reply queue */
-	while ((msg = g_async_queue_try_pop (msg_reply_queue)) != NULL) {
-		if (msg->info->done != NULL)
-			msg->info->done (msg);
-		mail_msg_check_error (msg);
-		mail_msg_unref (msg);
-	}
-	return FALSE;
-}
-
-static void
-mail_msg_proxy (MailMsg *msg)
-{
-	if (msg->info->desc != NULL && msg->cancel) {
-		gchar *text = msg->info->desc (msg);
-		camel_operation_register (msg->cancel);
-		camel_operation_start (msg->cancel, "%s", text);
-		g_free (text);
-	}
-
-	if (msg->info->exec != NULL)
-		msg->info->exec (msg);
-
-	if (msg->info->desc != NULL && msg->cancel) {
-		camel_operation_end (msg->cancel);
-		camel_operation_unregister (msg->cancel);
-	}
-
-	g_async_queue_push (msg_reply_queue, msg);
-
-	G_LOCK (idle_source_id);
-	if (idle_source_id == 0)
-		idle_source_id = g_idle_add (
-			(GSourceFunc) mail_msg_idle_cb, NULL);
-	G_UNLOCK (idle_source_id);
-}
-
 void
 mail_msg_cleanup (void)
 {
-	mail_msg_wait_all();
-
-	G_LOCK (idle_source_id);
-	if (idle_source_id != 0) {
-		GSource *source;
-
-		/* Cancel the idle source. */
-		source = g_main_context_find_source_by_id (
-			g_main_context_default (), idle_source_id);
-		g_source_destroy (source);
-		idle_source_id = 0;
-	}
-	G_UNLOCK (idle_source_id);
-
-	g_async_queue_unref (main_loop_queue);
-	main_loop_queue = NULL;
-
-	g_async_queue_unref (msg_reply_queue);
-	msg_reply_queue = NULL;
+	e_mail_task_manager_task_wait_all
+		(e_mail_task_manager_get_default ());
+	mail_async_event_destroy (mail_async_event);
 }
 
 void
 mail_msg_init (void)
 {
-	mail_msg_lock = g_mutex_new ();
-	mail_msg_cond = g_cond_new ();
-
-	main_loop_queue = g_async_queue_new ();
-	msg_reply_queue = g_async_queue_new ();
-
-	mail_msg_active_table = g_hash_table_new (NULL, NULL);
-	main_thread = g_thread_self ();
-
 	mail_async_event = mail_async_event_new ();
 }
 
-static gint
-mail_msg_compare (const MailMsg *msg1, const MailMsg *msg2)
-{
-	gint priority1 = msg1->priority;
-	gint priority2 = msg2->priority;
-
-	if (priority1 == priority2)
-		return 0;
-
-	return (priority1 < priority2) ? 1 : -1;
-}
-
-static gpointer
-create_thread_pool (gpointer data)
-{
-	GThreadPool *thread_pool;
-	gint max_threads = GPOINTER_TO_INT (data);
-
-	/* once created, run forever */
-	thread_pool = g_thread_pool_new (
-		(GFunc) mail_msg_proxy, NULL, max_threads, FALSE, NULL);
-	g_thread_pool_set_sort_function (
-		thread_pool, (GCompareDataFunc) mail_msg_compare, NULL);
-
-	return thread_pool;
-}
-
-void
-mail_msg_main_loop_push (gpointer msg)
-{
-	g_async_queue_push_sorted (main_loop_queue, msg,
-		(GCompareDataFunc) mail_msg_compare, NULL);
-
-	G_LOCK (idle_source_id);
-	if (idle_source_id == 0)
-		idle_source_id = g_idle_add (
-			(GSourceFunc) mail_msg_idle_cb, NULL);
-	G_UNLOCK (idle_source_id);
-}
-
-void
-mail_msg_unordered_push (gpointer msg)
-{
-	static GOnce once = G_ONCE_INIT;
-
-	g_once (&once, (GThreadFunc) create_thread_pool, GINT_TO_POINTER (10));
-
-	g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
-}
-
-void
-mail_msg_fast_ordered_push (gpointer msg)
-{
-	static GOnce once = G_ONCE_INIT;
-
-	g_once (&once, (GThreadFunc) create_thread_pool, GINT_TO_POINTER (1));
-
-	g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
-}
-
-void
-mail_msg_slow_ordered_push (gpointer msg)
-{
-	static GOnce once = G_ONCE_INIT;
-
-	g_once (&once, (GThreadFunc) create_thread_pool, GINT_TO_POINTER (1));
-
-	g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
-}
-
-gboolean
-mail_in_main_thread (void)
-{
-	return (g_thread_self () == main_thread);
-}
-
 /* ********************************************************************** */
 
+typedef struct _proxy_msg ProxyMsg;
 struct _proxy_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	MailAsyncEvent *ea;
 	mail_async_event_t type;
@@ -611,9 +83,17 @@ struct _proxy_msg {
 	gpointer event_data;
 	gpointer data;
 };
+typedef struct _ProxyMsgClass ProxyMsgClass;
+struct _ProxyMsgClass {
+	EMailMsgClass parent_class;
+};
+GType proxy_msg_get_type (void);
+G_DEFINE_TYPE (ProxyMsg, proxy_msg, E_TYPE_MAIL_MSG)
+#define PROXY_MSG(obj) \
+		G_TYPE_CHECK_INSTANCE_CAST ((obj), proxy_msg_get_type (), ProxyMsg)
 
 static void
-do_async_event(struct _proxy_msg *m)
+do_async_event(ProxyMsg *m)
 {
 	m->thread = g_thread_self ();
 	m->func(m->o, m->event_data, m->data);
@@ -624,23 +104,28 @@ do_async_event(struct _proxy_msg *m)
 	g_mutex_unlock(m->ea->lock);
 }
 
+static void
+proxy_msg_class_init (ProxyMsgClass *klass)
+{
+	klass->parent_class.desc = NULL;
+	klass->parent_class.exec = (MailMsgExecFunc) do_async_event;
+	klass->parent_class.done = NULL;
+}
+
+static void
+proxy_msg_init (ProxyMsg *msg)
+{
+}
+
 static gint
-idle_async_event(gpointer mm)
+idle_async_event(gpointer data)
 {
-	do_async_event(mm);
-	mail_msg_unref(mm);
+	do_async_event(PROXY_MSG (data));
+	g_object_unref(data);
 
 	return FALSE;
 }
 
-static MailMsgInfo async_event_info = {
-	sizeof (struct _proxy_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) do_async_event,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) NULL
-};
-
 MailAsyncEvent *mail_async_event_new(void)
 {
 	MailAsyncEvent *ea;
@@ -653,11 +138,10 @@ MailAsyncEvent *mail_async_event_new(void)
 
 gint mail_async_event_emit(MailAsyncEvent *ea, mail_async_event_t type, MailAsyncFunc func, gpointer o, gpointer event_data, gpointer data)
 {
-	struct _proxy_msg *m;
-	gint id;
+	ProxyMsg *m;
 
 	/* we dont have a reply port for this, we dont care when/if it gets executed, just queue it */
-	m = mail_msg_new(&async_event_info);
+	m = g_object_new (proxy_msg_get_type (), NULL);
 	m->func = func;
 	m->o = o;
 	m->event_data = event_data;
@@ -666,33 +150,33 @@ gint mail_async_event_emit(MailAsyncEvent *ea, mail_async_event_t type, MailAsyn
 	m->type = type;
 	m->thread = NULL;
 
-	id = m->base.seq;
 	g_mutex_lock(ea->lock);
 	ea->tasks = g_slist_prepend(ea->tasks, m);
 	g_mutex_unlock(ea->lock);
 
-	/* We use an idle function instead of our own message port only because the
-	   gui message ports's notification buffer might overflow and deadlock us */
 	if (type == MAIL_ASYNC_GUI) {
-		if (mail_in_main_thread ())
+		if (e_in_main_thread ()) {
 			g_idle_add(idle_async_event, m);
-		else
-			mail_msg_main_loop_push(m);
+		} else {
+			e_mail_task_manager_main_loop_push
+				(e_mail_task_manager_get_default (), (EMailMsg*) m);
+		}
 	} else
-		mail_msg_fast_ordered_push (m);
+		e_mail_task_manager_fast_ordered_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
-	return id;
+	return e_mail_msg_get_id ((EMailMsg*) m);
 }
 
 gint mail_async_event_destroy(MailAsyncEvent *ea)
 {
 	gint id;
-	struct _proxy_msg *m;
+	ProxyMsg *m;
 
 	g_mutex_lock(ea->lock);
 	while (ea->tasks) {
 		m = ea->tasks->data;
-		id = m->base.seq;
+		id = e_mail_msg_get_id ((EMailMsg*) m);
 		if (m->thread == g_thread_self ()) {
 			g_warning("Destroying async event from inside an event, returning EDEADLK");
 			g_mutex_unlock(ea->lock);
@@ -700,7 +184,8 @@ gint mail_async_event_destroy(MailAsyncEvent *ea)
 			return -1;
 		}
 		g_mutex_unlock(ea->lock);
-		mail_msg_wait(id);
+		e_mail_task_manager_task_wait
+			(e_mail_task_manager_get_default (), id);
 		g_mutex_lock(ea->lock);
 	}
 	g_mutex_unlock(ea->lock);
@@ -713,8 +198,9 @@ gint mail_async_event_destroy(MailAsyncEvent *ea)
 
 /* ********************************************************************** */
 
+typedef struct _call_msg CallMsg;
 struct _call_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	mail_call_t type;
 	MailMainFunc func;
@@ -722,9 +208,15 @@ struct _call_msg {
 	va_list ap;
 	EFlag *done;
 };
+typedef struct _CallMsgClass CallMsgClass;
+struct _CallMsgClass {
+	EMailMsgClass parent_class;
+};
+GType call_msg_get_type (void);
+G_DEFINE_TYPE (CallMsg, call_msg, E_TYPE_MAIL_MSG)
 
 static void
-do_call(struct _call_msg *m)
+do_call(CallMsg *m)
 {
 	gpointer p1, *p2, *p3, *p4, *p5;
 	gint i1;
@@ -778,34 +270,40 @@ do_call(struct _call_msg *m)
 		e_flag_set (m->done);
 }
 
-static MailMsgInfo mail_call_info = {
-	sizeof (struct _call_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) do_call,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) NULL
-};
+static void
+call_msg_class_init (CallMsgClass *klass)
+{
+	klass->parent_class.desc = NULL;
+	klass->parent_class.exec = (MailMsgExecFunc) do_call;
+	klass->parent_class.done = NULL;
+}
+
+static void
+call_msg_init (CallMsg *msg)
+{
+}
 
 gpointer
 mail_call_main (mail_call_t type, MailMainFunc func, ...)
 {
-	struct _call_msg *m;
+	CallMsg *m;
 	gpointer ret;
 	va_list ap;
 
 	va_start(ap, func);
 
-	m = mail_msg_new (&mail_call_info);
+	m = g_object_new (call_msg_get_type (), NULL);
 	m->type = type;
 	m->func = func;
 	G_VA_COPY(m->ap, ap);
 
-	if (mail_in_main_thread ())
+	if (e_in_main_thread ())
 		do_call (m);
 	else {
-		mail_msg_ref (m);
+		g_object_ref (m);
 		m->done = e_flag_new ();
-		mail_msg_main_loop_push (m);
+		e_mail_task_manager_main_loop_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) m);
 		e_flag_wait (m->done);
 		e_flag_free (m->done);
 	}
@@ -813,165 +311,13 @@ mail_call_main (mail_call_t type, MailMainFunc func, ...)
 	va_end(ap);
 
 	ret = m->ret;
-	mail_msg_unref (m);
+	g_object_unref (m);
 
 	return ret;
 }
 
 /* ******************************************************************************** */
 
-struct _op_status_msg {
-	MailMsg base;
-
-	CamelOperation *op;
-	gchar *what;
-	gint pc;
-	gpointer data;
-};
-
-static void
-op_cancelled_cb (EActivity *activity,
-                 gpointer user_data)
-{
-	mail_msg_cancel (GPOINTER_TO_UINT (user_data));
-}
-
-static void
-op_status_exec (struct _op_status_msg *m)
-{
-	EShell *shell;
-	EShellBackend *shell_backend;
-	MailMsg *msg;
-	MailMsgPrivate *data;
-	gchar *out, *p, *o, c;
-	gint pc;
-
-	g_return_if_fail (mail_in_main_thread ());
-
-	shell = e_shell_get_default ();
-	shell_backend = e_shell_get_backend_by_name (
-		shell, shell_builtin_backend);
-
-	g_mutex_lock (mail_msg_lock);
-
-	msg = g_hash_table_lookup (mail_msg_active_table, m->data);
-
-	if (msg == NULL) {
-		g_mutex_unlock (mail_msg_lock);
-		return;
-	}
-
-	data = msg->priv;
-
-	out = g_alloca (strlen (m->what) * 2 + 1);
-	o = out;
-	p = m->what;
-	while ((c = *p++)) {
-		if (c == '%')
-			*o++ = '%';
-		*o++ = c;
-	}
-	*o = 0;
-
-	pc = m->pc;
-
-	if (data->activity == NULL) {
-		gchar *what;
-
-		/* its being created/removed?  well leave it be */
-		if (data->activity_state == ACTIVITY_STATE_INITIALIZING ||
-		    data->activity_state == ACTIVITY_STATE_REMOVED) {
-			g_mutex_unlock (mail_msg_lock);
-			return;
-		} else {
-			data->activity_state = ACTIVITY_STATE_INITIALIZING;
-
-			g_mutex_unlock (mail_msg_lock);
-			if (msg->info->desc)
-				what = msg->info->desc (msg);
-			else if (m->what)
-				what = g_strdup (m->what);
-			/* uncommenting because message is not very useful for a user, see bug 271734*/
-			else {
-				what = g_strdup("");
-			}
-
-			data->activity = e_activity_new (what);
-			e_activity_set_allow_cancel (data->activity, TRUE);
-			e_activity_set_percent (data->activity, 0.0);
-			e_shell_backend_add_activity (shell_backend, data->activity);
-
-			g_signal_connect (
-				data->activity, "cancelled",
-				G_CALLBACK (op_cancelled_cb),
-				GUINT_TO_POINTER (msg->seq));
-
-			g_free (what);
-			g_mutex_lock (mail_msg_lock);
-			if (data->activity_state == ACTIVITY_STATE_REMOVED) {
-				EActivity *activity;
-
-				activity = g_object_ref (data->activity);
-
-				g_mutex_unlock (mail_msg_lock);
-				mail_msg_free (msg);
-
-				if (activity != 0)
-					mail_async_event_emit (
-						mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback,
-								NULL, activity, NULL);
-			} else {
-				data->activity_state = ACTIVITY_STATE_ACTIVE;
-				g_mutex_unlock (mail_msg_lock);
-			}
-			return;
-		}
-	} else if (data->activity != NULL) {
-		g_mutex_unlock (mail_msg_lock);
-		e_activity_set_primary_text (data->activity, out);
-		e_activity_set_percent (data->activity, pc / 100.0);
-	} else {
-		g_mutex_unlock (mail_msg_lock);
-	}
-}
-
-static void
-op_status_free (struct _op_status_msg *m)
-{
-	g_free (m->what);
-}
-
-static MailMsgInfo op_status_info = {
-	sizeof (struct _op_status_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) op_status_exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) op_status_free
-};
-
-static void
-mail_operation_status (CamelOperation *op, const gchar *what, gint pc, gpointer data)
-{
-	struct _op_status_msg *m;
-
-	d(printf("got operation statys: %s %d%%\n", what, pc));
-
-	m = mail_msg_new(&op_status_info);
-	m->op = op;
-	m->what = g_strdup(what);
-	switch (pc) {
-	case CAMEL_OPERATION_START:
-		pc = 0;
-		break;
-	case CAMEL_OPERATION_END:
-		pc = 100;
-		break;
-	}
-	m->pc = pc;
-	m->data = data;
-	mail_msg_main_loop_push(m);
-}
-
 void
 mail_mt_set_backend (gchar *backend)
 {
diff --git a/mail/mail-mt.h b/mail/mail-mt.h
index f9e6049..0b59a9d 100644
--- a/mail/mail-mt.h
+++ b/mail/mail-mt.h
@@ -14,9 +14,11 @@
  *
  *
  * Authors:
- *		Michael Zucchi <notzed ximian com>
+ *   Michael Zucchi <notzed ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Coporation
  *
  */
 
@@ -26,62 +28,9 @@
 #include "camel/camel-exception.h"
 #include "camel/camel-operation.h"
 
-typedef struct _MailMsg MailMsg;
-typedef struct _MailMsgInfo MailMsgInfo;
-typedef struct _MailMsgPrivate MailMsgPrivate;
-
-typedef gchar *	(*MailMsgDescFunc)	(MailMsg *msg);
-typedef void	(*MailMsgExecFunc)	(MailMsg *msg);
-typedef void	(*MailMsgDoneFunc)	(MailMsg *msg);
-typedef void	(*MailMsgFreeFunc)	(MailMsg *msg);
-typedef void	(*MailMsgDispatchFunc)	(gpointer msg);
-
-struct _MailMsg {
-	MailMsgInfo *info;
-	volatile gint ref_count;
-	guint seq;	/* seq number for synchronisation */
-	gint priority;		/* priority (default = 0) */
-	CamelOperation *cancel;	/* a cancellation/status handle */
-	CamelException ex;	/* an initialised camel exception, upto the caller to use this */
-	MailMsgPrivate *priv;
-};
-
-struct _MailMsgInfo {
-	gsize size;
-	MailMsgDescFunc desc;
-	MailMsgExecFunc exec;
-	MailMsgDoneFunc done;
-	MailMsgFreeFunc free;
-};
-
-/* setup ports */
 void mail_msg_init(void);
 void mail_msg_cleanup (void);
 
-gboolean mail_in_main_thread (void);
-
-/* allocate a new message */
-gpointer mail_msg_new (MailMsgInfo *info);
-gpointer mail_msg_ref (gpointer msg);
-void mail_msg_unref (gpointer msg);
-void mail_msg_check_error (gpointer msg);
-void mail_msg_cancel(guint msgid);
-void mail_msg_wait(guint msgid);
-void mail_msg_wait_all(void);
-gint mail_msg_active(guint msgid);
-
-/* dispatch a message */
-void mail_msg_main_loop_push (gpointer msg);
-void mail_msg_unordered_push (gpointer msg);
-void mail_msg_fast_ordered_push (gpointer msg);
-void mail_msg_slow_ordered_push (gpointer msg);
-
-/* To implement the stop button */
-GHook * mail_cancel_hook_add (GHookFunc func, gpointer data);
-void mail_cancel_hook_remove (GHook *hook);
-void mail_cancel_all (void);
-void mail_msg_set_cancelable (gpointer msg, gboolean status);
-
 /* asynchronous event proxies */
 typedef struct _MailAsyncEvent {
 	GMutex *lock;
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 73ad926..63d42c3 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -20,8 +20,10 @@
  *      Jeffrey Stedfast <fejj ximian com>
  *      Peter Williams <peterw ximian com>
  *      Michael Zucchi <notzed ximian com>
+ *      Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -47,6 +49,8 @@
 #include <libedataserver/e-data-server-util.h>
 #include "e-util/e-account-utils.h"
 
+#include "e-mail-local.h"
+#include "e-mail-task-manager.h"
 #include "em-filter-rule.h"
 #include "em-utils.h"
 #include "mail-mt.h"
@@ -54,8 +58,6 @@
 #include "mail-session.h"
 #include "mail-tools.h"
 
-#include "e-mail-local.h"
-
 #define w(x)
 #define d(x)
 
@@ -64,8 +66,9 @@ const gchar *x_mailer = "Evolution " VERSION SUB_VERSION " " VERSION_COMMENT;
 
 /* used for both just filtering a folder + uid's, and for filtering a whole folder */
 /* used both for fetching mail, and for filtering mail */
+typedef struct _filter_mail_msg FilterMailMsg;
 struct _filter_mail_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *source_folder; /* where they come from */
 	GPtrArray *source_uids;	/* uids to copy, or NULL == copy all */
@@ -75,10 +78,17 @@ struct _filter_mail_msg {
 	gint delete;		/* delete messages after filtering them? */
 	CamelFolder *destination; /* default destination for any messages, NULL for none */
 };
+typedef struct _FilterMailMsgClass FilterMailMsgClass;
+struct _FilterMailMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType filter_mail_msg_get_type ();
+G_DEFINE_TYPE (FilterMailMsg, filter_mail_msg, E_TYPE_MAIL_MSG);
 
 /* since fetching also filters, we subclass the data here */
+typedef struct _fetch_mail_msg FetchMailMsg;
 struct _fetch_mail_msg {
-	struct _filter_mail_msg fmsg;
+	FilterMailMsg fmsg;
 
 	CamelOperation *cancel;	/* we have our own cancellation struct, the other should be empty */
 	gint keep;		/* keep on server? */
@@ -88,9 +98,15 @@ struct _fetch_mail_msg {
 	void (*done)(const gchar *source, gpointer data);
 	gpointer data;
 };
+typedef struct _FetchMailMsgClass FetchMailMsgClass;
+struct _FetchMailMsgClass {
+	FilterMailMsg parent_class;
+};
+static GType fetch_mail_msg_get_type ();
+G_DEFINE_TYPE (FetchMailMsg, fetch_mail_msg, filter_mail_msg_get_type ());
 
 static gchar *
-em_filter_folder_element_desc (struct _filter_mail_msg *m)
+em_filter_folder_element_desc (FilterMailMsg *m)
 {
 	return g_strdup (_("Filtering Selected Messages"));
 }
@@ -98,7 +114,7 @@ em_filter_folder_element_desc (struct _filter_mail_msg *m)
 /* filter a folder, or a subset thereof, uses source_folder/source_uids */
 /* this is shared with fetch_mail */
 static void
-em_filter_folder_element_exec (struct _filter_mail_msg *m)
+em_filter_folder_element_exec (FilterMailMsg *m)
 {
 	CamelFolder *folder;
 	GPtrArray *uids, *folder_uids = NULL;
@@ -126,15 +142,20 @@ em_filter_folder_element_exec (struct _filter_mail_msg *m)
 	else
 		folder_uids = uids = camel_folder_get_uids (folder);
 
-	camel_filter_driver_filter_folder (m->driver, folder, m->cache, uids, m->delete, &m->base.ex);
-	camel_filter_driver_flush (m->driver, &m->base.ex);
+	camel_filter_driver_filter_folder (m->driver, folder, m->cache, uids,
+					   m->delete,
+					   e_mail_msg_get_exception ((EMailMsg*) m));
+	camel_filter_driver_flush (m->driver,
+				   e_mail_msg_get_exception ((EMailMsg*) m));
 
 	if (folder_uids)
 		camel_folder_free_uids (folder, folder_uids);
 
 	/* sync our source folder */
 	if (!m->cache)
-		camel_folder_sync (folder, FALSE, camel_exception_is_set (&m->base.ex) ? NULL : &m->base.ex);
+		camel_folder_sync (folder, FALSE,
+				   e_mail_msg_exception_is_set ((EMailMsg*) m) ?
+				   NULL : e_mail_msg_get_exception ((EMailMsg*) m));
 	camel_folder_thaw (folder);
 
 	if (m->destination)
@@ -145,52 +166,82 @@ em_filter_folder_element_exec (struct _filter_mail_msg *m)
 	camel_object_unref(m->driver);
 	m->driver = NULL;
 
-	if (m->cancel)
-		camel_operation_unregister (m->cancel);
+	if (e_mail_msg_get_operation ((EMailMsg*) m))
+		camel_operation_unregister (e_mail_msg_get_operation ((EMailMsg*) m));
 }
 
 static void
-em_filter_folder_element_done (struct _filter_mail_msg *m)
+em_filter_folder_element_done (FilterMailMsg *m)
 {
 }
 
 static void
-em_filter_folder_element_free (struct _filter_mail_msg *m)
+em_filter_folder_element_dispose (GObject *object)
 {
-	if (m->source_folder)
+	FilterMailMsg *m = (FilterMailMsg *) object;
+
+	if (m->source_folder) {
 		camel_object_unref (m->source_folder);
+		m->source_folder = NULL;
+	}
 
-	if (m->source_uids)
+	if (m->source_uids) {
 		em_utils_uids_free (m->source_uids);
+		m->source_uids = NULL;
+	}
 
-	if (m->cancel)
+	if (m->cancel) {
 		camel_operation_unref (m->cancel);
+		m->cancel = NULL;
+	}
 
-	if (m->destination)
+	if (m->destination) {
 		camel_object_unref (m->destination);
+		m->destination = NULL;
+	}
 
-	if (m->driver)
+	if (m->driver) {
 		camel_object_unref (m->driver);
+		m->driver = NULL;
+	}
+
+	G_OBJECT_CLASS (filter_mail_msg_parent_class)->dispose (object);
+}
 
+static void
+em_filter_folder_element_finalize (GObject *object)
+{
 	mail_session_flush_filter_log ();
+
+	G_OBJECT_CLASS (filter_mail_msg_parent_class)->finalize (object);
 }
 
-static MailMsgInfo em_filter_folder_element_info = {
-	sizeof (struct _filter_mail_msg),
-	(MailMsgDescFunc) em_filter_folder_element_desc,  /* we do our own progress reporting? */
-	(MailMsgExecFunc) em_filter_folder_element_exec,
-	(MailMsgDoneFunc) em_filter_folder_element_done,
-	(MailMsgFreeFunc) em_filter_folder_element_free
-};
+static void
+filter_mail_msg_class_init (FilterMailMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = em_filter_folder_element_dispose;
+	object_class->finalize = em_filter_folder_element_finalize;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) em_filter_folder_element_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) em_filter_folder_element_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) em_filter_folder_element_done;
+}
+
+static void
+filter_mail_msg_init (FilterMailMsg *msg)
+{
+}
 
 void
 mail_filter_folder (CamelFolder *source_folder, GPtrArray *uids,
 		    const gchar *type, gboolean notify,
 		    CamelOperation *cancel)
 {
-	struct _filter_mail_msg *m;
+	FilterMailMsg *m;
 
-	m = mail_msg_new (&em_filter_folder_element_info);
+	m = g_object_new (filter_mail_msg_get_type (), NULL);
 	m->source_folder = source_folder;
 	camel_object_ref (source_folder);
 	m->source_uids = uids;
@@ -209,7 +260,8 @@ mail_filter_folder (CamelFolder *source_folder, GPtrArray *uids,
 		camel_filter_driver_remove_rule_by_name (m->driver, "new-mail-notification");
 	}
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* convenience functions for it */
@@ -249,15 +301,15 @@ uid_cachename_hack (CamelStore *store)
 }
 
 static gchar *
-fetch_mail_desc (struct _fetch_mail_msg *m)
+fetch_mail_desc (FetchMailMsg *m)
 {
 	return g_strdup (_("Fetching Mail"));
 }
 
 static void
-fetch_mail_exec (struct _fetch_mail_msg *m)
+fetch_mail_exec (FetchMailMsg *m)
 {
-	struct _filter_mail_msg *fm = (struct _filter_mail_msg *)m;
+	FilterMailMsg *fm = (FilterMailMsg *)m;
 	gint i;
 
 	if (m->cancel)
@@ -271,20 +323,24 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 	/* 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)) {
-		gchar *path = mail_tool_do_movemail (m->source_uri, &fm->base.ex);
+		gchar *path = mail_tool_do_movemail (m->source_uri,
+						     e_mail_msg_get_exception ((EMailMsg*) m));
 
-		if (path && !camel_exception_is_set (&fm->base.ex)) {
+		if (path && !e_mail_msg_exception_is_set ((EMailMsg*) m)) {
 			camel_folder_freeze (fm->destination);
 			camel_filter_driver_set_default_folder (fm->driver, fm->destination);
-			camel_filter_driver_filter_mbox (fm->driver, path, m->source_uri, &fm->base.ex);
+			camel_filter_driver_filter_mbox (fm->driver, path, m->source_uri,
+							 e_mail_msg_get_exception ((EMailMsg*) m));
 			camel_folder_thaw (fm->destination);
 
-			if (!camel_exception_is_set (&fm->base.ex))
+			if (!e_mail_msg_exception_is_set ((EMailMsg*) m))
 				g_unlink (path);
 		}
 		g_free (path);
 	} else {
-		CamelFolder *folder = fm->source_folder = mail_tool_get_inbox (m->source_uri, &fm->base.ex);
+		CamelFolder *folder = fm->source_folder =
+			mail_tool_get_inbox (m->source_uri,
+					     e_mail_msg_get_exception ((EMailMsg*) m));
 
 		if (folder) {
 			/* this handles 'keep on server' stuff, if we have any new uid's to copy
@@ -313,14 +369,14 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 					em_filter_folder_element_exec (fm);
 
 					/* need to uncancel so writes/etc. don't fail */
-					if (fm->base.ex.id == CAMEL_EXCEPTION_USER_CANCEL)
+					if (e_mail_msg_get_exception ((EMailMsg*) m)->id == CAMEL_EXCEPTION_USER_CANCEL)
 						camel_operation_uncancel(NULL);
 
 					/* save the cache of uids that we've just downloaded */
 					camel_uid_cache_save (cache);
 				}
 
-				if (fm->delete && !camel_exception_is_set (&fm->base.ex)) {
+				if (fm->delete && !e_mail_msg_exception_is_set ((EMailMsg*) m)) {
 					/* not keep on server - just delete all the actual messages on the server */
 					for (i=0;i<folder_uids->len;i++) {
 						d(printf("force delete uid '%s'\n", (gchar *)folder_uids->pdata[i]));
@@ -328,7 +384,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 					}
 				}
 
-				if ((fm->delete || cache_uids) && !camel_exception_is_set (&fm->base.ex)) {
+				if ((fm->delete || cache_uids) && !e_mail_msg_exception_is_set ((EMailMsg*) m)) {
 					/* expunge messages (downloaded so far) */
 					camel_folder_sync(folder, fm->delete, NULL);
 				}
@@ -360,29 +416,44 @@ fail:
 }
 
 static void
-fetch_mail_done (struct _fetch_mail_msg *m)
+fetch_mail_done (FetchMailMsg *m)
 {
 	if (m->done)
 		m->done (m->source_uri, m->data);
 }
 
 static void
-fetch_mail_free (struct _fetch_mail_msg *m)
+fetch_mail_msg_dispose (GObject *object)
 {
+	FetchMailMsg *m = (FetchMailMsg*) object;
+
 	g_free (m->source_uri);
-	if (m->cancel)
+	m->source_uri = NULL;
+
+	if (m->cancel) {
 		camel_operation_unref (m->cancel);
+		m->cancel = NULL;
+	}
 
-	em_filter_folder_element_free ((struct _filter_mail_msg *) m);
+	G_OBJECT_CLASS (fetch_mail_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo fetch_mail_info = {
-	sizeof (struct _fetch_mail_msg),
-	(MailMsgDescFunc) fetch_mail_desc,
-	(MailMsgExecFunc) fetch_mail_exec,
-	(MailMsgDoneFunc) fetch_mail_done,
-	(MailMsgFreeFunc) fetch_mail_free
-};
+static void
+fetch_mail_msg_class_init (FetchMailMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = fetch_mail_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) fetch_mail_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) fetch_mail_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) fetch_mail_done;
+}
+
+static void
+fetch_mail_msg_init (FetchMailMsg *msg)
+{
+}
 
 /* ouch, a 'do everything' interface ... */
 void
@@ -391,11 +462,11 @@ mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperati
 		 CamelFilterStatusFunc *status, gpointer status_data,
 		 void (*done)(const gchar *source, gpointer data), gpointer data)
 {
-	struct _fetch_mail_msg *m;
-	struct _filter_mail_msg *fm;
+	FetchMailMsg *m;
+	FilterMailMsg *fm;
 
-	m = mail_msg_new (&fetch_mail_info);
-	fm = (struct _filter_mail_msg *)m;
+	m = g_object_new (fetch_mail_msg_get_type (), NULL);
+	fm = (FilterMailMsg *)m;
 	m->source_uri = g_strdup (source);
 	fm->delete = !keep;
 	fm->cache = NULL;
@@ -411,7 +482,8 @@ mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperati
 	if (status)
 		camel_filter_driver_set_status_func (fm->driver, status, status_data);
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 static gchar *
@@ -676,8 +748,9 @@ exit:
 
 /* ** SEND MAIL QUEUE ***************************************************** */
 
+typedef struct _send_queue_msg SendQueueMsg;
 struct _send_queue_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *queue;
 	gchar *destination;
@@ -692,9 +765,15 @@ struct _send_queue_msg {
 	void (*done)(const gchar *destination, gpointer data);
 	gpointer data;
 };
+typedef struct _SendQueueMsgClass SendQueueMsgClass;
+struct _SendQueueMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType send_queue_msg_get_type ();
+G_DEFINE_TYPE (SendQueueMsg, send_queue_msg, E_TYPE_MAIL_MSG);
 
 static void
-report_status (struct _send_queue_msg *m, enum camel_filter_status_t status, gint pc, const gchar *desc, ...)
+report_status (SendQueueMsg *m, enum camel_filter_status_t status, gint pc, const gchar *desc, ...)
 {
 	va_list ap;
 	gchar *str;
@@ -709,7 +788,7 @@ report_status (struct _send_queue_msg *m, enum camel_filter_status_t status, gin
 }
 
 static void
-send_queue_exec (struct _send_queue_msg *m)
+send_queue_exec (SendQueueMsg *m)
 {
 	CamelFolder *sent_folder;
 	GPtrArray *uids, *send_uids = NULL;
@@ -746,7 +825,7 @@ send_queue_exec (struct _send_queue_msg *m)
 	if (m->cancel)
 		camel_operation_register (m->cancel);
 	else
-		camel_operation_register (m->base.cancel);
+		camel_operation_register (e_mail_msg_get_operation ((EMailMsg*) m));
 
 	if (!m->cancel)
 		camel_operation_start (NULL, _("Sending message"));
@@ -765,19 +844,22 @@ send_queue_exec (struct _send_queue_msg *m)
 
 		mail_send_message (m, m->queue, send_uids->pdata[i], m->destination, m->driver, &ex);
 		if (camel_exception_is_set (&ex)) {
+			CamelException *base_exception = e_mail_msg_get_exception ((EMailMsg*) m);
 			if (ex.id != CAMEL_EXCEPTION_USER_CANCEL) {
 				/* merge exceptions into one */
-				if (camel_exception_is_set (&m->base.ex))
-					camel_exception_setv (&m->base.ex, CAMEL_EXCEPTION_SYSTEM, "%s\n\n%s", m->base.ex.desc, ex.desc);
+				if (e_mail_msg_exception_is_set ((EMailMsg*) m))
+					camel_exception_setv (base_exception,
+							      CAMEL_EXCEPTION_SYSTEM, "%s\n\n%s",
+							      base_exception->desc, ex.desc);
 				else
-					camel_exception_xfer (&m->base.ex, &ex);
+					camel_exception_xfer (base_exception, &ex);
 				camel_exception_clear (&ex);
 
 				/* keep track of the number of failures */
 				j++;
 			} else {
 				/* transfer the USER_CANCEL exeption to the async op exception and then break */
-				camel_exception_xfer (&m->base.ex, &ex);
+				camel_exception_xfer (base_exception, &ex);
 				break;
 			}
 		}
@@ -787,7 +869,7 @@ send_queue_exec (struct _send_queue_msg *m)
 
 	if (j > 0)
 		report_status (m, CAMEL_FILTER_STATUS_END, 100, _("Failed to send %d of %d messages"), j, send_uids->len);
-	else if (m->base.ex.id == CAMEL_EXCEPTION_USER_CANCEL)
+	else if (e_mail_msg_get_exception ((EMailMsg*) m)->id == CAMEL_EXCEPTION_USER_CANCEL)
 		report_status (m, CAMEL_FILTER_STATUS_END, 100, _("Canceled."));
 	else
 		report_status (m, CAMEL_FILTER_STATUS_END, 100, _("Complete."));
@@ -800,7 +882,7 @@ send_queue_exec (struct _send_queue_msg *m)
 	camel_folder_free_uids (m->queue, uids);
 	g_ptr_array_free (send_uids, TRUE);
 
-	if (j <= 0 && !camel_exception_is_set (&m->base.ex)) {
+	if (j <= 0 && !e_mail_msg_exception_is_set ((EMailMsg*) m)) {
 		camel_folder_sync (m->queue, TRUE, &ex);
 		camel_exception_clear (&ex);
 	}
@@ -816,41 +898,64 @@ send_queue_exec (struct _send_queue_msg *m)
 	if (m->cancel)
 		camel_operation_unregister (m->cancel);
 	else
-		camel_operation_unregister (m->base.cancel);
-
+		camel_operation_unregister (e_mail_msg_get_operation ((EMailMsg*) m));
 }
 
 static void
-send_queue_done (struct _send_queue_msg *m)
+send_queue_done (SendQueueMsg *m)
 {
 	if (m->done)
 		m->done(m->destination, m->data);
 }
 
 static gchar *
-send_queue_desc (struct _send_queue_msg *m)
+send_queue_desc (SendQueueMsg *m)
 {
 	return g_strdup (_("Sending message"));
 }
 
 static void
-send_queue_free (struct _send_queue_msg *m)
+send_queue_msg_dispose (GObject *object)
 {
-	if (m->driver)
+	SendQueueMsg *m = (SendQueueMsg*) object;
+
+	if (m->driver) {
 		camel_object_unref(m->driver);
-	camel_object_unref(m->queue);
+		m->driver = NULL;
+	}
+
+	if (m->queue) {
+		camel_object_unref(m->queue);
+		m->queue = NULL;
+	}
+
 	g_free(m->destination);
-	if (m->cancel)
+	m->destination = NULL;
+
+	if (m->cancel) {
 		camel_operation_unref(m->cancel);
+		m->cancel = NULL;
+	}
+
+	G_OBJECT_CLASS (send_queue_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo send_queue_info = {
-	sizeof (struct _send_queue_msg),
-	(MailMsgDescFunc) send_queue_desc,
-	(MailMsgExecFunc) send_queue_exec,
-	(MailMsgDoneFunc) send_queue_done,
-	(MailMsgFreeFunc) send_queue_free
-};
+static void
+send_queue_msg_class_init (SendQueueMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = send_queue_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) send_queue_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) send_queue_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) send_queue_done;
+}
+
+static void
+send_queue_msg_init (SendQueueMsg *msg)
+{
+}
 
 /* same interface as fetch_mail, just 'cause i'm lazy today (and we need to run it from the same spot?) */
 void
@@ -860,19 +965,17 @@ mail_send_queue(CamelFolder *queue, const gchar *destination,
 		CamelFilterStatusFunc *status, gpointer status_data,
 		void (*done)(const gchar *destination, gpointer data), gpointer data)
 {
-	struct _send_queue_msg *m;
+	SendQueueMsg *m;
 
-	m = mail_msg_new(&send_queue_info);
+	m = g_object_new (send_queue_msg_get_type (), NULL);
 	m->queue = queue;
 	camel_object_ref(queue);
 	m->destination = g_strdup(destination);
 	if (cancel) {
 		m->cancel = cancel;
 		camel_operation_ref(cancel);
-		camel_operation_unref (m->base.cancel);
-		mail_msg_set_cancelable (m, FALSE);
 
-		m->base.cancel = NULL;
+		e_mail_msg_set_operation ((EMailMsg*) m, NULL);
 	}
 	m->status = status;
 	m->status_data = status_data;
@@ -882,13 +985,15 @@ mail_send_queue(CamelFolder *queue, const gchar *destination,
 	m->driver = camel_session_get_filter_driver (session, type, NULL);
 	camel_filter_driver_set_folder_func (m->driver, get_folder, get_data);
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** APPEND MESSAGE TO FOLDER ******************************************** */
 
+typedef struct _append_msg AppendMsg;
 struct _append_msg {
-	MailMsg base;
+	EMailMsg base;
 
         CamelFolder *folder;
 	CamelMimeMessage *message;
@@ -898,49 +1003,79 @@ struct _append_msg {
 	void (*done)(CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info, gint ok, const gchar *appended_uid, gpointer data);
 	gpointer data;
 };
+typedef struct _AppendMsgClass AppendMsgClass;
+struct _AppendMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType append_msg_get_type ();
+G_DEFINE_TYPE (AppendMsg, append_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-append_mail_desc (struct _append_msg *m)
+append_mail_desc (AppendMsg *m)
 {
-	return g_strdup_printf (_("Saving message to folder '%s'"), camel_folder_get_full_name (m->folder));
+	return g_strdup_printf (_("Saving message to folder '%s'"),
+				camel_folder_get_full_name (m->folder));
 }
 
 static void
-append_mail_exec (struct _append_msg *m)
+append_mail_exec (AppendMsg *m)
 {
 	camel_mime_message_set_date(m->message, CAMEL_MESSAGE_DATE_CURRENT, 0);
-	camel_folder_append_message(m->folder, m->message, m->info, &m->appended_uid, &m->base.ex);
+	camel_folder_append_message(m->folder, m->message, m->info, &m->appended_uid,
+				    e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-append_mail_done (struct _append_msg *m)
+append_mail_done (AppendMsg *m)
 {
 	if (m->done)
-		m->done(m->folder, m->message, m->info, !camel_exception_is_set(&m->base.ex), m->appended_uid, m->data);
+		m->done(m->folder, m->message, m->info, !e_mail_msg_exception_is_set((EMailMsg*) m), m->appended_uid, m->data);
 }
 
 static void
-append_mail_free (struct _append_msg *m)
+append_msg_dispose (GObject *object)
 {
-	camel_object_unref(m->message);
-	camel_object_unref(m->folder);
+	AppendMsg *m = (AppendMsg *) object;
+
+	if (m->message) {
+		camel_object_unref(m->message);
+		m->message = NULL;
+	}
+
+	if (m->folder) {
+		camel_object_unref(m->folder);
+		m->folder = NULL;
+	}
+
 	g_free (m->appended_uid);
+	m->appended_uid = NULL;
+
+	G_OBJECT_CLASS (append_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo append_mail_info = {
-	sizeof (struct _append_msg),
-	(MailMsgDescFunc) append_mail_desc,
-	(MailMsgExecFunc) append_mail_exec,
-	(MailMsgDoneFunc) append_mail_done,
-	(MailMsgFreeFunc) append_mail_free
-};
+static void
+append_msg_class_init (AppendMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = append_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) append_mail_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) append_mail_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) append_mail_done;
+}
+
+static void
+append_msg_init (AppendMsg *msg)
+{
+}
 
 void
 mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info,
 		  void (*done)(CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info, gint ok, const gchar *appended_uid, gpointer data),
 		  gpointer data)
 {
-	struct _append_msg *m;
+	AppendMsg *m;
 
 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
@@ -948,7 +1083,7 @@ mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageIn
 	if (!camel_medium_get_header (CAMEL_MEDIUM (message), "X-Mailer"))
 		camel_medium_set_header (CAMEL_MEDIUM (message), "X-Mailer", x_mailer);
 
-	m = mail_msg_new (&append_mail_info);
+	m = g_object_new (append_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->message = message;
@@ -958,13 +1093,15 @@ mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageIn
 	m->done = done;
 	m->data = data;
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** TRANSFER MESSAGES **************************************************** */
 
+typedef struct _transfer_msg TransferMsg;
 struct _transfer_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *source;
 	GPtrArray *uids;
@@ -975,9 +1112,15 @@ struct _transfer_msg {
 	void (*done)(gboolean ok, gpointer data);
 	gpointer data;
 };
+typedef struct _TransferMsgClass TransferMsgClass;
+struct _TransferMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType transfer_msg_get_type ();
+G_DEFINE_TYPE (TransferMsg, transfer_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-transfer_messages_desc (struct _transfer_msg *m)
+transfer_messages_desc (TransferMsg *m)
 {
 	return g_strdup_printf (m->delete ? _("Moving messages to '%s'") : _("Copying messages to '%s'"),
 				m->dest_uri);
@@ -985,12 +1128,13 @@ transfer_messages_desc (struct _transfer_msg *m)
 }
 
 static void
-transfer_messages_exec (struct _transfer_msg *m)
+transfer_messages_exec (TransferMsg *m)
 {
 	CamelFolder *dest;
 
-	dest = mail_tool_uri_to_folder (m->dest_uri, m->dest_flags, &m->base.ex);
-	if (camel_exception_is_set (&m->base.ex))
+	dest = mail_tool_uri_to_folder (m->dest_uri, m->dest_flags,
+					e_mail_msg_get_exception ((EMailMsg*) m));
+	if (e_mail_msg_exception_is_set ((EMailMsg*) m))
 		return;
 
 	if (dest == m->source) {
@@ -1002,7 +1146,8 @@ transfer_messages_exec (struct _transfer_msg *m)
 	camel_folder_freeze (m->source);
 	camel_folder_freeze (dest);
 
-	camel_folder_transfer_messages_to (m->source, m->uids, dest, NULL, m->delete, &m->base.ex);
+	camel_folder_transfer_messages_to (m->source, m->uids, dest, NULL, m->delete,
+					   e_mail_msg_get_exception ((EMailMsg*)m));
 
 	/* make sure all deleted messages are marked as seen */
 
@@ -1021,27 +1166,49 @@ transfer_messages_exec (struct _transfer_msg *m)
 }
 
 static void
-transfer_messages_done (struct _transfer_msg *m)
+transfer_messages_done (TransferMsg *m)
 {
 	if (m->done)
-		m->done (!camel_exception_is_set (&m->base.ex), m->data);
+		m->done (!e_mail_msg_exception_is_set ((EMailMsg*) m), m->data);
 }
 
 static void
-transfer_messages_free (struct _transfer_msg *m)
+transfer_msg_dispose (GObject *object)
 {
-	camel_object_unref (m->source);
+	TransferMsg *m = (TransferMsg*) object;
+
+	if (m->source) {
+		camel_object_unref (m->source);
+		m->source = NULL;
+	}
+
 	g_free (m->dest_uri);
-	em_utils_uids_free (m->uids);
+	m->dest_uri = NULL;
+
+	if (m->uids) {
+		em_utils_uids_free (m->uids);
+		m->uids = NULL;
+	}
+
+	G_OBJECT_CLASS (transfer_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo transfer_messages_info = {
-	sizeof (struct _transfer_msg),
-	(MailMsgDescFunc) transfer_messages_desc,
-	(MailMsgExecFunc) transfer_messages_exec,
-	(MailMsgDoneFunc) transfer_messages_done,
-	(MailMsgFreeFunc) transfer_messages_free
-};
+static void
+transfer_msg_class_init (TransferMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = transfer_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) transfer_messages_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) transfer_messages_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) transfer_messages_done;
+}
+
+static void
+transfer_msg_init (TransferMsg *msg)
+{
+}
 
 void
 mail_transfer_messages (CamelFolder *source, GPtrArray *uids,
@@ -1051,13 +1218,13 @@ mail_transfer_messages (CamelFolder *source, GPtrArray *uids,
 			void (*done) (gboolean ok, gpointer data),
 			gpointer data)
 {
-	struct _transfer_msg *m;
+	TransferMsg *m;
 
 	g_return_if_fail (CAMEL_IS_FOLDER (source));
 	g_return_if_fail (uids != NULL);
 	g_return_if_fail (dest_uri != NULL);
 
-	m = mail_msg_new(&transfer_messages_info);
+	m = g_object_new (transfer_msg_get_type (), NULL);
 	m->source = source;
 	camel_object_ref (source);
 	m->uids = uids;
@@ -1067,13 +1234,15 @@ mail_transfer_messages (CamelFolder *source, GPtrArray *uids,
 	m->done = done;
 	m->data = data;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** SCAN SUBFOLDERS ***************************************************** */
 
+typedef struct _get_folderinfo_msg GetFolderInfoMsg;
 struct _get_folderinfo_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelStore *store;
 	CamelFolderInfo *info;
@@ -1081,9 +1250,15 @@ struct _get_folderinfo_msg {
 	gpointer data;
 	gboolean can_clear; /* whether we can clear folder info */
 };
+typedef struct _GetFolderInfoMsgClass GetFolderInfoMsgClass;
+struct _GetFolderInfoMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType get_folder_info_msg_get_type ();
+G_DEFINE_TYPE (GetFolderInfoMsg, get_folder_info_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-get_folderinfo_desc (struct _get_folderinfo_msg *m)
+get_folderinfo_desc (GetFolderInfoMsg *m)
 {
 	gchar *ret, *name;
 
@@ -1094,22 +1269,24 @@ get_folderinfo_desc (struct _get_folderinfo_msg *m)
 }
 
 static void
-get_folderinfo_exec (struct _get_folderinfo_msg *m)
+get_folderinfo_exec (GetFolderInfoMsg *m)
 {
 	guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
 
-	m->info = camel_store_get_folder_info (m->store, NULL, flags, &m->base.ex);
+	m->info = camel_store_get_folder_info (m->store, NULL, flags,
+					       e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-get_folderinfo_done (struct _get_folderinfo_msg *m)
+get_folderinfo_done (GetFolderInfoMsg *m)
 {
-	if (!m->info && camel_exception_is_set (&m->base.ex)) {
+	if (!m->info && e_mail_msg_exception_is_set ((EMailMsg*) m)) {
 		gchar *url;
 
 		url = camel_service_get_url (CAMEL_SERVICE (m->store));
 		w(g_warning ("Error getting folder info from store at %s: %s",
-			     url, camel_exception_get_description (&m->base.ex)));
+			     url, camel_exception_get_description
+			     (e_mail_msg_get_exception ((EMailMsg*) m))));
 		g_free (url);
 	}
 
@@ -1120,40 +1297,57 @@ get_folderinfo_done (struct _get_folderinfo_msg *m)
 }
 
 static void
-get_folderinfo_free (struct _get_folderinfo_msg *m)
+get_folder_info_msg_dispose (GObject *object)
 {
-	if (m->info && m->can_clear)
+	GetFolderInfoMsg *m = (GetFolderInfoMsg*) object;
+
+	if (m->info && m->can_clear) {
 		camel_store_free_folder_info(m->store, m->info);
-	camel_object_unref(m->store);
+		m->info = NULL;
+	}
+	if (m->store) {
+		camel_object_unref(m->store);
+		m->store = NULL;
+	}
+
+	G_OBJECT_CLASS (get_folder_info_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo get_folderinfo_info = {
-	sizeof (struct _get_folderinfo_msg),
-	(MailMsgDescFunc) get_folderinfo_desc,
-	(MailMsgExecFunc) get_folderinfo_exec,
-	(MailMsgDoneFunc) get_folderinfo_done,
-	(MailMsgFreeFunc) get_folderinfo_free
-};
+static void
+get_folder_info_msg_class_init (GetFolderInfoMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = get_folder_info_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) get_folderinfo_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) get_folderinfo_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_folderinfo_done;
+}
+
+static void
+get_folder_info_msg_init (GetFolderInfoMsg *msg)
+{
+}
 
 gint
 mail_get_folderinfo (CamelStore *store, CamelOperation *op, gboolean (*done)(CamelStore *store, CamelFolderInfo *info, gpointer data), gpointer data)
 {
-	struct _get_folderinfo_msg *m;
+	GetFolderInfoMsg *m;
 	gint id;
 
-	m = mail_msg_new(&get_folderinfo_info);
+	m = g_object_new (get_folder_info_msg_get_type (), NULL);
 	if (op) {
-		camel_operation_unref(m->base.cancel);
-		m->base.cancel = op;
-		camel_operation_ref(op);
+		e_mail_msg_set_operation ((EMailMsg*) m, op);
 	}
 	m->store = store;
 	camel_object_ref(store);
 	m->done = done;
 	m->data = data;
-	id = m->base.seq;
 
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
@@ -1224,8 +1418,9 @@ mail_build_attachment(CamelFolder *folder, GPtrArray *uids,
 /* there should be some way to merge this and create folder, since both can
    presumably create a folder ... */
 
+typedef struct _get_folder_msg GetFolderMsg;
 struct _get_folder_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gchar *uri;
 	guint32 flags;
@@ -1233,65 +1428,90 @@ struct _get_folder_msg {
 	void (*done) (gchar *uri, CamelFolder *folder, gpointer data);
 	gpointer data;
 };
+typedef struct _GetFolderMsgClass GetFolderMsgClass;
+struct _GetFolderMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType get_folder_msg_get_type ();
+G_DEFINE_TYPE (GetFolderMsg, get_folder_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-get_folder_desc (struct _get_folder_msg *m)
+get_folder_desc (GetFolderMsg *m)
 {
 	return g_strdup_printf (_("Opening folder '%s'"), m->uri);
 }
 
 static void
-get_folder_exec (struct _get_folder_msg *m)
+get_folder_exec (GetFolderMsg *m)
 {
-	m->folder = mail_tool_uri_to_folder (m->uri, m->flags, &m->base.ex);
+	m->folder = mail_tool_uri_to_folder (m->uri, m->flags,
+					     e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-get_folder_done (struct _get_folder_msg *m)
+get_folder_done (GetFolderMsg *m)
 {
 	if (m->done)
 		m->done (m->uri, m->folder, m->data);
 }
 
 static void
-get_folder_free (struct _get_folder_msg *m)
+get_folder_msg_dispose (GObject *object)
 {
+	GetFolderMsg *m = (GetFolderMsg*) object;
+
 	g_free (m->uri);
-	if (m->folder)
+	m->uri = NULL;
+
+	if (m->folder) {
 		camel_object_unref (m->folder);
+		m->folder = NULL;
+	}
+
+	G_OBJECT_CLASS (get_folder_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo get_folder_info = {
-	sizeof (struct _get_folder_msg),
-	(MailMsgDescFunc) get_folder_desc,
-	(MailMsgExecFunc) get_folder_exec,
-	(MailMsgDoneFunc) get_folder_done,
-	(MailMsgFreeFunc) get_folder_free
-};
+static void
+get_folder_msg_class_init (GetFolderMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = get_folder_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) get_folder_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) get_folder_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_folder_done;
+}
+
+static void
+get_folder_msg_init (GetFolderMsg *msg)
+{
+}
 
 gint
 mail_get_folder (const gchar *uri, guint32 flags,
 		 void (*done)(gchar *uri, CamelFolder *folder, gpointer data),
 		 gpointer data, MailMsgDispatchFunc dispatch)
 {
-	struct _get_folder_msg *m;
+	GetFolderMsg *m;
 	gint id;
 
-	m = mail_msg_new(&get_folder_info);
+	m = g_object_new (get_folder_msg_get_type (), NULL);
 	m->uri = g_strdup (uri);
 	m->flags = flags;
 	m->data = data;
 	m->done = done;
 
-	id = m->base.seq;
-	dispatch (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	dispatch ((EMailMsg*) m);
 	return id;
 }
 
 /* ** GET FOLDER'S QUOTA ********************************************************* */
 
+typedef struct _get_quota_msg GetQuotaMsg;
 struct _get_quota_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	CamelFolderQuotaInfo *quota;
@@ -1299,43 +1519,62 @@ struct _get_quota_msg {
 	gchar *folder_uri;
 	gpointer data;
 };
+typedef struct _GetQuotaMsgClass GetQuotaMsgClass;
+struct _GetQuotaMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType get_quota_msg_get_type ();
+G_DEFINE_TYPE (GetQuotaMsg, get_quota_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-get_quota_desc (struct _get_quota_msg *m)
+get_quota_desc (GetQuotaMsg *m)
 {
 	return g_strdup_printf (_("Retrieving quota information for folder '%s'"), camel_folder_get_name (m->folder));
 }
 
 static void
-get_quota_exec (struct _get_quota_msg *m)
+get_quota_exec (GetQuotaMsg *m)
 {
 	m->quota = camel_folder_get_quota_info (m->folder);
 }
 
 static void
-get_quota_done (struct _get_quota_msg *m)
+get_quota_done (GetQuotaMsg *m)
 {
 	if (m->done)
 		m->done (m->folder, m->folder_uri, m->quota, m->data);
 }
 
 static void
-get_quota_free (struct _get_quota_msg *m)
+get_quota_msg_dispose (GObject *object)
 {
+	GetQuotaMsg *m = (GetQuotaMsg *) object;
+
 	if (m->folder)
 		camel_object_unref (m->folder);
 	if (m->quota)
 		camel_folder_quota_info_free (m->quota);
 	g_free (m->folder_uri);
+
+	G_OBJECT_CLASS (get_quota_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo get_quota_info = {
-	sizeof (struct _get_quota_msg),
-	(MailMsgDescFunc) get_quota_desc,
-	(MailMsgExecFunc) get_quota_exec,
-	(MailMsgDoneFunc) get_quota_done,
-	(MailMsgFreeFunc) get_quota_free
-};
+static void
+get_quota_msg_class_init (GetQuotaMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = get_quota_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) get_quota_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) get_quota_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_quota_done;
+}
+
+static void
+get_quota_msg_init (GetQuotaMsg *msg)
+{
+}
 
 gint
 mail_get_folder_quota (CamelFolder *folder,
@@ -1343,12 +1582,12 @@ mail_get_folder_quota (CamelFolder *folder,
 		 void (*done)(CamelFolder *folder, const gchar *uri, CamelFolderQuotaInfo *quota, gpointer data),
 		 gpointer data, MailMsgDispatchFunc dispatch)
 {
-	struct _get_quota_msg *m;
+	GetQuotaMsg *m;
 	gint id;
 
 	g_return_val_if_fail (folder != NULL, -1);
 
-	m = mail_msg_new (&get_quota_info);
+	m = g_object_new (get_quota_msg_get_type (), NULL);
 	m->folder = folder;
 	m->folder_uri = g_strdup (folder_uri);
 	m->data = data;
@@ -1356,95 +1595,121 @@ mail_get_folder_quota (CamelFolder *folder,
 
 	camel_object_ref (m->folder);
 
-	id = m->base.seq;
-	dispatch (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	dispatch ((EMailMsg*) m);
 	return id;
 }
 
 /* ** GET STORE ******************************************************* */
 
+typedef struct _get_store_msg GetStoreMsg;
 struct _get_store_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gchar *uri;
 	CamelStore *store;
 	void (*done) (gchar *uri, CamelStore *store, gpointer data);
 	gpointer data;
 };
+typedef struct _GetStoreMsgClass GetStoreMsgClass;
+struct _GetStoreMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType get_store_msg_get_type ();
+G_DEFINE_TYPE (GetStoreMsg, get_store_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-get_store_desc (struct _get_store_msg *m)
+get_store_desc (GetStoreMsg *m)
 {
 	return g_strdup_printf (_("Opening store '%s'"), m->uri);
 }
 
 static void
-get_store_exec (struct _get_store_msg *m)
+get_store_exec (GetStoreMsg *m)
 {
 	/*camel_session_get_store connects us, which we don't want to do on startup. */
 
-	m->store = (CamelStore *) camel_session_get_service (session, m->uri,
-							     CAMEL_PROVIDER_STORE,
-							     &m->base.ex);
+	m->store = (CamelStore *)
+		camel_session_get_service (session, m->uri,
+					   CAMEL_PROVIDER_STORE,
+					   e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-get_store_done (struct _get_store_msg *m)
+get_store_done (GetStoreMsg *m)
 {
 	if (m->done)
 		m->done (m->uri, m->store, m->data);
 }
 
 static void
-get_store_free (struct _get_store_msg *m)
+get_store_msg_dispose (GObject *object)
 {
+	GetStoreMsg *m = (GetStoreMsg *) object;
 	g_free (m->uri);
 	if (m->store)
 		camel_object_unref (m->store);
+
+	G_OBJECT_CLASS (get_store_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo get_store_info = {
-	sizeof (struct _get_store_msg),
-	(MailMsgDescFunc) get_store_desc,
-	(MailMsgExecFunc) get_store_exec,
-	(MailMsgDoneFunc) get_store_done,
-	(MailMsgFreeFunc) get_store_free
-};
+static void
+get_store_msg_class_init (GetStoreMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = get_store_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) get_store_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) get_store_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_store_done;
+}
+
+static void
+get_store_msg_init (GetStoreMsg *msg)
+{
+}
 
 gint
 mail_get_store (const gchar *uri, CamelOperation *op, void (*done) (gchar *uri, CamelStore *store, gpointer data), gpointer data)
 {
-	struct _get_store_msg *m;
+	GetStoreMsg *m;
 	gint id;
 
-	m = mail_msg_new (&get_store_info);
+	m = g_object_new (get_store_msg_get_type (), NULL);
 	if (op) {
-		camel_operation_unref(m->base.cancel);
-		m->base.cancel = op;
-		camel_operation_ref(op);
+		e_mail_msg_set_operation ((EMailMsg*) m, op);
 	}
 	m->uri = g_strdup (uri);
 	m->data = data;
 	m->done = done;
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 	return id;
 }
 
 /* ** REMOVE FOLDER ******************************************************* */
 
+typedef struct _remove_folder_msg RemoveFolderMsg;
 struct _remove_folder_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	gboolean removed;
 	void (*done) (CamelFolder *folder, gboolean removed, CamelException *ex, gpointer data);
 	gpointer data;
 };
+typedef struct _RemoveFolderMsgClass RemoveFolderMsgClass;
+struct _RemoveFolderMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType remove_folder_msg_get_type ();
+G_DEFINE_TYPE (RemoveFolderMsg, remove_folder_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-remove_folder_desc (struct _remove_folder_msg *m)
+remove_folder_desc (RemoveFolderMsg *m)
 {
 	return g_strdup_printf (_("Removing folder '%s'"), camel_folder_get_full_name (m->folder));
 }
@@ -1495,7 +1760,7 @@ remove_folder_rec (CamelStore *store, CamelFolderInfo *fi, CamelException *ex)
 }
 
 static void
-remove_folder_exec (struct _remove_folder_msg *m)
+remove_folder_exec (RemoveFolderMsg *m)
 {
 	CamelStore *store;
 	CamelFolderInfo *fi;
@@ -1504,124 +1769,178 @@ remove_folder_exec (struct _remove_folder_msg *m)
 
 	store = m->folder->parent_store;
 
-	fi = camel_store_get_folder_info (store, m->folder->full_name, CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, &m->base.ex);
-	if (camel_exception_is_set (&m->base.ex))
+	fi = camel_store_get_folder_info (store, m->folder->full_name,
+					  CAMEL_STORE_FOLDER_INFO_RECURSIVE |
+					  CAMEL_STORE_FOLDER_INFO_FAST |
+					  CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
+					  e_mail_msg_get_exception ((EMailMsg*) m));
+	if (e_mail_msg_exception_is_set ((EMailMsg*) m))
 		return;
 
-	remove_folder_rec (store, fi, &m->base.ex);
+	remove_folder_rec (store, fi, e_mail_msg_get_exception ((EMailMsg*) m));
 	camel_store_free_folder_info (store, fi);
 
-	m->removed = !camel_exception_is_set (&m->base.ex);
+	m->removed = !e_mail_msg_exception_is_set ((EMailMsg*) m);
 }
 
 static void
-remove_folder_done (struct _remove_folder_msg *m)
+remove_folder_done (RemoveFolderMsg *m)
 {
 	if (m->done)
-		m->done (m->folder, m->removed, &m->base.ex, m->data);
+		m->done (m->folder, m->removed,
+			 e_mail_msg_get_exception ((EMailMsg*) m),
+			 m->data);
+}
+
+static void
+remove_folder_msg_dispose (GObject *object)
+{
+	RemoveFolderMsg *m = (RemoveFolderMsg*) object;
+	if (m->folder) {
+		camel_object_unref (m->folder);
+		m->folder = NULL;
+	}
+
+	G_OBJECT_CLASS (remove_folder_msg_parent_class)->dispose (object);
 }
 
 static void
-remove_folder_free (struct _remove_folder_msg *m)
+remove_folder_msg_class_init (RemoveFolderMsgClass *klass)
 {
-	camel_object_unref (m->folder);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = remove_folder_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) remove_folder_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) remove_folder_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) remove_folder_done;
 }
 
-static MailMsgInfo remove_folder_info = {
-	sizeof (struct _remove_folder_msg),
-	(MailMsgDescFunc) remove_folder_desc,
-	(MailMsgExecFunc) remove_folder_exec,
-	(MailMsgDoneFunc) remove_folder_done,
-	(MailMsgFreeFunc) remove_folder_free
-};
+static void
+remove_folder_msg_init (RemoveFolderMsg *msg)
+{
+}
 
 void
 mail_remove_folder (CamelFolder *folder, void (*done) (CamelFolder *folder, gboolean removed, CamelException *ex, gpointer data), gpointer data)
 {
-	struct _remove_folder_msg *m;
+	RemoveFolderMsg *m;
 
 	g_return_if_fail (folder != NULL);
 
-	m = mail_msg_new (&remove_folder_info);
+	m = g_object_new (remove_folder_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref (folder);
 	m->data = data;
 	m->done = done;
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** SYNC FOLDER ********************************************************* */
 
+typedef struct _sync_folder_msg SyncFolderMsg;
 struct _sync_folder_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	void (*done) (CamelFolder *folder, gpointer data);
 	gpointer data;
 };
+typedef struct _SyncFolderMsgClass SyncFolderMsgClass;
+struct _SyncFolderMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType sync_folder_msg_get_type ();
+G_DEFINE_TYPE (SyncFolderMsg, sync_folder_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-sync_folder_desc (struct _sync_folder_msg *m)
+sync_folder_desc (SyncFolderMsg *m)
 {
 	return g_strdup_printf (_("Storing folder '%s'"),
 			       camel_folder_get_full_name (m->folder));
 }
 
 static void
-sync_folder_exec (struct _sync_folder_msg *m)
+sync_folder_exec (SyncFolderMsg *m)
 {
-	camel_folder_sync(m->folder, FALSE, &m->base.ex);
+	camel_folder_sync(m->folder, FALSE,
+			  e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-sync_folder_done (struct _sync_folder_msg *m)
+sync_folder_done (SyncFolderMsg *m)
 {
 	if (m->done)
 		m->done(m->folder, m->data);
 }
 
 static void
-sync_folder_free (struct _sync_folder_msg *m)
+sync_folder_msg_dispose (GObject *object)
 {
-	camel_object_unref((CamelObject *)m->folder);
+	SyncFolderMsg *m = (SyncFolderMsg*) object;
+
+	if (m->folder) {
+		camel_object_unref((CamelObject *)m->folder);
+		m->folder = NULL;
+	}
+
+	G_OBJECT_CLASS (sync_folder_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo sync_folder_info = {
-	sizeof (struct _sync_folder_msg),
-	(MailMsgDescFunc) sync_folder_desc,
-	(MailMsgExecFunc) sync_folder_exec,
-	(MailMsgDoneFunc) sync_folder_done,
-	(MailMsgFreeFunc) sync_folder_free
-};
+static void
+sync_folder_msg_class_init (SyncFolderMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = sync_folder_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) sync_folder_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) sync_folder_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) sync_folder_done;
+}
+
+static void
+sync_folder_msg_init (SyncFolderMsg *msg)
+{
+}
 
 void
 mail_sync_folder(CamelFolder *folder, void (*done) (CamelFolder *folder, gpointer data), gpointer data)
 {
-	struct _sync_folder_msg *m;
+	SyncFolderMsg *m;
 
-	m = mail_msg_new(&sync_folder_info);
+	m = g_object_new (sync_folder_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->data = data;
 	m->done = done;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** SYNC STORE ********************************************************* */
 
+typedef struct _sync_store_msg SyncStoreMsg;
 struct _sync_store_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelStore *store;
 	gint expunge;
 	void (*done) (CamelStore *store, gpointer data);
 	gpointer data;
 };
+typedef struct _SyncStoreMsgClass SyncStoreMsgClass;
+struct _SyncStoreMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType sync_store_msg_get_type ();
+G_DEFINE_TYPE (SyncStoreMsg, sync_store_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-sync_store_desc (struct _sync_store_msg *m)
+sync_store_desc (SyncStoreMsg *m)
 {
 	gchar *uri, *res;
 
@@ -1636,204 +1955,283 @@ sync_store_desc (struct _sync_store_msg *m)
 }
 
 static void
-sync_store_exec (struct _sync_store_msg *m)
+sync_store_exec (SyncStoreMsg *m)
 {
-	camel_store_sync(m->store, m->expunge, &m->base.ex);
+	camel_store_sync(m->store, m->expunge,
+			 e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-sync_store_done (struct _sync_store_msg *m)
+sync_store_done (SyncStoreMsg *m)
 {
 	if (m->done)
 		m->done(m->store, m->data);
 }
 
 static void
-sync_store_free (struct _sync_store_msg *m)
+sync_store_msg_dispose (GObject *object)
 {
-	camel_object_unref(m->store);
+	SyncStoreMsg *m = (SyncStoreMsg*) object;
+
+	if (m->store) {
+		camel_object_unref(m->store);
+		m->store = NULL;
+	}
+
+	G_OBJECT_CLASS (sync_store_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo sync_store_info = {
-	sizeof (struct _sync_store_msg),
-	(MailMsgDescFunc) sync_store_desc,
-	(MailMsgExecFunc) sync_store_exec,
-	(MailMsgDoneFunc) sync_store_done,
-	(MailMsgFreeFunc) sync_store_free
-};
+static void
+sync_store_msg_class_init (SyncStoreMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = sync_store_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) sync_store_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) sync_store_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) sync_store_done;
+}
+
+static void
+sync_store_msg_init (SyncStoreMsg *msg)
+{
+}
 
 void
 mail_sync_store(CamelStore *store, gint expunge, void (*done) (CamelStore *store, gpointer data), gpointer data)
 {
-	struct _sync_store_msg *m;
+	SyncStoreMsg *m;
 
-	m = mail_msg_new(&sync_store_info);
+	m = g_object_new (sync_store_msg_get_type (), NULL);
 	m->store = store;
 	m->expunge = expunge;
 	camel_object_ref(store);
 	m->data = data;
 	m->done = done;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ******************************************************************************** */
 
+typedef struct
+{
+	SyncFolderMsg parent;
+} RefreshFolderMsg;
+
+typedef struct
+{
+	SyncFolderMsgClass parent_class;
+} RefreshFolderMsgClass;
+
+static GType refresh_folder_msg_get_type ();
+G_DEFINE_TYPE (RefreshFolderMsg, refresh_folder_msg, sync_folder_msg_get_type ());
+
 static gchar *
-refresh_folder_desc (struct _sync_folder_msg *m)
+refresh_folder_desc (SyncFolderMsg *m)
 {
-	return g_strdup_printf (_("Refreshing folder '%s'"), camel_folder_get_full_name (m->folder));
+	return g_strdup_printf (_("Refreshing folder '%s'"),
+				camel_folder_get_full_name (m->folder));
 }
 
 static void
-refresh_folder_exec (struct _sync_folder_msg *m)
+refresh_folder_exec (SyncFolderMsg *m)
 {
-	/* camel_folder_sync (m->folder, FALSE, &m->base.ex); */
+	/* camel_folder_sync (m->folder, FALSE, e_mail_msg_get_exception ((EMailMsg*) m)); */
 
-	/* if (!camel_exception_is_set (&m->base.ex)) */
-		camel_folder_refresh_info(m->folder, &m->base.ex);
+	/* if (!e_mail_msg_exception_is_set ((EMailMsg*) m)) */
+		camel_folder_refresh_info(m->folder, e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
-/* we just use the sync stuff where we can, since it would be the same */
-static MailMsgInfo refresh_folder_info = {
-	sizeof (struct _sync_folder_msg),
-	(MailMsgDescFunc) refresh_folder_desc,
-	(MailMsgExecFunc) refresh_folder_exec,
-	(MailMsgDoneFunc) sync_folder_done,
-	(MailMsgFreeFunc) sync_folder_free
-};
+static void
+refresh_folder_msg_class_init (RefreshFolderMsgClass *klass)
+{
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) refresh_folder_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) refresh_folder_exec;
+}
+
+static void
+refresh_folder_msg_init (RefreshFolderMsg *msg)
+{
+}
 
 void
 mail_refresh_folder(CamelFolder *folder, void (*done) (CamelFolder *folder, gpointer data), gpointer data)
 {
-	struct _sync_folder_msg *m;
+	SyncFolderMsg *m;
 
-	m = mail_msg_new(&refresh_folder_info);
+	m = g_object_new (refresh_folder_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->data = data;
 	m->done = done;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ******************************************************************************** */
 
+typedef struct
+{
+	SyncFolderMsg parent;
+} ExpungeFolderMsg;
+
+typedef struct
+{
+	SyncFolderMsgClass parent_class;
+} ExpungeFolderMsgClass;
+
+static GType expunge_folder_msg_get_type ();
+G_DEFINE_TYPE (ExpungeFolderMsg, expunge_folder_msg, sync_folder_msg_get_type ());
+
 static gchar *
-expunge_folder_desc (struct _sync_folder_msg *m)
+expunge_folder_desc (SyncFolderMsg *m)
 {
 	return g_strdup_printf (_("Expunging folder '%s'"), camel_folder_get_full_name (m->folder));
 }
 
 static void
-expunge_folder_exec (struct _sync_folder_msg *m)
+expunge_folder_exec (SyncFolderMsg *m)
 {
-	camel_folder_expunge(m->folder, &m->base.ex);
+	camel_folder_expunge(m->folder,
+			     e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
-/* we just use the sync stuff where we can, since it would be the same */
-static MailMsgInfo expunge_folder_info = {
-	sizeof (struct _sync_folder_msg),
-	(MailMsgDescFunc) expunge_folder_desc,
-	(MailMsgExecFunc) expunge_folder_exec,
-	(MailMsgDoneFunc) sync_folder_done,
-	(MailMsgFreeFunc) sync_folder_free
-};
+static void
+expunge_folder_msg_class_init (ExpungeFolderMsgClass *klass)
+{
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) expunge_folder_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) expunge_folder_exec;
+}
+
+static void
+expunge_folder_msg_init (ExpungeFolderMsg *msg)
+{
+}
 
 void
 mail_expunge_folder(CamelFolder *folder, void (*done) (CamelFolder *folder, gpointer data), gpointer data)
 {
-	struct _sync_folder_msg *m;
+	SyncFolderMsg *m;
 
-	m = mail_msg_new(&expunge_folder_info);
+	m = g_object_new (expunge_folder_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->data = data;
 	m->done = done;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ******************************************************************************** */
 
+typedef struct _empty_trash_msg EmptyTrashMsg;
 struct _empty_trash_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	EAccount *account;
 	void (*done) (EAccount *account, gpointer data);
 	gpointer data;
 };
+typedef struct _EmptyTrashMsgClass EmptyTrashMsgClass;
+struct _EmptyTrashMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType empty_trash_msg_get_type ();
+G_DEFINE_TYPE (EmptyTrashMsg, empty_trash_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-empty_trash_desc (struct _empty_trash_msg *m)
+empty_trash_desc (EmptyTrashMsg *m)
 {
 	return g_strdup_printf (_("Emptying trash in '%s'"),
 				m->account ? m->account->name : _("Local Folders"));
 }
 
 static void
-empty_trash_exec (struct _empty_trash_msg *m)
+empty_trash_exec (EmptyTrashMsg *m)
 {
 	const gchar *data_dir;
 	CamelFolder *trash;
 	gchar *uri;
 
 	if (m->account) {
-		trash = mail_tool_get_trash (m->account->source->url, FALSE, &m->base.ex);
+		trash = mail_tool_get_trash (m->account->source->url, FALSE,
+					     e_mail_msg_get_exception ((EMailMsg*) m));
 	} else {
 		data_dir = mail_session_get_data_dir ();
 		uri = g_strdup_printf ("mbox:%s/local", data_dir);
-		trash = mail_tool_get_trash (uri, TRUE, &m->base.ex);
+		trash = mail_tool_get_trash (uri, TRUE,
+					     e_mail_msg_get_exception ((EMailMsg*) m));
 		g_free (uri);
 	}
 
 	if (trash) {
-		camel_folder_expunge (trash, &m->base.ex);
+		camel_folder_expunge (trash, e_mail_msg_get_exception ((EMailMsg*) m));
 		camel_object_unref (trash);
 	}
 }
 
 static void
-empty_trash_done (struct _empty_trash_msg *m)
+empty_trash_done (EmptyTrashMsg *m)
 {
 	if (m->done)
 		m->done(m->account, m->data);
 }
 
 static void
-empty_trash_free (struct _empty_trash_msg *m)
+empty_trash_msg_dispose (GObject *object)
 {
-	if (m->account)
+	EmptyTrashMsg *m = (EmptyTrashMsg*) object;
+	if (m->account) {
 		g_object_unref(m->account);
+		m->account = NULL;
+	}
+
+	G_OBJECT_CLASS (empty_trash_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo empty_trash_info = {
-	sizeof (struct _empty_trash_msg),
-	(MailMsgDescFunc) empty_trash_desc,
-	(MailMsgExecFunc) empty_trash_exec,
-	(MailMsgDoneFunc) empty_trash_done,
-	(MailMsgFreeFunc) empty_trash_free
-};
+static void
+empty_trash_msg_class_init (EmptyTrashMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = empty_trash_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) empty_trash_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) empty_trash_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) empty_trash_done;
+}
+
+static void
+empty_trash_msg_init (EmptyTrashMsg *msg)
+{
+}
 
 void
 mail_empty_trash(EAccount *account, void (*done) (EAccount *account, gpointer data), gpointer data)
 {
-	struct _empty_trash_msg *m;
+	EmptyTrashMsg *m;
 
-	m = mail_msg_new(&empty_trash_info);
+	m = g_object_new (empty_trash_msg_get_type (), NULL);
 	m->account = account;
 	if (account)
 		g_object_ref(account);
 	m->data = data;
 	m->done = done;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** GET MESSAGE(s) ***************************************************** */
 
+typedef struct _get_message_msg GetMessageMsg;
 struct _get_message_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	gchar *uid;
@@ -1842,70 +2240,112 @@ struct _get_message_msg {
 	CamelMimeMessage *message;
 	CamelOperation *cancel;
 };
+typedef struct _GetMessageMsgClass GetMessageMsgClass;
+struct _GetMessageMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType get_message_msg_get_type ();
+G_DEFINE_TYPE (GetMessageMsg, get_message_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-get_message_desc (struct _get_message_msg *m)
+get_message_desc (GetMessageMsg *m)
 {
 	return g_strdup_printf (_("Retrieving message '%s'"), m->uid);
 }
 
 static void
-get_message_exec (struct _get_message_msg *m)
+get_message_exec (GetMessageMsg *m)
 {
-	if (m->base.cancel && camel_operation_cancel_check (m->base.cancel))
+	CamelOperation *op = e_mail_msg_get_operation ((EMailMsg*) m);
+	if (op && camel_operation_cancel_check (op))
 		m->message = NULL;
 	else
-		m->message = camel_folder_get_message (m->folder, m->uid, &m->base.ex);
+		m->message = camel_folder_get_message (m->folder, m->uid,
+						       e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-get_message_done (struct _get_message_msg *m)
+get_message_done (GetMessageMsg *m)
 {
 	if (m->done)
 		m->done(m->folder, m->uid, m->message, m->data);
 }
 
 static void
-get_message_free (struct _get_message_msg *m)
+get_message_msg_dispose (GObject *object)
 {
+	GetMessageMsg *m = (GetMessageMsg*) object;
 	g_free (m->uid);
-	camel_object_unref (m->folder);
-	camel_operation_unref (m->cancel);
+	m->uid = NULL;
 
-	if (m->message)
+	if (m->folder) {
+		camel_object_unref (m->folder);
+		m->folder = NULL;
+	}
+
+	if (m->cancel) {
+		camel_operation_unref (m->cancel);
+		m->cancel = NULL;
+	}
+
+	if (m->message) {
 		camel_object_unref (m->message);
+		m->message = NULL;
+	}
+
+	G_OBJECT_CLASS (get_message_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo get_message_info = {
-	sizeof (struct _get_message_msg),
-	(MailMsgDescFunc) get_message_desc,
-	(MailMsgExecFunc) get_message_exec,
-	(MailMsgDoneFunc) get_message_done,
-	(MailMsgFreeFunc) get_message_free
-};
+static void
+get_message_msg_class_init (GetMessageMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = get_message_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) get_message_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) get_message_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_message_done;
+}
+
+static void
+get_message_msg_init (GetMessageMsg *msg)
+{
+}
 
 gint
 mail_get_message(CamelFolder *folder, const gchar *uid, void (*done) (CamelFolder *folder, const gchar *uid,
 								     CamelMimeMessage *msg, gpointer data),
 		 gpointer data, MailMsgDispatchFunc dispatch)
 {
-	struct _get_message_msg *m;
+	GetMessageMsg *m;
 	gint id;
 
-	m = mail_msg_new(&get_message_info);
+	m = g_object_new (get_message_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->uid = g_strdup(uid);
 	m->data = data;
 	m->done = (void (*) (CamelFolder *, const gchar *, CamelMimeMessage *, gpointer )) done;
 	m->cancel = camel_operation_new(NULL, NULL);
-	id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
 
-	dispatch (m);
+	dispatch ((EMailMsg*) m);
 
 	return id;
 }
 
+typedef struct
+{
+	GetMessageMsg parent;
+} GetMessagexMsg;
+typedef struct
+{
+	GetMessageMsgClass parent_class;
+} GetMessagexMsgClass;
+static GType get_messagex_msg_get_type ();
+G_DEFINE_TYPE (GetMessagexMsg, get_messagex_msg, get_message_msg_get_type ());
+
 typedef void (*get_done)(CamelFolder *folder, const gchar *uid, CamelMimeMessage *msg, gpointer data, CamelException *);
 
 static void
@@ -1913,17 +2353,19 @@ get_messagex_done (struct _get_message_msg *m)
 {
 	if (m->done && !camel_operation_cancel_check (m->cancel)) {
 		get_done done = (get_done)m->done;
-		done(m->folder, m->uid, m->message, m->data, &m->base.ex);
+		done(m->folder, m->uid, m->message, m->data,
+		     e_mail_msg_get_exception ((EMailMsg*) m));
 	}
 }
 
-static MailMsgInfo get_messagex_info = {
-	sizeof (struct _get_message_msg),
-	(MailMsgDescFunc) get_message_desc,
-	(MailMsgExecFunc) get_message_exec,
-	(MailMsgDoneFunc) get_messagex_done,
-	(MailMsgFreeFunc) get_message_free
-};
+void get_messagex_msg_class_init (GetMessagexMsgClass *klass)
+{
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_messagex_done;
+}
+
+void get_messagex_msg_init (GetMessagexMsg *msg)
+{
+}
 
 /* This is temporary, to avoid having to rewrite everything that uses
    mail_get_message; it adds an exception argument to the callback */
@@ -1931,27 +2373,28 @@ gint
 mail_get_messagex(CamelFolder *folder, const gchar *uid, void (*done) (CamelFolder *folder, const gchar *uid, CamelMimeMessage *msg, gpointer data, CamelException *),
 		 gpointer data, MailMsgDispatchFunc dispatch)
 {
-	struct _get_message_msg *m;
+	GetMessageMsg *m;
 	gint id;
 
-	m = mail_msg_new(&get_messagex_info);
+	m = g_object_new (get_messagex_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->uid = g_strdup(uid);
 	m->data = data;
 	m->done = (void (*) (CamelFolder *, const gchar *, CamelMimeMessage *, gpointer )) done;
 	m->cancel = camel_operation_new(NULL, NULL);
-	id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
 
-	dispatch (m);
+	dispatch ((EMailMsg*) m);
 
 	return id;
 }
 
 /* ********************************************************************** */
 
+typedef struct _get_messages_msg GetMessagesMsg;
 struct _get_messages_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	GPtrArray *uids;
@@ -1960,9 +2403,15 @@ struct _get_messages_msg {
 	void (*done) (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, gpointer data);
 	gpointer data;
 };
+typedef struct _GetMessagesMsgClass GetMessagesMsgClass;
+struct _GetMessagesMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType get_messages_msg_get_type ();
+G_DEFINE_TYPE (GetMessagesMsg, get_messages_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-get_messages_desc (struct _get_messages_msg *m)
+get_messages_desc (GetMessagesMsg *m)
 {
 	return g_strdup_printf(ngettext("Retrieving %d message",
 					"Retrieving %d messages", m->uids->len),
@@ -1970,7 +2419,7 @@ get_messages_desc (struct _get_messages_msg *m)
 }
 
 static void
-get_messages_exec (struct _get_messages_msg *m)
+get_messages_exec (GetMessagesMsg *m)
 {
 	gint i;
 	CamelMimeMessage *message;
@@ -1978,8 +2427,9 @@ get_messages_exec (struct _get_messages_msg *m)
 	for (i=0; i<m->uids->len; i++) {
 		gint pc = ((i+1) * 100) / m->uids->len;
 
-		message = camel_folder_get_message(m->folder, m->uids->pdata[i], &m->base.ex);
-		camel_operation_progress(m->base.cancel, pc);
+		message = camel_folder_get_message(m->folder, m->uids->pdata[i],
+						   e_mail_msg_get_exception ((EMailMsg*) m));
+		camel_operation_progress(e_mail_msg_get_operation ((EMailMsg*) m), pc);
 		if (message == NULL)
 			break;
 
@@ -1988,60 +2438,84 @@ get_messages_exec (struct _get_messages_msg *m)
 }
 
 static void
-get_messages_done (struct _get_messages_msg *m)
+get_messages_done (GetMessagesMsg *m)
 {
 	if (m->done)
 		m->done(m->folder, m->uids, m->messages, m->data);
 }
 
 static void
-get_messages_free (struct _get_messages_msg *m)
+get_messages_msg_dispose (GObject *object)
 {
+	GetMessagesMsg *m = (GetMessagesMsg*) object;
 	gint i;
 
-	em_utils_uids_free (m->uids);
-	for (i=0;i<m->messages->len;i++) {
-		if (m->messages->pdata[i])
-			camel_object_unref(m->messages->pdata[i]);
+	if (m->uids) {
+		em_utils_uids_free (m->uids);
+		m->uids = NULL;
 	}
-	g_ptr_array_free(m->messages, TRUE);
-	camel_object_unref(m->folder);
+	if (m->messages) {
+		for (i=0;i<m->messages->len;i++) {
+			if (m->messages->pdata[i])
+				camel_object_unref(m->messages->pdata[i]);
+		}
+		g_ptr_array_free(m->messages, TRUE);
+		m->messages = NULL;
+	}
+
+	if (m->folder) {
+		camel_object_unref(m->folder);
+		m->folder = NULL;
+	}
+
+	G_OBJECT_CLASS (get_messages_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo get_messages_info = {
-	sizeof (struct _get_messages_msg),
-	(MailMsgDescFunc) get_messages_desc,
-	(MailMsgExecFunc) get_messages_exec,
-	(MailMsgDoneFunc) get_messages_done,
-	(MailMsgFreeFunc) get_messages_free
-};
+static void
+get_messages_msg_class_init (GetMessagesMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = get_messages_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) get_messages_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) get_messages_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) get_messages_done;
+}
+
+static void
+get_messages_msg_init (GetMessagesMsg *msg)
+{
+}
 
 gint
 mail_get_messages(CamelFolder *folder, GPtrArray *uids,
 		  void (*done) (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, gpointer data),
 		  gpointer data)
 {
-	struct _get_messages_msg *m;
+	GetMessagesMsg *m;
 	gint id;
 
-	m = mail_msg_new(&get_messages_info);
+	m = g_object_new (get_messages_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->uids = uids;
 	m->messages = g_ptr_array_new();
 	m->data = data;
 	m->done = done;
-	id = m->base.seq;
+	id = e_mail_msg_get_id ((EMailMsg*) m);
 
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
 
 /* ** SAVE MESSAGES ******************************************************* */
 
+typedef struct _save_messages_msg SaveMessagesMsg;
 struct _save_messages_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	GPtrArray *uids;
@@ -2049,9 +2523,15 @@ struct _save_messages_msg {
 	void (*done)(CamelFolder *folder, GPtrArray *uids, gchar *path, gpointer data);
 	gpointer data;
 };
+typedef struct _SaveMessagesMsgClass SaveMessagesMsgClass;
+struct _SaveMessagesMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType save_messages_msg_get_type ();
+G_DEFINE_TYPE (SaveMessagesMsg, save_messages_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-save_messages_desc (struct _save_messages_msg *m)
+save_messages_desc (SaveMessagesMsg *m)
 {
 	return g_strdup_printf(ngettext("Saving %d message",
 					"Saving %d messages", m->uids->len),
@@ -2091,7 +2571,7 @@ save_prepare_part (CamelMimePart *mime_part)
 }
 
 static void
-save_messages_exec (struct _save_messages_msg *m)
+save_messages_exec (SaveMessagesMsg *m)
 {
 	CamelStreamFilter *filtered_stream;
 	CamelMimeFilterFrom *from_filter;
@@ -2117,8 +2597,9 @@ save_messages_exec (struct _save_messages_msg *m)
 		CamelMimeMessage *message;
 		gint pc = ((i+1) * 100) / m->uids->len;
 
-		message = camel_folder_get_message(m->folder, m->uids->pdata[i], &m->base.ex);
-		camel_operation_progress(m->base.cancel, pc);
+		message = camel_folder_get_message(m->folder, m->uids->pdata[i],
+						   e_mail_msg_get_exception ((EMailMsg*) m));
+		camel_operation_progress(e_mail_msg_get_operation ((EMailMsg*) m), pc);
 		if (message == NULL)
 			break;
 
@@ -2132,7 +2613,8 @@ save_messages_exec (struct _save_messages_msg *m)
 		    || camel_stream_flush((CamelStream *)filtered_stream) == -1
 		    || camel_stream_write_string(stream, "\n") == -1
 		    || camel_stream_flush(stream) == -1) {
-			camel_exception_setv(&m->base.ex, CAMEL_EXCEPTION_SYSTEM,
+			camel_exception_setv(e_mail_msg_get_exception ((EMailMsg*) m),
+					     CAMEL_EXCEPTION_SYSTEM,
 					     _("Error saving messages to: %s:\n %s"), m->path, g_strerror(errno));
 			g_free(from);
 			camel_object_unref((CamelObject *)message);
@@ -2147,36 +2629,58 @@ save_messages_exec (struct _save_messages_msg *m)
 }
 
 static void
-save_messages_done (struct _save_messages_msg *m)
+save_messages_done (SaveMessagesMsg *m)
 {
 	if (m->done)
 		m->done(m->folder, m->uids, m->path, m->data);
 }
 
 static void
-save_messages_free (struct _save_messages_msg *m)
+save_messages_msg_dispose (GObject *object)
 {
-	em_utils_uids_free (m->uids);
-	camel_object_unref(m->folder);
+	SaveMessagesMsg *m = (SaveMessagesMsg*) object;
+
+	if (m->uids) {
+		em_utils_uids_free (m->uids);
+		m->uids = NULL;
+	}
+
+	if (m->folder) {
+		camel_object_unref(m->folder);
+		m->folder = NULL;
+	}
+
 	g_free(m->path);
+	m->path = NULL;
+
+	G_OBJECT_CLASS (save_messages_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo save_messages_info = {
-	sizeof (struct _save_messages_msg),
-	(MailMsgDescFunc) save_messages_desc,
-	(MailMsgExecFunc) save_messages_exec,
-	(MailMsgDoneFunc) save_messages_done,
-	(MailMsgFreeFunc) save_messages_free
-};
+static void
+save_messages_msg_class_init (SaveMessagesMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = save_messages_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) save_messages_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) save_messages_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) save_messages_done;
+}
+
+static void
+save_messages_msg_init (SaveMessagesMsg *msg)
+{
+}
 
 gint
 mail_save_messages(CamelFolder *folder, GPtrArray *uids, const gchar *path,
 		   void (*done) (CamelFolder *folder, GPtrArray *uids, gchar *path, gpointer data), gpointer data)
 {
-	struct _save_messages_msg *m;
+	SaveMessagesMsg *m;
 	gint id;
 
-	m = mail_msg_new(&save_messages_info);
+	m = g_object_new (save_messages_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->uids = uids;
@@ -2184,16 +2688,18 @@ mail_save_messages(CamelFolder *folder, GPtrArray *uids, const gchar *path,
 	m->data = data;
 	m->done = done;
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
 
 /* ** SAVE PART ******************************************************* */
 
+typedef struct _save_part_msg SavePartMsg;
 struct _save_part_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelMimePart *part;
 	gchar *path;
@@ -2201,15 +2707,21 @@ struct _save_part_msg {
 	gpointer data;
 	gboolean readonly;
 };
+typedef struct _SavePartMsgClass SavePartMsgClass;
+struct _SavePartMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType save_part_msg_get_type ();
+G_DEFINE_TYPE (SavePartMsg, save_part_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-save_part_desc (struct _save_part_msg *m)
+save_part_desc (SavePartMsg *m)
 {
 	return g_strdup(_("Saving attachment"));
 }
 
 static void
-save_part_exec (struct _save_part_msg *m)
+save_part_exec (SavePartMsg *m)
 {
 	CamelDataWrapper *content;
 	CamelStream *stream;
@@ -2222,7 +2734,8 @@ save_part_exec (struct _save_part_msg *m)
 
 	if (!m->readonly) {
 		if (!(stream = camel_stream_vfs_new_with_uri (path, CAMEL_STREAM_VFS_CREATE))) {
-			camel_exception_setv (&m->base.ex, CAMEL_EXCEPTION_SYSTEM,
+			camel_exception_setv (e_mail_msg_get_exception ((EMailMsg*) m),
+					      CAMEL_EXCEPTION_SYSTEM,
 					      _("Cannot create output file: %s:\n %s"),
 					      path, g_strerror (errno));
 			if (path != m->path)
@@ -2230,7 +2743,8 @@ save_part_exec (struct _save_part_msg *m)
 			return;
 		}
 	} else if (!(stream = camel_stream_vfs_new_with_uri (path, CAMEL_STREAM_VFS_CREATE))) {
-		camel_exception_setv (&m->base.ex, CAMEL_EXCEPTION_SYSTEM,
+		camel_exception_setv (e_mail_msg_get_exception ((EMailMsg*) m),
+				      CAMEL_EXCEPTION_SYSTEM,
 				      _("Cannot create output file: %s:\n %s"),
 				      path, g_strerror (errno));
 		if (path != m->path)
@@ -2245,7 +2759,8 @@ save_part_exec (struct _save_part_msg *m)
 
 	if (camel_data_wrapper_decode_to_stream (content, stream) == -1
 	    || camel_stream_flush (stream) == -1)
-		camel_exception_setv (&m->base.ex, CAMEL_EXCEPTION_SYSTEM,
+		camel_exception_setv (e_mail_msg_get_exception ((EMailMsg*) m),
+				      CAMEL_EXCEPTION_SYSTEM,
 				      _("Could not write data: %s"),
 				      g_strerror (errno));
 
@@ -2253,34 +2768,54 @@ save_part_exec (struct _save_part_msg *m)
 }
 
 static void
-save_part_done (struct _save_part_msg *m)
+save_part_done (SavePartMsg *m)
 {
 	if (m->done)
-		m->done (m->part, m->path, !camel_exception_is_set (&m->base.ex), m->data);
+		m->done (m->part, m->path,
+			 !e_mail_msg_exception_is_set ((EMailMsg*) m),
+			 m->data);
 }
 
 static void
-save_part_free (struct _save_part_msg *m)
+save_part_msg_dispose (GObject *object)
 {
-	camel_object_unref (m->part);
+	SavePartMsg *m = (SavePartMsg*) object;
+
+	if (m->part) {
+		camel_object_unref (m->part);
+		m->part = NULL;
+	}
+
 	g_free (m->path);
+	m->path = NULL;
+
+	G_OBJECT_CLASS (save_part_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo save_part_info = {
-	sizeof (struct _save_part_msg),
-	(MailMsgDescFunc) save_part_desc,
-	(MailMsgExecFunc) save_part_exec,
-	(MailMsgDoneFunc) save_part_done,
-	(MailMsgFreeFunc) save_part_free
-};
+static void
+save_part_msg_class_init (SavePartMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = save_part_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) save_part_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) save_part_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) save_part_done;
+}
+
+static void
+save_part_msg_init (SavePartMsg *msg)
+{
+}
 
 gint
 mail_save_part (CamelMimePart *part, const gchar *path,
 		void (*done)(CamelMimePart *part, gchar *path, gint saved, gpointer data), gpointer data, gboolean readonly)
 {
-	struct _save_part_msg *m;
+	SavePartMsg *m;
 	gint id;
-	m = mail_msg_new (&save_part_info);
+	m = g_object_new (save_part_msg_get_type (), NULL);
 	m->part = part;
 	camel_object_ref (part);
 	m->path = g_strdup (path);
@@ -2288,39 +2823,52 @@ mail_save_part (CamelMimePart *part, const gchar *path,
 	m->done = done;
 	m->readonly = readonly;
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
 
 /* ** PREPARE OFFLINE ***************************************************** */
+/* XXX: Really?  how is PrepOfflineMsg different from PrepareOfflineMsg ??
+ * this one doesn't seem to be used anywhere...
+ */
 
+typedef struct _prep_offline_msg PrepOfflineMsg;
 struct _prep_offline_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelOperation *cancel;
 	gchar *uri;
 	void (*done)(const gchar *uri, gpointer data);
 	gpointer data;
 };
+typedef struct _PrepOfflineMsgClass PrepOfflineMsgClass;
+struct _PrepOfflineMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType prep_offline_msg_get_type ();
+G_DEFINE_TYPE (PrepOfflineMsg, prep_offline_msg, E_TYPE_MAIL_MSG);
 
 static void
-prep_offline_exec (struct _prep_offline_msg *m)
+prep_offline_exec (PrepOfflineMsg *m)
 {
 	CamelFolder *folder;
 
 	if (m->cancel)
 		camel_operation_register(m->cancel);
 
-	folder = mail_tool_uri_to_folder(m->uri, 0, &m->base.ex);
+	folder = mail_tool_uri_to_folder(m->uri, 0,
+					 e_mail_msg_get_exception ((EMailMsg*) m));
 	if (folder) {
 		if (CAMEL_IS_DISCO_FOLDER(folder)) {
 			camel_disco_folder_prepare_for_offline((CamelDiscoFolder *)folder,
 							       "(match-all)",
-							       &m->base.ex);
+							       e_mail_msg_get_exception ((EMailMsg*) m));
 		} else if (CAMEL_IS_OFFLINE_FOLDER (folder)) {
-			camel_offline_folder_downsync ((CamelOfflineFolder *) folder, "(match-all)", &m->base.ex);
+			camel_offline_folder_downsync ((CamelOfflineFolder *) folder, "(match-all)",
+						       e_mail_msg_get_exception ((EMailMsg*) m));
 		}
 		/* prepare_for_offline should do this? */
 		/* of course it should all be atomic, but ... */
@@ -2333,27 +2881,41 @@ prep_offline_exec (struct _prep_offline_msg *m)
 }
 
 static void
-prep_offline_done (struct _prep_offline_msg *m)
+prep_offline_done (PrepOfflineMsg *m)
 {
 	if (m->done)
 		m->done(m->uri, m->data);
 }
 
 static void
-prep_offline_free (struct _prep_offline_msg *m)
+prep_offline_msg_dispose (GObject *object)
 {
-	if (m->cancel)
+	PrepOfflineMsg *m = (PrepOfflineMsg*) object;
+	if (m->cancel) {
 		camel_operation_unref(m->cancel);
+		m->cancel = NULL;
+	}
 	g_free(m->uri);
+	m->uri = NULL;
+
+	G_OBJECT_CLASS (prep_offline_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo prep_offline_info = {
-	sizeof (struct _prep_offline_msg),
-	(MailMsgDescFunc) NULL, /* DO NOT CHANGE THIS, IT MUST BE NULL FOR CANCELLATION TO WORK */
-	(MailMsgExecFunc) prep_offline_exec,
-	(MailMsgDoneFunc) prep_offline_done,
-	(MailMsgFreeFunc) prep_offline_free
-};
+static void
+prep_offline_msg_class_init (PrepOfflineMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = prep_offline_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) prep_offline_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) prep_offline_done;
+}
+
+static void
+prep_offline_msg_init (PrepOfflineMsg *msg)
+{
+}
 
 void
 mail_prep_offline(const gchar *uri,
@@ -2361,9 +2923,9 @@ mail_prep_offline(const gchar *uri,
 		  void (*done)(const gchar *, gpointer data),
 		  gpointer data)
 {
-	struct _prep_offline_msg *m;
+	PrepOfflineMsg *m;
 
-	m = mail_msg_new(&prep_offline_info);
+	m = g_object_new (prep_offline_msg_get_type (), NULL);
 	m->cancel = cancel;
 	if (cancel)
 		camel_operation_ref(cancel);
@@ -2371,22 +2933,30 @@ mail_prep_offline(const gchar *uri,
 	m->data = data;
 	m->done = done;
 
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 /* ** GO OFFLINE ***************************************************** */
 
+typedef struct _set_offline_msg SetOfflineMsg;
 struct _set_offline_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelStore *store;
 	gboolean offline;
 	void (*done)(CamelStore *store, gpointer data);
 	gpointer data;
 };
+typedef struct _SetOfflineMsgClass SetOfflineMsgClass;
+struct _SetOfflineMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType set_offline_msg_get_type ();
+G_DEFINE_TYPE (SetOfflineMsg, set_offline_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-set_offline_desc (struct _set_offline_msg *m)
+set_offline_desc (SetOfflineMsg *m)
 {
 	gchar *service_name = camel_service_get_name (CAMEL_SERVICE (m->store), TRUE);
 	gchar *msg;
@@ -2398,66 +2968,82 @@ set_offline_desc (struct _set_offline_msg *m)
 }
 
 static void
-set_offline_exec (struct _set_offline_msg *m)
+set_offline_exec (SetOfflineMsg *m)
 {
 	if (CAMEL_IS_DISCO_STORE (m->store)) {
 		if (!m->offline) {
 			camel_disco_store_set_status (CAMEL_DISCO_STORE (m->store),
 						      CAMEL_DISCO_STORE_ONLINE,
-						      &m->base.ex);
+						      e_mail_msg_get_exception ((EMailMsg*) m));
 			return;
 		} else if (camel_disco_store_can_work_offline (CAMEL_DISCO_STORE (m->store))) {
 			camel_disco_store_set_status (CAMEL_DISCO_STORE (m->store),
 						      CAMEL_DISCO_STORE_OFFLINE,
-						      &m->base.ex);
+						      e_mail_msg_get_exception ((EMailMsg*) m));
 			return;
 		}
 	} else if (CAMEL_IS_OFFLINE_STORE (m->store)) {
 		if (!m->offline) {
 			camel_offline_store_set_network_state (CAMEL_OFFLINE_STORE (m->store),
 							       CAMEL_OFFLINE_STORE_NETWORK_AVAIL,
-							       &m->base.ex);
+							       e_mail_msg_get_exception ((EMailMsg*) m));
 			return;
 		} else {
 			camel_offline_store_set_network_state (CAMEL_OFFLINE_STORE (m->store),
 							       CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL,
-							       &m->base.ex);
+							       e_mail_msg_get_exception ((EMailMsg*) m));
 			return;
 		}
 	}
 
 	if (m->offline)
 		camel_service_disconnect (CAMEL_SERVICE (m->store),
-					  TRUE, &m->base.ex);
+					  TRUE, e_mail_msg_get_exception ((EMailMsg*) m));
 }
 
 static void
-set_offline_done (struct _set_offline_msg *m)
+set_offline_done (SetOfflineMsg *m)
 {
 	if (m->done)
 		m->done(m->store, m->data);
 }
 
 static void
-set_offline_free (struct _set_offline_msg *m)
+set_offline_msg_dispose (GObject *object)
 {
-	camel_object_unref(m->store);
+	SetOfflineMsg *m = (SetOfflineMsg*) object;
+
+	if (m->store ) {
+		camel_object_unref(m->store);
+		m->store = NULL;
+	}
+
+	G_OBJECT_CLASS (set_offline_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo set_offline_info = {
-	sizeof (struct _set_offline_msg),
-	(MailMsgDescFunc) set_offline_desc,
-	(MailMsgExecFunc) set_offline_exec,
-	(MailMsgDoneFunc) set_offline_done,
-	(MailMsgFreeFunc) set_offline_free
-};
+static void
+set_offline_msg_class_init (SetOfflineMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = set_offline_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) set_offline_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) set_offline_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) set_offline_done;
+}
+
+static void
+set_offline_msg_init (SetOfflineMsg *msg)
+{
+}
 
 gint
 mail_store_set_offline (CamelStore *store, gboolean offline,
 			void (*done)(CamelStore *, gpointer data),
 			gpointer data)
 {
-	struct _set_offline_msg *m;
+	SetOfflineMsg *m;
 	gint id;
 
 	/* Cancel any pending connect first so the set_offline_op
@@ -2466,23 +3052,37 @@ mail_store_set_offline (CamelStore *store, gboolean offline,
 	if (offline)
 		camel_service_cancel_connect (CAMEL_SERVICE (store));
 
-	m = mail_msg_new(&set_offline_info);
+	m = g_object_new (set_offline_msg_get_type (), NULL);
 	m->store = store;
 	camel_object_ref(store);
 	m->offline = offline;
 	m->data = data;
 	m->done = done;
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
 
 /* ** Prepare OFFLINE ***************************************************** */
 
+typedef struct
+{
+	SetOfflineMsg parent;
+} PrepareOfflineMsg;
+
+typedef struct
+{
+	SetOfflineMsgClass parent_class;
+} PrepareOfflineMsgClass;
+
+static GType prepare_offline_msg_get_type ();
+G_DEFINE_TYPE (PrepareOfflineMsg, prepare_offline_msg, set_offline_msg_get_type ());
+
 static gchar *
-prepare_offline_desc (struct _set_offline_msg *m)
+prepare_offline_desc (SetOfflineMsg *m)
 {
 	gchar *service_name = camel_service_get_name (CAMEL_SERVICE (m->store), TRUE);
 	gchar *msg;
@@ -2494,56 +3094,56 @@ prepare_offline_desc (struct _set_offline_msg *m)
 }
 
 static void
-prepare_offline_exec (struct _set_offline_msg *m)
+prepare_offline_exec (SetOfflineMsg *m)
 {
 	if (CAMEL_IS_DISCO_STORE (m->store)) {
 		camel_disco_store_prepare_for_offline (CAMEL_DISCO_STORE (m->store),
-					       &m->base.ex);
+						       e_mail_msg_get_exception ((EMailMsg*) m));
 	} else if (CAMEL_IS_OFFLINE_STORE (m->store)) {
 		camel_offline_store_prepare_for_offline (CAMEL_OFFLINE_STORE (m->store),
-							 &m->base.ex);
+							 e_mail_msg_get_exception ((EMailMsg*) m));
 	}
 }
 
 static void
-prepare_offline_done (struct _set_offline_msg *m)
+prepare_offline_done (SetOfflineMsg *m)
 {
 	if (m->done)
 		m->done (m->store, m->data);
 }
 
 static void
-prepare_offline_free (struct _set_offline_msg *m)
+prepare_offline_msg_class_init (PrepareOfflineMsgClass *klass)
 {
-	camel_object_unref (m->store);
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) prepare_offline_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) prepare_offline_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) prepare_offline_done;
 }
 
-static MailMsgInfo prepare_offline_info = {
-	sizeof (struct _set_offline_msg),
-	(MailMsgDescFunc) prepare_offline_desc,
-	(MailMsgExecFunc) prepare_offline_exec,
-	(MailMsgDoneFunc) prepare_offline_done,
-	(MailMsgFreeFunc) prepare_offline_free
-};
+static void
+prepare_offline_msg_init (PrepareOfflineMsg *msg)
+{
+}
 
 gint
 mail_store_prepare_offline (CamelStore *store)
 {
-	struct _set_offline_msg *m;
+	SetOfflineMsg *m;
 	gint id;
 
 	/* Cancel any pending connect first so the set_offline_op
 	 * thread won't get queued behind a hung connect op.
 	 */
 
-	m = mail_msg_new(&prepare_offline_info);
+	m = g_object_new (prepare_offline_msg_get_type (), NULL);
 	m->store = store;
 	camel_object_ref(store);
 	m->data = NULL;
 	m->done = NULL;
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
@@ -2559,8 +3159,9 @@ mail_execute_shell_command (CamelFilterDriver *driver, gint argc, gchar **argv,
 }
 
 /* Async service-checking/authtype-lookup code. */
+typedef struct _check_msg CheckServiceMsg;
 struct _check_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gchar *url;
 	CamelProviderType type;
@@ -2569,64 +3170,87 @@ struct _check_msg {
 	void (*done)(const gchar *url, CamelProviderType type, GList *types, gpointer data);
 	gpointer data;
 };
+typedef struct _CheckServiceMsgClass CheckServiceMsgClass;
+struct _CheckServiceMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType check_service_msg_get_type ();
+G_DEFINE_TYPE (CheckServiceMsg, check_service_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-check_service_desc (struct _check_msg *m)
+check_service_desc (CheckServiceMsg *m)
 {
 	return g_strdup(_("Checking Service"));
 }
 
 static void
-check_service_exec (struct _check_msg *m)
+check_service_exec (CheckServiceMsg *m)
 {
 	CamelService *service;
 
-	service = camel_session_get_service(session, m->url, m->type, &m->base.ex);
+	service = camel_session_get_service(session, m->url, m->type,
+					    e_mail_msg_get_exception ((EMailMsg*) m));
 	if (!service) {
-		camel_operation_unregister(m->base.cancel);
+		camel_operation_unregister(e_mail_msg_get_operation ((EMailMsg*) m));
 		return;
 	}
 
-	m->authtypes = camel_service_query_auth_types(service, &m->base.ex);
+	m->authtypes = camel_service_query_auth_types(service,
+						      e_mail_msg_get_exception ((EMailMsg*) m));
 	camel_object_unref(service);
 }
 
 static void
-check_service_done (struct _check_msg *m)
+check_service_done (CheckServiceMsg *m)
 {
 	if (m->done)
 		m->done(m->url, m->type, m->authtypes, m->data);
 }
 
 static void
-check_service_free (struct _check_msg *m)
+check_service_msg_finalize (GObject *object)
 {
+	CheckServiceMsg *m = (CheckServiceMsg*) object;
+
 	g_free(m->url);
 	g_list_free(m->authtypes);
+
+	G_OBJECT_CLASS (check_service_msg_parent_class)->finalize (object);
+}
+
+static void
+check_service_msg_class_init (CheckServiceMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = check_service_msg_finalize;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) check_service_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) check_service_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) check_service_done;
+}
+
+static void
+check_service_msg_init (CheckServiceMsg *msg)
+{
 }
 
-static MailMsgInfo check_service_info = {
-	sizeof (struct _check_msg),
-	(MailMsgDescFunc) check_service_desc,
-	(MailMsgExecFunc) check_service_exec,
-	(MailMsgDoneFunc) check_service_done,
-	(MailMsgFreeFunc) check_service_free
-};
 
 gint
 mail_check_service(const gchar *url, CamelProviderType type, void (*done)(const gchar *url, CamelProviderType type, GList *authtypes, gpointer data), gpointer data)
 {
-	struct _check_msg *m;
+	CheckServiceMsg *m;
 	gint id;
 
-	m = mail_msg_new (&check_service_info);
+	m = g_object_new (check_service_msg_get_type (), NULL);
 	m->url = g_strdup(url);
 	m->type = type;
 	m->done = done;
 	m->data = data;
 
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
diff --git a/mail/mail-ops.h b/mail/mail-ops.h
index 843ada5..ea94ee7 100644
--- a/mail/mail-ops.h
+++ b/mail/mail-ops.h
@@ -14,10 +14,12 @@
  *
  *
  * Authors:
- *		Peter Williams <peterw ximian com>
- *		Michael Zucchi <notzed ximian com>
+ *   Peter Williams <peterw ximian com>
+ *   Michael Zucchi <notzed ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -26,7 +28,7 @@
 
 G_BEGIN_DECLS
 
-#include "mail-mt.h"
+#include "e-mail-msg.h"
 
 #include "camel/camel-store.h"
 #include "camel/camel-folder.h"
@@ -36,6 +38,8 @@ G_BEGIN_DECLS
 
 #include "libedataserver/e-account.h"
 
+typedef void (*MailMsgDispatchFunc) (EMailMsg *msg);
+
 void mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info,
 		       void (*done)(CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info, gint ok,
 				    const gchar *appended_uid, gpointer data),
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index 1f2ee35..82f4acd 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -41,6 +41,7 @@
 #include "e-util/gconf-bridge.h"
 
 #include "e-mail-local.h"
+#include "e-mail-task-manager.h"
 #include "em-event.h"
 #include "em-filter-rule.h"
 #include "mail-config.h"
@@ -858,14 +859,21 @@ get_folders (CamelStore *store, GPtrArray *folders, CamelFolderInfo *info)
 	}
 }
 
+typedef struct _refresh_folders_msg RefreshFoldersMsg;
 struct _refresh_folders_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	struct _send_info *info;
 	GPtrArray *folders;
 	CamelStore *store;
 	CamelFolderInfo *finfo;
 };
+typedef struct _RefreshFoldersMsgClass RefreshFoldersMsgClass;
+struct _RefreshFoldersMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType refresh_folders_msg_get_type ();
+G_DEFINE_TYPE (RefreshFoldersMsg, refresh_folders_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
 refresh_folders_desc (struct _refresh_folders_msg *m)
@@ -907,42 +915,62 @@ refresh_folders_done (struct _refresh_folders_msg *m)
 }
 
 static void
-refresh_folders_free (struct _refresh_folders_msg *m)
+refresh_folders_msg_dispose (GObject *object)
 {
+	RefreshFoldersMsg *m = (RefreshFoldersMsg*) object;
 	gint i;
 
-	for (i=0;i<m->folders->len;i++)
-		g_free(m->folders->pdata[i]);
-	g_ptr_array_free(m->folders, TRUE);
+	if (m->folders) {
+		for (i=0;i<m->folders->len;i++)
+			g_free(m->folders->pdata[i]);
+		g_ptr_array_free(m->folders, TRUE);
+		m->folders = NULL;
+	}
+
+	if (m->store) {
+		camel_store_free_folder_info (m->store, m->finfo);
+		m->finfo = NULL;
+		camel_object_unref(m->store);
+		m->store = NULL;
+	}
 
-	camel_store_free_folder_info (m->store, m->finfo);
-	camel_object_unref(m->store);
+	G_OBJECT_CLASS (refresh_folders_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo refresh_folders_info = {
-	sizeof (struct _refresh_folders_msg),
-	(MailMsgDescFunc) refresh_folders_desc,
-	(MailMsgExecFunc) refresh_folders_exec,
-	(MailMsgDoneFunc) refresh_folders_done,
-	(MailMsgFreeFunc) refresh_folders_free
-};
+static void
+refresh_folders_msg_class_init (RefreshFoldersMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = refresh_folders_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) refresh_folders_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) refresh_folders_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) refresh_folders_done;
+}
+
+static void
+refresh_folders_msg_init (RefreshFoldersMsg *msg)
+{
+}
 
 static gboolean
 receive_update_got_folderinfo(CamelStore *store, CamelFolderInfo *info, gpointer data)
 {
 	if (info) {
 		GPtrArray *folders = g_ptr_array_new();
-		struct _refresh_folders_msg *m;
+		RefreshFoldersMsg *m;
 		struct _send_info *sinfo = data;
 
-		m = mail_msg_new(&refresh_folders_info);
+		m = g_object_new (refresh_folders_msg_get_type (), NULL);
 		m->store = store;
 		camel_object_ref(store);
 		m->folders = folders;
 		m->info = sinfo;
 		m->finfo = info;
 
-		mail_msg_unordered_push (m);
+		e_mail_task_manager_unordered_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 		/* do not free folder info, we will free it later */
 		return FALSE;
diff --git a/mail/mail-session.c b/mail/mail-session.c
index 0341b5f..afd0200 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -50,11 +50,12 @@
 #include "e-util/e-alert-dialog.h"
 #include "e-util/e-util-private.h"
 
+#include "e-mail-local.h"
+#include "e-mail-task-manager.h"
 #include "em-composer-utils.h"
 #include "em-filter-context.h"
 #include "em-filter-rule.h"
 #include "em-utils.h"
-#include "e-mail-local.h"
 #include "mail-config.h"
 #include "mail-mt.h"
 #include "mail-ops.h"
@@ -284,8 +285,9 @@ forget_password (CamelSession *session, CamelService *service, const gchar *doma
 static gpointer user_message_dialog;
 static GQueue user_message_queue = { NULL, NULL, 0 };
 
+typedef struct _user_message_msg UserMessageMsg;
 struct _user_message_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelSessionAlertType type;
 	gchar *prompt;
@@ -295,11 +297,17 @@ struct _user_message_msg {
 	guint result:1;
 	guint ismain:1;
 };
+typedef struct _UserMessageMsgClass UserMessageMsgClass;
+struct _UserMessageMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType user_message_msg_get_type ();
+G_DEFINE_TYPE (UserMessageMsg, user_message_msg, E_TYPE_MAIL_MSG);
 
-static void user_message_exec (struct _user_message_msg *m);
+static void user_message_exec (UserMessageMsg *m);
 
 static void
-user_message_response_free (GtkDialog *dialog, gint button, struct _user_message_msg *m)
+user_message_response_free (GtkDialog *dialog, gint button, UserMessageMsg *m)
 {
 	gtk_widget_destroy ((GtkWidget *) dialog);
 
@@ -309,13 +317,13 @@ user_message_response_free (GtkDialog *dialog, gint button, struct _user_message
 	if (!g_queue_is_empty (&user_message_queue)) {
 		m = g_queue_pop_head (&user_message_queue);
 		user_message_exec (m);
-		mail_msg_unref (m);
+		g_object_unref (m);
 	}
 }
 
 /* clicked, send back the reply */
 static void
-user_message_response (GtkDialog *dialog, gint button, struct _user_message_msg *m)
+user_message_response (GtkDialog *dialog, gint button, UserMessageMsg *m)
 {
 	/* if !allow_cancel, then we've already replied */
 	if (m->allow_cancel) {
@@ -327,12 +335,12 @@ user_message_response (GtkDialog *dialog, gint button, struct _user_message_msg
 }
 
 static void
-user_message_exec (struct _user_message_msg *m)
+user_message_exec (UserMessageMsg *m)
 {
 	const gchar *error_type;
 
 	if (!m->ismain && user_message_dialog != NULL) {
-		g_queue_push_tail (&user_message_queue, mail_msg_ref (m));
+		g_queue_push_tail (&user_message_queue, g_object_ref (m));
 		return;
 	}
 
@@ -394,19 +402,30 @@ user_message_exec (struct _user_message_msg *m)
 }
 
 static void
-user_message_free (struct _user_message_msg *m)
+user_message_msg_finalize (GObject *object)
 {
+	UserMessageMsg *m = (UserMessageMsg*) object;
+
 	g_free (m->prompt);
 	e_flag_free (m->done);
+
+	G_OBJECT_CLASS (user_message_msg_parent_class)->finalize (object);
 }
 
-static MailMsgInfo user_message_info = {
-	sizeof (struct _user_message_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) user_message_exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) user_message_free
-};
+static void
+user_message_msg_class_init (UserMessageMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = user_message_msg_finalize;
+
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) user_message_exec;
+}
+
+static void
+user_message_msg_init (UserMessageMsg *msg)
+{
+}
 
 static gboolean
 lookup_addressbook(CamelSession *session, const gchar *name)
@@ -428,33 +447,33 @@ lookup_addressbook(CamelSession *session, const gchar *name)
 static gboolean
 alert_user(CamelSession *session, CamelSessionAlertType type, const gchar *prompt, gboolean cancel)
 {
-	MailSession *mail_session = MAIL_SESSION (session);
-	struct _user_message_msg *m;
+	UserMessageMsg *m;
 	gboolean result = TRUE;
 
-	m = mail_msg_new (&user_message_info);
-	m->ismain = mail_in_main_thread ();
+	m = g_object_new (user_message_msg_get_type (), NULL);
+	m->ismain = e_in_main_thread ();
 	m->type = type;
 	m->prompt = g_strdup (prompt);
 	m->done = e_flag_new ();
 	m->allow_cancel = cancel;
 
 	if (cancel)
-		mail_msg_ref (m);
+		g_object_ref (m);
 
 	if (m->ismain)
 		user_message_exec (m);
 	else
-		mail_msg_main_loop_push (m);
+		e_mail_task_manager_main_loop_push
+			(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	if (cancel) {
 		e_flag_wait (m->done);
 		result = m->result;
-		mail_msg_unref (m);
+		g_object_ref (m);
 	}
 
 	if (m->ismain)
-		mail_msg_unref (m);
+		g_object_unref (m);
 
 	return result;
 }
@@ -601,9 +620,6 @@ get_filter_driver (CamelSession *session, const gchar *type, CamelException *ex)
 
 /* TODO: This is very temporary, until we have a better way to do the progress reporting,
    we just borrow a dummy mail-mt thread message and hook it onto out camel thread message */
-
-static MailMsgInfo ms_thread_info_dummy = { sizeof (MailMsg) };
-
 static gpointer ms_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, guint size)
 {
 	CamelSessionThreadMsg *msg = ms_parent_class->thread_msg_new(session, ops, size);
@@ -611,11 +627,11 @@ static gpointer ms_thread_msg_new(CamelSession *session, CamelSessionThreadOps *
 	/* We create a dummy mail_msg, and then copy its cancellation port over to ours, so
 	   we get cancellation and progress in common with hte existing mail code, for free */
 	if (msg) {
-		MailMsg *m = mail_msg_new(&ms_thread_info_dummy);
+		EMailMsg *m = g_object_new (E_TYPE_MAIL_MSG, NULL);
 
 		msg->data = m;
 		camel_operation_unref(msg->op);
-		msg->op = m->cancel;
+		msg->op = e_mail_msg_get_operation ((EMailMsg*) m);
 		camel_operation_ref(msg->op);
 	}
 
@@ -624,7 +640,7 @@ static gpointer ms_thread_msg_new(CamelSession *session, CamelSessionThreadOps *
 
 static void ms_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *m)
 {
-	mail_msg_unref(m->data);
+	g_object_unref (m->data);
 	ms_parent_class->thread_msg_free(session, m);
 }
 
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index 6301e5f..eb2ec1f 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -32,10 +32,14 @@
 #include <camel/camel-vtrash-folder.h>
 #include <libedataserver/e-account-list.h>
 
+#include "e-util/e-account-utils.h"
 #include "e-util/e-alert-dialog.h"
 #include "e-util/e-util-private.h"
-#include "e-util/e-account-utils.h"
+#include "e-util/e-util.h"
 
+#include "e-mail-local.h"
+#include "e-mail-store.h"
+#include "e-mail-task-manager.h"
 #include "em-folder-tree-model.h"
 #include "em-utils.h"
 #include "em-vfolder-context.h"
@@ -50,9 +54,6 @@
 #include "mail-tools.h"
 #include "mail-vfolder.h"
 
-#include "e-mail-local.h"
-#include "e-mail-store.h"
-
 #define d(x)  /* (printf("%s:%s: ",  G_STRLOC, G_STRFUNC), (x))*/
 
 static EMVFolderContext *context;	/* context remains open all time */
@@ -72,23 +73,30 @@ static void rule_changed(EFilterRule *rule, CamelFolder *folder);
 
 /* ********************************************************************** */
 
+typedef struct _setup_msg VFolderSetupMsg;
 struct _setup_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	CamelFolder *folder;
 	gchar *query;
 	GList *sources_uri;
 	GList *sources_folder;
 };
+typedef struct _VFolderSetupMsgClass VFolderSetupMsgClass;
+struct _VFolderSetupMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType vfolder_setup_msg_get_type ();
+G_DEFINE_TYPE (VFolderSetupMsg, vfolder_setup_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-vfolder_setup_desc (struct _setup_msg *m)
+vfolder_setup_desc (VFolderSetupMsg *m)
 {
 	return g_strdup_printf(_("Setting up Search Folder: %s"), m->folder->full_name);
 }
 
 static void
-vfolder_setup_exec (struct _setup_msg *m)
+vfolder_setup_exec (VFolderSetupMsg *m)
 {
 	GList *l, *list = NULL;
 	CamelFolder *folder;
@@ -101,12 +109,13 @@ vfolder_setup_exec (struct _setup_msg *m)
 	while (l && !shutdown) {
 		d(printf(" Adding uri: %s\n", (gchar *)l->data));
 
-		folder = mail_tool_uri_to_folder (l->data, 0, &m->base.ex);
+		folder = mail_tool_uri_to_folder (l->data, 0,
+						  e_mail_msg_get_exception ((EMailMsg*) m));
 		if (folder) {
 			list = g_list_append(list, folder);
 		} else {
 			g_warning("Could not open vfolder source: %s", (gchar *)l->data);
-			camel_exception_clear(&m->base.ex);
+			camel_exception_clear(e_mail_msg_get_exception ((EMailMsg*) m));
 		}
 		l = l->next;
 	}
@@ -131,73 +140,105 @@ vfolder_setup_exec (struct _setup_msg *m)
 }
 
 static void
-vfolder_setup_done (struct _setup_msg *m)
+vfolder_setup_done (VFolderSetupMsg *m)
 {
 }
 
 static void
-vfolder_setup_free (struct _setup_msg *m)
+vfolder_setup_msg_dispose (GObject *object)
 {
+	VFolderSetupMsg *m = (VFolderSetupMsg*) object;
+
 	GList *l;
 
-	camel_object_unref(m->folder);
+	if (m->folder) {
+		camel_object_unref(m->folder);
+		m->folder = NULL;
+	}
+
 	g_free(m->query);
+	m->query = NULL;
 
-	l = m->sources_uri;
-	while (l) {
-		g_free(l->data);
-		l = l->next;
+	if (m->sources_uri) {
+		l = m->sources_uri;
+		while (l) {
+			g_free(l->data);
+			l = l->next;
+		}
+		g_list_free(m->sources_uri);
+		m->sources_uri = NULL;
 	}
-	g_list_free(m->sources_uri);
 
-	l = m->sources_folder;
-	while (l) {
-		camel_object_unref(l->data);
-		l = l->next;
+	if (m->sources_folder) {
+		l = m->sources_folder;
+		while (l) {
+			camel_object_unref(l->data);
+			l = l->next;
+		}
+		g_list_free(m->sources_folder);
+		m->sources_folder = NULL;
 	}
-	g_list_free(m->sources_folder);
+
+	G_OBJECT_CLASS (vfolder_setup_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo vfolder_setup_info = {
-	sizeof (struct _setup_msg),
-	(MailMsgDescFunc) vfolder_setup_desc,
-	(MailMsgExecFunc) vfolder_setup_exec,
-	(MailMsgDoneFunc) vfolder_setup_done,
-	(MailMsgFreeFunc) vfolder_setup_free
-};
+static void
+vfolder_setup_msg_class_init (VFolderSetupMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = vfolder_setup_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) vfolder_setup_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) vfolder_setup_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) vfolder_setup_done;
+}
+
+static void
+vfolder_setup_msg_init (VFolderSetupMsg *msg)
+{
+}
 
 /* sources_uri should be camel uri's */
 static gint
 vfolder_setup(CamelFolder *folder, const gchar *query, GList *sources_uri, GList *sources_folder)
 {
-	struct _setup_msg *m;
+	VFolderSetupMsg *m;
 	gint id;
 
-	m = mail_msg_new(&vfolder_setup_info);
+	m = g_object_new (vfolder_setup_msg_get_type (), NULL);
 	m->folder = folder;
 	camel_object_ref(folder);
 	m->query = g_strdup(query);
 	m->sources_uri = sources_uri;
 	m->sources_folder = sources_folder;
 
-	id = m->base.seq;
-	mail_msg_slow_ordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
 
 /* ********************************************************************** */
 
+typedef struct _adduri_msg VFolderAdduriMsg;
 struct _adduri_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gchar *uri;
 	GList *folders;
 	gint remove;
 };
+typedef struct _VFolderAdduriMsgClass VFolderAdduriMsgClass;
+struct _VFolderAdduriMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType vfolder_adduri_msg_get_type ();
+G_DEFINE_TYPE (VFolderAdduriMsg, vfolder_adduri_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-vfolder_adduri_desc (struct _adduri_msg *m)
+vfolder_adduri_desc (VFolderAdduriMsg *m)
 {
 	gchar *euri, *desc = NULL;
 
@@ -242,7 +283,7 @@ vfolder_adduri_desc (struct _adduri_msg *m)
 }
 
 static void
-vfolder_adduri_exec (struct _adduri_msg *m)
+vfolder_adduri_exec (VFolderAdduriMsg *m)
 {
 	GList *l;
 	CamelFolder *folder = NULL;
@@ -262,7 +303,8 @@ vfolder_adduri_exec (struct _adduri_msg *m)
 	}
 
 	if (folder == NULL)
-		folder = mail_tool_uri_to_folder (m->uri, 0, &m->base.ex);
+		folder = mail_tool_uri_to_folder (m->uri, 0,
+						  e_mail_msg_get_exception ((EMailMsg*) m));
 
 	if (folder != NULL) {
 		l = m->folders;
@@ -278,40 +320,59 @@ vfolder_adduri_exec (struct _adduri_msg *m)
 }
 
 static void
-vfolder_adduri_done(struct _adduri_msg *m)
+vfolder_adduri_done(VFolderAdduriMsg *m)
 {
 }
 
 static void
-vfolder_adduri_free (struct _adduri_msg *m)
+vfolder_adduri_msg_dispose (GObject *object)
 {
-	g_list_foreach(m->folders, (GFunc)camel_object_unref, NULL);
-	g_list_free(m->folders);
+	VFolderAdduriMsg *m = (VFolderAdduriMsg*) object;
+
+	if (m->folders) {
+		g_list_foreach(m->folders, (GFunc)camel_object_unref, NULL);
+		g_list_free(m->folders);
+		m->folders = NULL;
+	}
+
 	g_free(m->uri);
+	m->uri = NULL;
+
+	G_OBJECT_CLASS (vfolder_adduri_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo vfolder_adduri_info = {
-	sizeof (struct _adduri_msg),
-	(MailMsgDescFunc) vfolder_adduri_desc,
-	(MailMsgExecFunc) vfolder_adduri_exec,
-	(MailMsgDoneFunc) vfolder_adduri_done,
-	(MailMsgFreeFunc) vfolder_adduri_free
-};
+static void
+vfolder_adduri_msg_class_init (VFolderAdduriMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = vfolder_adduri_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) vfolder_adduri_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) vfolder_adduri_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) vfolder_adduri_done;
+}
+
+static void
+vfolder_adduri_msg_init (VFolderAdduriMsg *msg)
+{
+}
 
 /* uri should be a camel uri */
 static gint
 vfolder_adduri(const gchar *uri, GList *folders, gint remove)
 {
-	struct _adduri_msg *m;
+	VFolderAdduriMsg *m;
 	gint id;
 
-	m = mail_msg_new(&vfolder_adduri_info);
+	m = g_object_new (vfolder_adduri_msg_get_type (), NULL);
 	m->folders = folders;
 	m->uri = g_strdup(uri);
 	m->remove = remove;
 
-	id = m->base.seq;
-	mail_msg_slow_ordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
@@ -458,7 +519,7 @@ mail_vfolder_add_uri(CamelStore *store, const gchar *curi, gint remove)
 		return;
 	}
 
-	g_return_if_fail (mail_in_main_thread());
+	g_return_if_fail (e_in_main_thread());
 
 	is_ignore = uri_is_ignore(store, curi);
 
@@ -604,7 +665,7 @@ mail_vfolder_delete_uri(CamelStore *store, const gchar *curi)
 
 	d(printf ("Deleting uri to check: %s\n", uri));
 
-	g_return_if_fail (mail_in_main_thread());
+	g_return_if_fail (e_in_main_thread());
 
 	changed = g_string_new ("");
 
@@ -692,7 +753,7 @@ mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto)
 	if (context == NULL || uri_is_spethal(store, cfrom) || uri_is_spethal(store, cto))
 		return;
 
-	g_return_if_fail (mail_in_main_thread());
+	g_return_if_fail (e_in_main_thread());
 
 	from = em_uri_from_camel(cfrom);
 	to = em_uri_from_camel(cto);
diff --git a/mail/message-list.c b/mail/message-list.c
index 6a674be..d5a9eaf 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -71,6 +71,7 @@
 #include "table/e-cell-hbox.h"
 
 #include "e-mail-label-list-store.h"
+#include "e-mail-task-manager.h"
 #include "em-utils.h"
 #include "mail-config.h"
 #include "mail-mt.h"
@@ -2093,8 +2094,9 @@ ml_tree_drag_data_get (ETree *tree, gint row, ETreePath path, gint col,
 
 /* TODO: merge this with the folder tree stuff via empopup targets */
 /* Drop handling */
+typedef struct _drop_msg DropMsg;
 struct _drop_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	GdkDragContext *context;
 
@@ -2110,9 +2112,15 @@ struct _drop_msg {
 	guint moved:1;
 	guint aborted:1;
 };
+typedef struct _DropMsgClass DropMsgClass;
+struct _DropMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType drop_msg_get_type ();
+G_DEFINE_TYPE (DropMsg, drop_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-ml_drop_async_desc (struct _drop_msg *m)
+ml_drop_async_desc (DropMsg *m)
 {
 	if (m->move)
 		return g_strdup_printf(_("Moving messages into folder %s"), m->folder->full_name);
@@ -2121,11 +2129,12 @@ ml_drop_async_desc (struct _drop_msg *m)
 }
 
 static void
-ml_drop_async_exec (struct _drop_msg *m)
+ml_drop_async_exec (DropMsg *m)
 {
 	switch (m->info) {
 	case DND_X_UID_LIST:
-		em_utils_selection_get_uidlist(m->selection, m->folder, m->action == GDK_ACTION_MOVE, &m->base.ex);
+		em_utils_selection_get_uidlist(m->selection, m->folder, m->action == GDK_ACTION_MOVE,
+					       e_mail_msg_get_exception ((EMailMsg*) m));
 		break;
 	case DND_MESSAGE_RFC822:
 		em_utils_selection_get_message(m->selection, m->folder);
@@ -2137,7 +2146,7 @@ ml_drop_async_exec (struct _drop_msg *m)
 }
 
 static void
-ml_drop_async_done (struct _drop_msg *m)
+ml_drop_async_done (DropMsg *m)
 {
 	gboolean success, delete;
 
@@ -2146,7 +2155,7 @@ ml_drop_async_done (struct _drop_msg *m)
 		success = FALSE;
 		delete = FALSE;
 	} else {
-		success = !camel_exception_is_set (&m->base.ex);
+		success = !e_mail_msg_exception_is_set ((EMailMsg*) m);
 		delete = success && m->move && !m->moved;
 	}
 
@@ -2154,28 +2163,52 @@ ml_drop_async_done (struct _drop_msg *m)
 }
 
 static void
-ml_drop_async_free (struct _drop_msg *m)
+drop_msg_dispose (GObject *object)
 {
-	g_object_unref(m->context);
-	camel_object_unref(m->folder);
+	DropMsg *m = (DropMsg*) object;
+
+	if (m->context) {
+		g_object_unref(m->context);
+		m->context = NULL;
+	}
+
+	if (m->folder) {
+		camel_object_unref(m->folder);
+		m->folder = NULL;
+	}
 
 	g_free(m->selection->data);
+	m->selection->data = NULL;
+
 	g_free(m->selection);
+	m->selection = NULL;
+
+	G_OBJECT_CLASS (drop_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo ml_drop_async_info = {
-	sizeof (struct _drop_msg),
-	(MailMsgDescFunc) ml_drop_async_desc,
-	(MailMsgExecFunc) ml_drop_async_exec,
-	(MailMsgDoneFunc) ml_drop_async_done,
-	(MailMsgFreeFunc) ml_drop_async_free
-};
+static void
+drop_msg_class_init (DropMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = drop_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) ml_drop_async_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) ml_drop_async_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) ml_drop_async_done;
+}
 
 static void
-ml_drop_action(struct _drop_msg *m)
+drop_msg_init (DropMsg *msg)
+{
+}
+
+static void
+ml_drop_action(DropMsg *m)
 {
 	m->move = m->action == GDK_ACTION_MOVE;
-	mail_msg_unordered_push (m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 }
 
 static void
@@ -2184,13 +2217,13 @@ ml_tree_drag_data_received (ETree *tree, gint row, ETreePath path, gint col,
 			    GtkSelectionData *data, guint info,
 			    guint time, MessageList *ml)
 {
-	struct _drop_msg *m;
+	DropMsg *m;
 
 	/* this means we are receiving no data */
 	if (!ml->folder || data->data == NULL || data->length == -1)
 		return;
 
-	m = mail_msg_new(&ml_drop_async_info);
+	m = g_object_new (drop_msg_get_type (), NULL);
 	m->context = context;
 	g_object_ref(context);
 	m->folder = ml->folder;
@@ -4314,8 +4347,9 @@ ml_sort_uids_by_tree (MessageList *ml, GPtrArray *uids)
 }
 
 /* ** REGENERATE MESSAGELIST ********************************************** */
+typedef struct _regen_list_msg RegenListMsg;
 struct _regen_list_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gint complete;
 
@@ -4335,7 +4369,14 @@ struct _regen_list_msg {
 	gint last_row; /* last selected (cursor) row */
 
 	xmlDoc *expand_state; /* stored expanded state of the previous view */
+	gboolean dispose_has_run;
+};
+typedef struct _RegenListMsgClass RegenListMsgClass;
+struct _RegenListMsgClass {
+	EMailMsgClass parent_class;
 };
+static GType regen_list_msg_get_type ();
+G_DEFINE_TYPE (RegenListMsg, regen_list_msg, E_TYPE_MAIL_MSG);
 
 /*
   maintain copy of summary
@@ -4348,13 +4389,13 @@ struct _regen_list_msg {
  */
 
 static gchar *
-regen_list_desc (struct _regen_list_msg *m)
+regen_list_desc (RegenListMsg *m)
 {
 	return g_strdup (_("Generating message list"));
 }
 
 static void
-regen_list_exec (struct _regen_list_msg *m)
+regen_list_exec (RegenListMsg *m)
 {
 	GPtrArray *uids, *uidnew, *showuids, *searchuids = NULL;
 	CamelMessageInfo *info;
@@ -4406,7 +4447,8 @@ regen_list_exec (struct _regen_list_msg *m)
 	if (expr == NULL) {
 		uids = camel_folder_get_uids (m->folder);
 	} else {
-		searchuids = uids = camel_folder_search_by_expression (m->folder, expr, &m->base.ex);
+		searchuids = uids = camel_folder_search_by_expression (m->folder, expr,
+								       e_mail_msg_get_exception ((EMailMsg*) m));
 		/* If m->changes is not NULL, then it means we are called from folder_changed event,
 		   thus we will keep the selected message to be sure it doesn't disappear because
 		   it no longer belong to our search filter. */
@@ -4444,14 +4486,15 @@ regen_list_exec (struct _regen_list_msg *m)
 		}
 	}
 
-	if (camel_exception_is_set (&m->base.ex))
+	if (e_mail_msg_exception_is_set ((EMailMsg*) m))
 		return;
 
 	/* perform hiding */
 	if (m->hideexpr && camel_folder_has_search_capability(m->folder)) {
-		uidnew = camel_folder_search_by_expression (m->ml->folder, m->hideexpr, &m->base.ex);
+		uidnew = camel_folder_search_by_expression (m->ml->folder, m->hideexpr,
+							    e_mail_msg_get_exception ((EMailMsg*) m));
 		/* well, lets not abort just because this faileld ... */
-		camel_exception_clear (&m->base.ex);
+		camel_exception_clear (e_mail_msg_get_exception ((EMailMsg*) m));
 
 		if (uidnew) {
 			MESSAGE_LIST_LOCK(m->ml, hide_lock);
@@ -4539,7 +4582,7 @@ regen_list_exec (struct _regen_list_msg *m)
 	e_profile_event_emit("list.threaduids", m->folder->full_name, 0);
 
 	/* camel_folder_summary_reload_from_db (m->folder->summary, NULL); */
-	if (!camel_operation_cancel_check(m->base.cancel)) {
+	if (!camel_operation_cancel_check(e_mail_msg_get_operation ((EMailMsg*) m))) {
 		/* update/build a new tree */
 		if (m->dotree) {
 			ml_sort_uids_by_tree (m->ml, showuids);
@@ -4581,7 +4624,7 @@ regen_list_exec (struct _regen_list_msg *m)
 }
 
 static void
-regen_list_done (struct _regen_list_msg *m)
+regen_list_done (RegenListMsg *m)
 {
 	ETree *tree;
 
@@ -4591,7 +4634,7 @@ regen_list_done (struct _regen_list_msg *m)
 	if (!m->complete)
 		return;
 
-	if (camel_operation_cancel_check(m->base.cancel))
+	if (camel_operation_cancel_check(e_mail_msg_get_operation ((EMailMsg*) m)))
 		return;
 
 	if (m->ml->folder != m->folder)
@@ -4687,10 +4730,16 @@ regen_list_done (struct _regen_list_msg *m)
 }
 
 static void
-regen_list_free (struct _regen_list_msg *m)
+regen_list_msg_dispose (GObject *object)
 {
+	RegenListMsg *m = (RegenListMsg*) object;
 	gint i;
 
+	if (m->dispose_has_run)
+		goto chain_up;
+
+	m->dispose_has_run = TRUE;
+
 	e_profile_event_emit("list.regenerated", m->folder->full_name, 0);
 
 	if (m->summary) {
@@ -4719,18 +4768,30 @@ regen_list_free (struct _regen_list_msg *m)
 		xmlFreeDoc (m->expand_state);
 
 	g_object_unref(m->ml);
+
+chain_up:
+	G_OBJECT_CLASS (regen_list_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo regen_list_info = {
-	sizeof (struct _regen_list_msg),
-	(MailMsgDescFunc) regen_list_desc,
-	(MailMsgExecFunc) regen_list_exec,
-	(MailMsgDoneFunc) regen_list_done,
-	(MailMsgFreeFunc) regen_list_free
-};
+static void
+regen_list_msg_class_init (RegenListMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = regen_list_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) regen_list_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) regen_list_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) regen_list_done;
+}
+
+static void
+regen_list_msg_init (RegenListMsg *msg)
+{
+}
 
 static gboolean
-ml_regen_timeout(struct _regen_list_msg *m)
+ml_regen_timeout(RegenListMsg *m)
 {
 	e_profile_event_emit("list.regenerate", m->folder->full_name, 0);
 
@@ -4738,7 +4799,8 @@ ml_regen_timeout(struct _regen_list_msg *m)
 	m->ml->regen = g_list_prepend(m->ml->regen, m);
 	g_mutex_unlock (m->ml->regen_lock);
 	/* TODO: we should manage our own thread stuff, would make cancelling outstanding stuff easier */
-	mail_msg_fast_ordered_push (m);
+	e_mail_task_manager_fast_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	m->ml->regen_timeout_msg = NULL;
 	m->ml->regen_timeout_id = 0;
@@ -4757,10 +4819,10 @@ mail_regen_cancel(MessageList *ml)
 
 		l = ml->regen;
 		while (l) {
-			MailMsg *mm = l->data;
+			EMailMsg *mm = l->data;
 
-			if (mm->cancel)
-				camel_operation_cancel(mm->cancel);
+			if (e_mail_msg_get_operation ((EMailMsg*) mm))
+				camel_operation_cancel(e_mail_msg_get_operation ((EMailMsg*) mm));
 			l = l->next;
 		}
 
@@ -4771,7 +4833,7 @@ mail_regen_cancel(MessageList *ml)
 	if (ml->regen_timeout_id) {
 		g_source_remove(ml->regen_timeout_id);
 		ml->regen_timeout_id = 0;
-		mail_msg_unref(ml->regen_timeout_msg);
+		g_object_unref (ml->regen_timeout_msg);
 		ml->regen_timeout_msg = NULL;
 	}
 }
@@ -4779,7 +4841,7 @@ mail_regen_cancel(MessageList *ml)
 static void
 mail_regen_list (MessageList *ml, const gchar *search, const gchar *hideexpr, CamelFolderChangeInfo *changes)
 {
-	struct _regen_list_msg *m;
+	RegenListMsg *m;
 	GConfClient *gconf;
 
 	/* report empty search as NULL, not as one/two-space string */
@@ -4810,7 +4872,7 @@ mail_regen_list (MessageList *ml, const gchar *search, const gchar *hideexpr, Ca
 	}
 #endif
 
-	m = mail_msg_new (&regen_list_info);
+	m = g_object_new (regen_list_msg_get_type (), NULL);
 	m->ml = ml;
 	m->search = g_strdup (search);
 	m->hideexpr = g_strdup (hideexpr);
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index ef25000..7ebdee6 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -43,6 +43,7 @@
 #include "e-mail-browser.h"
 #include "e-mail-reader.h"
 #include "e-mail-store.h"
+#include "e-mail-task-manager.h"
 #include "em-account-editor.h"
 #include "em-account-prefs.h"
 #include "em-composer-prefs.h"
@@ -335,6 +336,13 @@ exit:
 	camel_url_free (url);
 }
 
+static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
 static gboolean
 mail_shell_backend_handle_uri_cb (EShell *shell,
                                   const gchar *uri,
@@ -356,7 +364,7 @@ mail_shell_backend_handle_uri_cb (EShell *shell,
 			mail_get_folder (
 				curi, 0,
 				mail_shell_backend_handle_email_uri_cb,
-				mail_shell_backend, mail_msg_unordered_push);
+				mail_shell_backend, default_unordered_push);
 			g_free (curi);
 
 		} else {
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 139dd94..02baf19 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -20,6 +20,7 @@
  */
 
 #include "e-mail-shell-view-private.h"
+#include "mail/e-mail-task-manager.h"
 
 static void
 action_gal_save_custom_view_cb (GtkAction *action,
@@ -745,7 +746,7 @@ static void
 action_mail_stop_cb (GtkAction *action,
                      EMailShellView *mail_shell_view)
 {
-	mail_cancel_all ();
+	e_mail_task_manager_cancel_all ();
 }
 
 static void
diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c
index 85395fd..ff01571 100644
--- a/modules/mail/e-mail-shell-view-private.c
+++ b/modules/mail/e-mail-shell-view-private.c
@@ -22,6 +22,7 @@
 #include "e-mail-shell-view-private.h"
 
 #include "widgets/menus/gal-view-factory-etable.h"
+#include "mail/e-mail-task-manager.h"
 
 static void
 mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view,
@@ -670,6 +671,13 @@ mail_shell_view_create_filter_cb (CamelFolder *folder,
 	g_free (filter_data);
 }
 
+static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
 void
 e_mail_shell_view_create_filter_from_selected (EMailShellView *mail_shell_view,
                                                gint filter_type)
@@ -707,7 +715,7 @@ e_mail_shell_view_create_filter_from_selected (EMailShellView *mail_shell_view,
 		mail_get_message (
 			folder, uids->pdata[0],
 			mail_shell_view_create_filter_cb,
-			filter_data, mail_msg_unordered_push);
+			filter_data, default_unordered_push);
 	}
 
 	em_utils_uids_free (uids);
@@ -762,7 +770,7 @@ e_mail_shell_view_create_vfolder_from_selected (EMailShellView *mail_shell_view,
 		mail_get_message (
 			folder, uids->pdata[0],
 			mail_shell_view_create_vfolder_cb,
-			vfolder_data, mail_msg_unordered_push);
+			vfolder_data, default_unordered_push);
 	}
 
 	em_utils_uids_free (uids);
diff --git a/plugins/groupwise-features/share-folder-common.c b/plugins/groupwise-features/share-folder-common.c
index 14e3b0e..e51a8e1 100644
--- a/plugins/groupwise-features/share-folder-common.c
+++ b/plugins/groupwise-features/share-folder-common.c
@@ -29,6 +29,7 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <e-util/e-config.h>
+#include <mail/e-mail-task-manager.h>
 #include <mail/em-config.h>
 #include <mail/em-folder-properties.h>
 #include <mail/em-folder-tree.h>
@@ -118,8 +119,9 @@ shared_folder_abort (EPlugin *ep, EConfigTarget *target)
 	}
 }
 
+typedef struct _EMCreateFolder CreateFolderMsg;
 struct _EMCreateFolder {
-	MailMsg base;
+	EMailMsg base;
 
 	/* input data */
 	CamelStore *store;
@@ -131,29 +133,38 @@ struct _EMCreateFolder {
 	CamelFolderInfo *fi;
 
 	/* callback data */
-	void (* done) (struct _EMCreateFolder *m, gpointer user_data);
+	void (* done) (CreateFolderMsg *m, gpointer user_data);
 	gpointer user_data;
 };
 
+typedef struct _CreateFolderMsgClass CreateFolderMsgClass;
+struct _CreateFolderMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType create_folder_msg_get_type ();
+G_DEFINE_TYPE (CreateFolderMsg, create_folder_msg, E_TYPE_MAIL_MSG);
+
 static gchar *
-create_folder_desc (struct _EMCreateFolder *m)
+create_folder_desc (CreateFolderMsg *m)
 {
 	return g_strdup_printf (_("Creating folder `%s'"), m->full_name);
 }
 
 static void
-create_folder_exec (struct _EMCreateFolder *m)
+create_folder_exec (CreateFolderMsg *m)
 {
 	d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name));
 
-	if ((m->fi = camel_store_create_folder (m->store, m->parent, m->name, &m->base.ex))) {
+	if ((m->fi = camel_store_create_folder (m->store, m->parent, m->name,
+						e_mail_msg_get_exception ((EMailMsg*) m)))) {
 		if (camel_store_supports_subscriptions (m->store))
-			camel_store_subscribe_folder (m->store, m->full_name, &m->base.ex);
+			camel_store_subscribe_folder (m->store, m->full_name,
+						      e_mail_msg_get_exception ((EMailMsg*) m));
 	}
 }
 
 static void
-create_folder_done (struct _EMCreateFolder *m)
+create_folder_done (CreateFolderMsg *m)
 {
 	struct ShareInfo *ssi = (struct ShareInfo *) m->user_data;
 	CamelStore *store = CAMEL_STORE (m->store);
@@ -173,25 +184,45 @@ create_folder_done (struct _EMCreateFolder *m)
 }
 
 static void
-create_folder_free (struct _EMCreateFolder *m)
+create_folder_msg_dispose (GObject *object)
 {
-	camel_store_free_folder_info (m->store, m->fi);
-	camel_object_unref (m->store);
+	CreateFolderMsg *m = (CreateFolderMsg*) object;
+
+	if (m->store) {
+		camel_store_free_folder_info (m->store, m->fi);
+		camel_object_unref (m->store);
+		m->store = NULL;
+	}
+
 	g_free (m->full_name);
+	m->full_name = NULL;
 	g_free (m->parent);
+	m->parent = NULL;
 	g_free (m->name);
+	m->name = NULL;
+
+	G_OBJECT_CLASS (create_folder_msg_parent_class)->dispose (object);
 }
 
-static MailMsgInfo create_folder_info = {
-	sizeof (struct _EMCreateFolder),
-	(MailMsgDescFunc) create_folder_desc,
-	(MailMsgExecFunc) create_folder_exec,
-	(MailMsgDoneFunc) create_folder_done,
-	(MailMsgFreeFunc) create_folder_free
-};
+static void
+create_folder_msg_class_init (CreateFolderMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->dispose = create_folder_msg_dispose;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) create_folder_desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) create_folder_exec;
+	E_MAIL_MSG_CLASS (klass)->done = (MailMsgDoneFunc) create_folder_done;
+}
+
+static void
+create_folder_msg_init (CreateFolderMsg *msg)
+{
+}
 
 static void
-new_folder_created_cb (struct _EMCreateFolder *m, gpointer user_data)
+new_folder_created_cb (CreateFolderMsg *m, gpointer user_data)
 {
 	struct ShareInfo *ssi = (struct ShareInfo *) user_data;
 	EMFolderSelector *emfs = ssi->emfs;
@@ -205,10 +236,10 @@ new_folder_created_cb (struct _EMCreateFolder *m, gpointer user_data)
 }
 
 static gint
-create_folder (CamelStore *store, const gchar *full_name, void (* done) (struct _EMCreateFolder *m, gpointer user_data), gpointer user_data)
+create_folder (CamelStore *store, const gchar *full_name, void (* done) (CreateFolderMsg *m, gpointer user_data), gpointer user_data)
 {
 	gchar *name, *namebuf = NULL;
-	struct _EMCreateFolder *m;
+	CreateFolderMsg *m;
 	const gchar *parent;
 	gint id;
 
@@ -221,7 +252,7 @@ create_folder (CamelStore *store, const gchar *full_name, void (* done) (struct
 		parent = namebuf;
 	}
 
-	m = mail_msg_new (&create_folder_info);
+	m = g_object_new (create_folder_msg_get_type (), NULL);
 	camel_object_ref (store);
 	m->store = store;
 	m->full_name = g_strdup (full_name);
@@ -230,8 +261,9 @@ create_folder (CamelStore *store, const gchar *full_name, void (* done) (struct
 	m->user_data = (struct ShareInfo *) user_data;
 	m->done = done;
 	g_free (namebuf);
-	id = m->base.seq;
-	mail_msg_unordered_push (m);
+	id = e_mail_msg_get_id ((EMailMsg*) m);
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	return id;
 }
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 7f03570..bcbecea 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -44,13 +44,14 @@
 #include <libecal/e-cal-time-util.h>
 #include <libedataserverui/e-source-selector.h>
 #include <gtkhtml/gtkhtml-embedded.h>
-#include <mail/em-format-hook.h>
+#include <mail/e-mail-task-manager.h>
 #include <mail/em-config.h>
+#include <mail/em-format-hook.h>
 #include <mail/em-format-html.h>
 #include <mail/em-utils.h>
 #include <mail/mail-folder-cache.h>
-#include <mail/mail-tools.h>
 #include <mail/mail-mt.h>
+#include <mail/mail-tools.h>
 #include <libedataserver/e-account-list.h>
 #include <e-util/e-alert-dialog.h>
 #include <calendar/gui/calendar-config.h>
@@ -1809,20 +1810,27 @@ extract_itip_data (struct _itip_puri *pitip, GtkContainer *container, gboolean *
 	return TRUE;
 }
 
+typedef struct _opencal_msg OpencalMsg;
 struct _opencal_msg {
-	MailMsg base;
+	EMailMsg base;
 
 	gchar *command; /* command line to run */
 };
+typedef struct _OpencalMsgClass OpencalMsgClass;
+struct _OpencalMsgClass {
+	EMailMsgClass parent_class;
+};
+static GType opencal_msg_get_type ();
+G_DEFINE_TYPE (OpencalMsg, opencal_msg, E_TYPE_MAIL_MSG);
 
 static gchar *
-open_calendar__desc (struct _opencal_msg *m, gint complete)
+open_calendar__desc (OpencalMsg *m, gint complete)
 {
 	return g_strdup (_("Opening calendar"));
 }
 
 static void
-open_calendar__exec (struct _opencal_msg *m)
+open_calendar__exec (OpencalMsg *m)
 {
 	if (!g_spawn_command_line_async (m->command, NULL)) {
 		g_warning ("Could not launch %s", m->command);
@@ -1830,32 +1838,45 @@ open_calendar__exec (struct _opencal_msg *m)
 }
 
 static void
-open_calendar__free (struct _opencal_msg *m)
+opencal_msg_finalize (GObject *object)
 {
+	OpencalMsg *m = (OpencalMsg*) object;
+
 	g_free (m->command);
 	m->command = NULL;
+
+	G_OBJECT_CLASS (opencal_msg_parent_class)->finalize (object);
 }
 
-static MailMsgInfo open_calendar_info = {
-	sizeof (struct _opencal_msg),
-	(MailMsgDescFunc) open_calendar__desc,
-	(MailMsgExecFunc) open_calendar__exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) open_calendar__free,
-};
+static void
+opencal_msg_class_init (OpencalMsgClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = opencal_msg_finalize;
+
+	E_MAIL_MSG_CLASS (klass)->desc = (MailMsgDescFunc) open_calendar__desc;
+	E_MAIL_MSG_CLASS (klass)->exec = (MailMsgExecFunc) open_calendar__exec;
+}
+
+static void
+opencal_msg_init (OpencalMsg *msg)
+{
+}
 
 static gboolean
 idle_open_cb (gpointer data)
 {
 	struct _itip_puri *pitip = data;
-	struct _opencal_msg *m;
+	OpencalMsg *m;
 	gchar *start, *end;
 
 	start = isodate_from_time_t (pitip->start_time);
 	end = isodate_from_time_t (pitip->end_time);
-	m = mail_msg_new (&open_calendar_info);
+	m = g_object_new (opencal_msg_get_type (), NULL);
 	m->command = g_strdup_printf ("evolution \"calendar://?startdate=%s&enddate=%s\"", start, end);
-	mail_msg_slow_ordered_push (m);
+	e_mail_task_manager_slow_ordered_push
+		(e_mail_task_manager_get_default (), (EMailMsg*) m);
 
 	g_free (start);
 	g_free (end);
diff --git a/plugins/mailing-list-actions/mailing-list-actions.c b/plugins/mailing-list-actions/mailing-list-actions.c
index 59e54e6..d5fdf6e 100644
--- a/plugins/mailing-list-actions/mailing-list-actions.c
+++ b/plugins/mailing-list-actions/mailing-list-actions.c
@@ -37,6 +37,7 @@
 #include "composer/e-msg-composer.h"
 #include "mail/e-mail-browser.h"
 #include "mail/e-mail-reader.h"
+#include "mail/e-mail-task-manager.h"
 #include "mail/em-composer-utils.h"
 #include "mail/em-format-hook.h"
 #include "mail/em-config.h"
@@ -199,6 +200,13 @@ exit:
 }
 
 static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
+static void
 emla_list_action (EMailReader *reader,
                   EmlaAction action)
 {
@@ -221,7 +229,7 @@ emla_list_action (EMailReader *reader,
 	mail_get_message (
 		folder, uids->pdata[0],
 		emla_list_action_do, data,
-		mail_msg_unordered_push);
+		default_unordered_push);
 
 	em_utils_uids_free (uids);
 }
diff --git a/plugins/mark-all-read/mark-all-read.c b/plugins/mark-all-read/mark-all-read.c
index baaa80c..4693fd3 100644
--- a/plugins/mark-all-read/mark-all-read.c
+++ b/plugins/mark-all-read/mark-all-read.c
@@ -29,6 +29,7 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <e-util/e-plugin-ui.h>
+#include <mail/e-mail-task-manager.h>
 #include <mail/em-folder-tree.h>
 #include <mail/mail-ops.h>
 #include <mail/mail-mt.h>
@@ -316,6 +317,13 @@ has_unread_mail (GtkTreeModel *model, GtkTreeIter *parent, gboolean is_root, gbo
 }
 
 static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
+static void
 action_mail_mark_read_recursive_cb (GtkAction *action,
                                     EShellView *shell_view)
 {
@@ -329,7 +337,7 @@ action_mail_mark_read_recursive_cb (GtkAction *action,
 	g_return_if_fail (folder_uri != NULL);
 
 	mail_get_folder (
-		folder_uri, 0, mar_got_folder, NULL, mail_msg_unordered_push);
+		folder_uri, 0, mar_got_folder, NULL, default_unordered_push);
 
 	g_free (folder_uri);
 	g_object_unref (folder_tree);
diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c
index 1ed02dd..3f5dc99 100644
--- a/plugins/templates/templates.c
+++ b/plugins/templates/templates.c
@@ -37,6 +37,7 @@
 
 #include <mail/e-mail-local.h>
 #include <mail/e-mail-reader.h>
+#include <mail/e-mail-task-manager.h>
 #include <mail/em-composer-utils.h>
 #include <mail/em-utils.h>
 #include <mail/mail-session.h>
@@ -522,6 +523,13 @@ create_new_message (CamelFolder *folder, const gchar *uid, CamelMimeMessage *mes
 }
 
 static void
+default_unordered_push (EMailMsg *msg)
+{
+	e_mail_task_manager_unordered_push
+		(e_mail_task_manager_get_default (), msg);
+}
+
+static void
 action_reply_with_template_cb (GtkAction *action,
                                const gchar *message_uid)
 {
@@ -534,7 +542,8 @@ action_reply_with_template_cb (GtkAction *action,
 
 	g_object_ref (G_OBJECT (action));
 
-	mail_get_message (folder, message_uid, create_new_message, action, mail_msg_unordered_push);
+	mail_get_message (folder, message_uid, create_new_message, action,
+			  default_unordered_push);
 
 	g_object_unref (G_OBJECT (action));
 }
diff --git a/shell/main.c b/shell/main.c
index eb8e566..d06b927 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -498,8 +498,7 @@ main (gint argc, gchar **argv)
 	}
 
 	g_type_init ();
-	if (!g_thread_get_initialized ())
-		g_thread_init (NULL);
+	e_thread_init ();
 	dbus_g_thread_init ();
 
 #ifdef G_OS_WIN32



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]