Modified webpage: now tinymail repository is in gitorious.
[modest] / src / modest-mail-operation.c
index e8cfaeb..20f58fc 100644 (file)
@@ -67,6 +67,8 @@
 #include <clockd/libtime.h>
 #endif
 #include "modest-account-protocol.h"
+#include <camel/camel-stream-null.h>
+#include <widgets/modest-msg-view-window.h>
 
 #define KB 1024
 
@@ -138,6 +140,7 @@ typedef struct
        TnyFolderObserver *inbox_observer;
        gboolean interactive;
        gboolean msg_readed;
+       gboolean update_folder_counts;
 } UpdateAccountInfo;
 
 static void destroy_update_account_info         (UpdateAccountInfo *info);
@@ -194,6 +197,8 @@ typedef struct {
        gint last_total_bytes;
        gint sum_total_bytes;
        gint total_bytes;
+       TnyIterator *get_parts;
+       TnyMsg *msg;
 } GetMsgInfo;
 
 typedef struct _RefreshAsyncHelper {   
@@ -223,6 +228,12 @@ typedef struct _XFerFolderAsyncHelper
        gpointer user_data;
 } XFerFolderAsyncHelper;
 
+typedef struct _SyncFolderHelper {
+       ModestMailOperation *mail_op;
+       SyncFolderCallback user_callback;
+       gpointer user_data;
+} SyncFolderHelper;
+
 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
                                                      TnyMsg *msg,
                                                      gpointer userdata);
@@ -235,6 +246,7 @@ static void          modest_mail_operation_create_msg (ModestMailOperation *self
                                                       const GList *images_list,
                                                       TnyHeaderFlags priority_flags,
                                                       const gchar *references, const gchar *in_reply_to,
+                                                      TnyList *header_pairs,
                                                       ModestMailOperationCreateMsgCallback callback,
                                                       gpointer userdata);
 
@@ -254,6 +266,7 @@ typedef struct
        GList *attachments_list;
        GList *images_list;
        TnyHeaderFlags priority_flags;
+       TnyList *header_pairs;
        ModestMailOperationCreateMsgCallback callback;
        gpointer userdata;
 } CreateMsgInfo;
@@ -842,6 +855,7 @@ create_msg_thread (gpointer thread_data)
                                              info->references, info->in_reply_to,
                                              info->plain_body, 
                                              info->attachments_list, &attached,
+                                             info->header_pairs,
                                              &(priv->error));
        } else {
                new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
@@ -850,15 +864,16 @@ create_msg_thread (gpointer thread_data)
                                                         info->html_body,
                                                         info->plain_body, info->attachments_list,
                                                         info->images_list, &attached,
+                                                        info->header_pairs,
                                                         &(priv->error));
        }
 
        if (new_msg) {
-               TnyHeader *header;
+               TnyHeader *header = tny_msg_get_header (new_msg);
 
                /* Set priority flags in message */
-               header = tny_msg_get_header (new_msg);
-               tny_header_set_flag (header, info->priority_flags);
+               if (info->priority_flags != TNY_HEADER_FLAG_NORMAL_PRIORITY)
+                       tny_header_set_flag (header, info->priority_flags);
 
                /* Set attachment flags in message */
                if (info->attachments_list != NULL && attached > 0)
@@ -887,6 +902,7 @@ create_msg_thread (gpointer thread_data)
        g_list_free (info->attachments_list);
        g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
        g_list_free (info->images_list);
+       g_object_unref (info->header_pairs);
 
        if (info->callback) {
                CreateMsgIdleInfo *idle_info;
@@ -918,6 +934,7 @@ modest_mail_operation_create_msg (ModestMailOperation *self,
                                  TnyHeaderFlags priority_flags,
                                  const gchar *references,
                                  const gchar *in_reply_to,
+                                 TnyList *header_pairs,
                                  ModestMailOperationCreateMsgCallback callback,
                                  gpointer userdata)
 {
@@ -939,7 +956,8 @@ modest_mail_operation_create_msg (ModestMailOperation *self,
        g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
        info->images_list = g_list_copy ((GList *) images_list);
        g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
-       info->priority_flags = priority_flags;
+       info->priority_flags = 0 | priority_flags;
+       info->header_pairs = tny_list_copy (header_pairs);
 
        info->callback = callback;
        info->userdata = userdata;
@@ -1085,6 +1103,56 @@ end:
 }
 
 void
+modest_mail_operation_send_mail (ModestMailOperation *self,
+                                TnyTransportAccount *transport_account,
+                                TnyMsg *msg)
+{
+       TnySendQueue *send_queue = NULL;
+       ModestMailOperationPrivate *priv = NULL;
+
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
+
+       if (!msg) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               modest_mail_operation_notify_end (self);
+               return;
+       }
+
+       if (priv->error && priv->error->code != MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               modest_mail_operation_notify_end (self);
+               return;
+       }
+
+       /* Add message to send queue */
+       send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
+       if (!TNY_IS_SEND_QUEUE(send_queue)) {
+               if (priv->error) {
+                       g_error_free (priv->error);
+                       priv->error = NULL;
+               }
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
+                            "modest: could not find send queue for account\n");
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               modest_mail_operation_notify_end (self);
+               return;
+       } else {
+               SendNewMailHelper *helper = g_slice_new (SendNewMailHelper);
+               helper->mail_op = g_object_ref (self);
+               helper->notify = TRUE;
+
+               /* Add the msg to the queue. The callback will free
+                  the helper */
+               modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue), 
+                                                                 FALSE);
+               tny_send_queue_add_async (send_queue, msg, send_mail_on_added_to_outbox, 
+                                         NULL, helper);
+       }
+
+}
+
+void
 modest_mail_operation_send_new_mail (ModestMailOperation *self,
                                     TnyTransportAccount *transport_account,
                                     TnyMsg *draft_msg,
@@ -1096,7 +1164,8 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
                                     const GList *images_list,
                                     const gchar *references,
                                     const gchar *in_reply_to,
-                                    TnyHeaderFlags priority_flags)
+                                    TnyHeaderFlags priority_flags,
+                                    TnyList *header_pairs)
 {
        ModestMailOperationPrivate *priv = NULL;
        SendNewMailInfo *info;
@@ -1133,6 +1202,7 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
        modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
                                          attachments_list, images_list, priority_flags,
                                          references, in_reply_to,
+                                         header_pairs,
                                          modest_mail_operation_send_new_mail_cb, info);
 
 }
@@ -1364,6 +1434,7 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
                                      TnyHeaderFlags priority_flags,
                                      const gchar *references,
                                      const gchar *in_reply_to,
+                                     TnyList *header_pairs,
                                      SaveToDraftstCallback callback,
                                      gpointer user_data)
 {
@@ -1390,6 +1461,7 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
        modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
                                          attachments_list, images_list, priority_flags,
                                          references, in_reply_to,
+                                         header_pairs,
                                          modest_mail_operation_save_to_drafts_cb, info);
 }
 
@@ -1499,6 +1571,9 @@ update_account_send_mail (UpdateAccountInfo *info)
        TnyTransportAccount *transport_account = NULL;
        ModestTnyAccountStore *account_store;
 
+       if (info->update_folder_counts)
+               return;
+
        account_store = modest_runtime_get_account_store ();
 
        /* We don't try to send messages while sending mails is blocked */
@@ -1597,6 +1672,8 @@ update_account_get_msg_async_cb (TnyFolder *folder,
                update_account_notify_user_and_free (info, new_headers);
 
                /* Delete the helper */
+               if (msg_info->msg)
+                       g_object_unref (msg_info->msg);
                g_object_unref (msg_info->more_msgs);
                g_object_unref (msg_info->mail_op);
                g_slice_free (GetMsgInfo, msg_info);
@@ -1634,7 +1711,7 @@ inbox_refreshed_cb (TnyFolder *inbox,
        ModestMailOperationPrivate *priv;
        TnyIterator *new_headers_iter;
        GPtrArray *new_headers_array = NULL;
-       gint max_size, retrieve_limit, i;
+       gint max_size = G_MAXINT, retrieve_limit, i;
        ModestAccountMgr *mgr;
        ModestAccountRetrieveType retrieve_type;
        TnyList *new_headers = NULL;
@@ -1669,29 +1746,36 @@ inbox_refreshed_cb (TnyFolder *inbox,
                goto send_mail;
        }
 
-       /* Set the last updated as the current time */
+       if (!info->update_folder_counts) {
+               /* Set the last updated as the current time */
 #ifdef MODEST_USE_LIBTIME
-       struct tm utc_tm;
-       time_get_utc (&utc_tm);
-       time_to_store = time_mktime (&utc_tm, "GMT");
+               struct tm utc_tm;
+               time_get_utc (&utc_tm);
+               time_to_store = time_mktime (&utc_tm, "GMT");
 #else
-       time_to_store = time (NULL);
+               time_to_store = time (NULL);
 #endif
-       modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
+               modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
 
-       /* Get the message max size */
-       max_size  = modest_conf_get_int (modest_runtime_get_conf (),
-                                        MODEST_CONF_MSG_SIZE_LIMIT, NULL);
-       if (max_size == 0)
-               max_size = G_MAXINT;
-       else
-               max_size = max_size * KB;
+               /* Get the message max size */
+               max_size  = modest_conf_get_int (modest_runtime_get_conf (),
+                                                MODEST_CONF_MSG_SIZE_LIMIT, NULL);
+               if (max_size == 0)
+                       max_size = G_MAXINT;
+               else
+                       max_size = max_size * KB;
+       }
 
        /* Create the new headers array. We need it to sort the
           new headers by date */
        new_headers_array = g_ptr_array_new ();
        if (info->inbox_observer) {
                new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
+               if (!tny_iterator_is_done (new_headers_iter)) {
+                       modest_platform_emit_folder_updated_signal (info->account_name, tny_folder_get_id (TNY_FOLDER (inbox)));
+                       modest_account_mgr_set_has_new_mails (modest_runtime_get_account_mgr (),
+                                                             info->account_name, TRUE);
+               }
                while (!tny_iterator_is_done (new_headers_iter)) {
                        TnyHeader *header = NULL;
 
@@ -1753,6 +1837,7 @@ inbox_refreshed_cb (TnyFolder *inbox,
                msg_info->mail_op = g_object_ref (info->mail_op);
                msg_info->total_bytes = compute_message_list_size (new_headers, priv->total);
                msg_info->more_msgs = g_object_ref (iter);
+               msg_info->msg = NULL;
                msg_info->user_data = info;
 
                while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) {
@@ -1899,7 +1984,7 @@ recurse_folders_async_cb (TnyFolderStore *folder_store,
 
                        folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
 
-                       if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
+                       if (!info->update_folder_counts && tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
                                /* Get a reference to the INBOX */
                                inbox = g_object_ref (folder);
                        } else {
@@ -1992,6 +2077,7 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        info->mail_op = g_object_ref (self);
        info->poke_all = poke_all;
        info->interactive = interactive;
+       info->update_folder_counts = FALSE;
        info->account_name = g_strdup (account_name);
        info->callback = callback;
        info->user_data = user_data;
@@ -2021,6 +2107,86 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        
 }
 
+void
+modest_mail_operation_update_folder_counts (ModestMailOperation *self,
+                                     const gchar *account_name)
+{
+       UpdateAccountInfo *info = NULL;
+       ModestMailOperationPrivate *priv = NULL;
+       ModestTnyAccountStore *account_store = NULL;
+       TnyList *folders;
+       ModestMailOperationState *state;
+
+       /* Init mail operation */
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
+       priv->total = 0;
+       priv->done  = 0;
+       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
+       priv->op_type = MODEST_MAIL_OPERATION_TYPE_UPDATE_FOLDER_COUNTS;
+
+       /* Get the store account */
+       account_store = modest_runtime_get_account_store ();
+       priv->account =
+               modest_tny_account_store_get_server_account (account_store,
+                                                            account_name,
+                                                            TNY_ACCOUNT_TYPE_STORE);
+
+       /* The above function could return NULL */
+       if (!priv->account) {
+               /* Check if the operation was a success */
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
+                            "no account");
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+
+               /* Notify about operation end */
+               modest_mail_operation_notify_end (self);
+
+               return;
+       }
+       
+       /* We have once seen priv->account getting finalized during this code,
+        * therefore adding a reference (bug #82296) */
+       
+       g_object_ref (priv->account);
+
+       /* Create the helper object */
+       info = g_slice_new0 (UpdateAccountInfo);
+       info->pending_calls = 1;
+       info->folders = tny_simple_list_new ();
+       info->mail_op = g_object_ref (self);
+       info->poke_all = TRUE;
+       info->interactive = FALSE;
+       info->update_folder_counts = TRUE;
+       info->account_name = g_strdup (account_name);
+       info->callback = NULL;
+       info->user_data = NULL;
+
+       /* Set account busy */
+       modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
+       modest_mail_operation_notify_start (self);
+
+       /* notify about the start of the operation */ 
+       state = modest_mail_operation_clone_state (self);
+       state->done = 0;
+       state->total = 0;
+
+       /* Start notifying progress */
+       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
+       g_slice_free (ModestMailOperationState, state);
+       
+       /* Get all folders and continue in the callback */ 
+       folders = tny_simple_list_new ();
+       tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
+                                           folders, NULL, TRUE,
+                                           recurse_folders_async_cb, 
+                                           NULL, info);
+       g_object_unref (folders);
+       
+       g_object_unref (priv->account);
+       
+}
+
 /*
  * Used to notify the queue from the main
  * loop. We call it inside an idle call to achieve that
@@ -2132,7 +2298,7 @@ modest_mail_operation_create_folder (ModestMailOperation *self,
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
-                            _CS("ckdg_ib_folder_already_exists"));
+                            _CS_FOLDER_ALREADY_EXISTS);
        }
 
        /* Check parent */
@@ -2372,7 +2538,7 @@ new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
-                            _CS("ckdg_ib_folder_already_exists"));
+                            _CS_FOLDER_ALREADY_EXISTS);
                return FALSE;
        } else
                return TRUE;
@@ -2462,7 +2628,7 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
        g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                     MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
-                    error_msg);
+                    "%s", error_msg);
 
        /* Call the user callback if exists */
        if (user_callback)
@@ -2593,6 +2759,8 @@ modest_mail_operation_find_msg (ModestMailOperation *self,
        helper->sum_total_bytes = 0;
        helper->total_bytes = 0;
        helper->more_msgs = NULL;
+       helper->get_parts = NULL;
+       helper->msg = NULL;
 
        modest_mail_operation_notify_start (self);
        
@@ -2660,6 +2828,91 @@ modest_mail_operation_get_msg (ModestMailOperation *self,
        helper->sum_total_bytes = 0;
        helper->total_bytes = tny_header_get_message_size (header);
        helper->more_msgs = NULL;
+       helper->get_parts = NULL;
+       helper->msg = NULL;
+
+       modest_mail_operation_notify_start (self);
+       
+       /* notify about the start of the operation */ 
+       ModestMailOperationState *state;
+       state = modest_mail_operation_clone_state (self);
+       state->done = 0;
+       state->total = 0;
+       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 
+                               0, state, NULL);
+       g_slice_free (ModestMailOperationState, state);
+       
+       tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
+
+       g_object_unref (G_OBJECT (folder));
+}
+
+void 
+modest_mail_operation_get_msg_and_parts (ModestMailOperation *self,
+                                        TnyHeader *header,
+                                        TnyList *parts,
+                                        gboolean progress_feedback,
+                                        GetMsgAsyncUserCallback user_callback,
+                                        gpointer user_data)
+{
+       GetMsgInfo *helper = NULL;
+       TnyFolder *folder;
+       ModestMailOperationPrivate *priv;
+       
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
+       g_return_if_fail (TNY_IS_HEADER (header));
+       
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
+       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
+       priv->total = 1;
+       priv->done = 0;
+
+       /* Check memory low */
+       if (_check_memory_low (self)) {
+               if (user_callback)
+                       user_callback (self, header, FALSE, NULL, priv->error, user_data);
+               modest_mail_operation_notify_end (self);
+               return;
+       }
+
+       /* Get account and set it into mail_operation */
+       folder = tny_header_get_folder (header);
+       if (folder == NULL && MODEST_IS_MSG_VIEW_WINDOW (priv->source)) {
+               const gchar *acc_name;
+               acc_name = modest_window_get_active_account (MODEST_WINDOW (priv->source));
+               priv->account = modest_tny_account_store_get_server_account
+                       (modest_runtime_get_account_store (),
+                        acc_name,
+                        TNY_ACCOUNT_TYPE_STORE);
+               folder = modest_tny_folder_store_find_folder_from_uri (TNY_FOLDER_STORE (priv->account), 
+                                                                      modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (priv->source)));
+       } else {
+               priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
+       }
+       
+       /* Check for cached messages */
+       if (progress_feedback) {
+               if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
+                       priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
+               else 
+                       priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
+       } else {
+               priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
+       }
+       
+       /* Create the helper */
+       helper = g_slice_new0 (GetMsgInfo);
+       helper->header = g_object_ref (header);
+       helper->mail_op = g_object_ref (self);
+       helper->user_callback = user_callback;
+       helper->user_data = user_data;
+       helper->destroy_notify = NULL;
+       helper->last_total_bytes = 0;
+       helper->sum_total_bytes = 0;
+       helper->total_bytes = tny_header_get_message_size (header);
+       helper->more_msgs = NULL;
+       helper->get_parts = tny_list_create_iterator (parts);
+       helper->msg = NULL;
 
        modest_mail_operation_notify_start (self);
        
@@ -2699,6 +2952,23 @@ get_msg_status_cb (GObject *obj,
 }
 
 static void
+get_msg_async_get_part_cb (TnyMimePart *self, gboolean cancelled, TnyStream *stream, GError *err, gpointer user_data)
+{
+       GetMsgInfo *helper;
+       TnyFolder *folder = NULL;
+
+       helper = (GetMsgInfo *) user_data;
+
+       if (helper->header) {
+               folder = tny_header_get_folder (helper->header);
+       }
+
+       get_msg_async_cb (folder, cancelled, helper->msg, err, user_data);
+
+       if (folder) g_object_unref (folder);
+}
+
+static void
 get_msg_async_cb (TnyFolder *folder, 
                  gboolean canceled, 
                  TnyMsg *msg, 
@@ -2717,6 +2987,9 @@ get_msg_async_cb (TnyFolder *folder,
        if (info->more_msgs) {
                tny_iterator_next (info->more_msgs);
                finished = (tny_iterator_is_done (info->more_msgs));
+       } else if (info->get_parts) {
+               tny_iterator_next (info->get_parts);
+               finished = (tny_iterator_is_done (info->get_parts));
        } else {
                finished = (priv->done == priv->total) ? TRUE : FALSE;
        }
@@ -2734,7 +3007,7 @@ get_msg_async_cb (TnyFolder *folder,
                } else {
                        g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                                     MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
-                                    err->message);
+                                    "%s", err->message);
                }
        } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
                /* Set the success status before calling the user callback */
@@ -2745,7 +3018,7 @@ get_msg_async_cb (TnyFolder *folder,
                info->header = tny_msg_get_header (msg);
 
        /* Call the user callback */
-       if (info->user_callback)
+       if (info->user_callback && (finished || (info->get_parts == NULL)))
                info->user_callback (info->mail_op, info->header, canceled, 
                                     msg, err, info->user_data);
 
@@ -2759,12 +3032,33 @@ get_msg_async_cb (TnyFolder *folder,
                modest_mail_operation_notify_end (info->mail_op);
 
                /* Clean */
+               if (info->msg)
+                       g_object_unref (info->msg);
                if (info->more_msgs)
                        g_object_unref (info->more_msgs);
                if (info->header)
                        g_object_unref (info->header);
                g_object_unref (info->mail_op);
                g_slice_free (GetMsgInfo, info);
+       } else if (info->get_parts) {
+               CamelStream *null_stream;
+               TnyStream *tny_null_stream;
+               TnyMimePart *part;
+
+               if (info->msg == NULL && msg != NULL)
+                       info->msg = g_object_ref (msg);
+
+               null_stream = camel_stream_null_new ();
+               tny_null_stream = tny_camel_stream_new (null_stream);
+               
+               part = TNY_MIME_PART (tny_iterator_get_current (info->get_parts));
+               tny_mime_part_decode_to_stream_async (part, tny_null_stream, 
+                                                     get_msg_async_get_part_cb,
+                                                     get_msg_status_cb,
+                                                     info);
+               g_object_unref (tny_null_stream);
+               g_object_unref (part);
+
        } else if (info->more_msgs) {
                TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
                TnyFolder *folder = tny_header_get_folder (header);
@@ -2881,6 +3175,7 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
                msg_info->last_total_bytes = 0;
                msg_info->sum_total_bytes = 0;
                msg_info->total_bytes = msg_list_size;
+               msg_info->msg = NULL;
 
                /* The callback will call it per each header */
                tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
@@ -2900,13 +3195,14 @@ remove_msgs_async_cb (TnyFolder *folder,
                      GError *err, 
                      gpointer user_data)
 {
-       gboolean expunge, leave_on_server;
+       gboolean expunge;
        const gchar *account_name;
        TnyAccount *account;
        ModestProtocolType account_proto = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
        ModestMailOperation *self;
        ModestMailOperationPrivate *priv;
        ModestProtocolRegistry *protocol_registry;
+       SyncFolderHelper *helper;
 
        self = (ModestMailOperation *) user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
@@ -2929,22 +3225,30 @@ remove_msgs_async_cb (TnyFolder *folder,
 
        account = modest_tny_folder_get_account (folder);
        account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
-       leave_on_server =
-               modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
-                                                       account_name);  
        account_proto = modest_tny_account_get_protocol_type (account);
        g_object_unref (account);
 
-       if ((modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto) && 
-            !leave_on_server) ||
-           !modest_tny_folder_is_remote_folder (folder))
+       if (modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto)) {
+               if (modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
+                                                           account_name))
+                       expunge = FALSE;
+               else
+                       expunge = TRUE;
+       } else {
                expunge = TRUE;
-       else
-               expunge = FALSE;
+       }
+
+       /* Create helper */
+       helper = g_slice_new0 (SyncFolderHelper);
+       helper->mail_op = g_object_ref (self);
+       helper->user_callback = NULL;
+       helper->user_data = NULL;
 
        /* Sync folder */
-       tny_folder_sync_async(folder, expunge, sync_folder_finish_callback, 
-                             NULL, self);
+       tny_folder_sync_async(folder, expunge, sync_folder_finish_callback, NULL, helper);
+
+       /* Remove the extra reference */
+       g_object_unref (self);
 }
 
 void 
@@ -3041,6 +3345,23 @@ modest_mail_operation_remove_msgs (ModestMailOperation *self,
        if (!remove_headers)
                remove_headers = g_object_ref (headers);
 
+       /* Notify messages are "read" */
+       iter = tny_list_create_iterator (remove_headers);
+       while (!tny_iterator_is_done (iter)) {
+               gchar *msg_uid;
+               TnyHeader *header;
+
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               msg_uid =  modest_tny_folder_get_header_unique_id (header);
+               if (msg_uid) {
+                       modest_platform_emit_msg_read_changed_signal (msg_uid, TRUE);
+                       g_free (msg_uid);
+               }
+               g_object_unref (header);
+               tny_iterator_next (iter);
+       }
+       g_object_unref (iter);
+
        /* remove message from folder */
        modest_mail_operation_notify_start (self);
        tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb, 
@@ -3195,6 +3516,34 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer u
        }
 
        if (finished) {
+               TnyAccount *src_account;
+               TnyAccount *dest_account;
+
+               /* send the notification that the source folder might have changed */
+               src_account = modest_tny_folder_get_account (folder);
+               if (src_account) {
+                       const gchar *src_folder_id;
+                       const gchar *src_account_name;
+
+                       src_folder_id = tny_folder_get_id (folder);
+                       src_account_name =
+                               modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
+                       modest_platform_emit_folder_updated_signal (src_account_name, src_folder_id);
+                       g_object_unref (src_account);
+               }
+               /* send the notification that the destination folder might have changed */
+               dest_account = modest_tny_folder_get_account (helper->dest_folder);
+               if (dest_account) {
+                       const gchar *dest_folder_id;
+                       const gchar *dest_account_name;
+
+                       dest_folder_id = tny_folder_get_id (helper->dest_folder);
+                       dest_account_name =
+                               modest_tny_account_get_parent_modest_account_name_for_server_account (dest_account);
+                       modest_platform_emit_folder_updated_signal (dest_account_name, dest_folder_id);
+                       g_object_unref (dest_account);
+               }
+
                /* Synchronize the source folder contents. This should
                   be done by tinymail but the camel_folder_sync it's
                   actually disabled in transfer_msgs_thread_clean
@@ -3280,7 +3629,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
-                            _CS("ckct_ib_unable_to_paste_here"));
+                            _CS_UNABLE_TO_PASTE_HERE);
                /* Notify the queue */
                modest_mail_operation_notify_end (self);
                return;
@@ -3673,17 +4022,17 @@ modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore
 }
 
 static void
-sync_folder_finish_callback (TnyFolder *self, 
-                            gboolean cancelled, 
-                            GError *err, 
+sync_folder_finish_callback (TnyFolder *self,
+                            gboolean cancelled,
+                            GError *err,
                             gpointer user_data)
 
 {
-       ModestMailOperation *mail_op;
        ModestMailOperationPrivate *priv;
+       SyncFolderHelper *helper;
 
-       mail_op = (ModestMailOperation *) user_data;
-       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
+       helper = (SyncFolderHelper *) user_data;
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->mail_op);
 
        /* If canceled by the user, ignore the error given by Tinymail */
        if (cancelled) {
@@ -3702,15 +4051,26 @@ sync_folder_finish_callback (TnyFolder *self,
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
 
-       modest_mail_operation_notify_end (mail_op);
-       g_object_unref (mail_op);
+       /* User callback */
+       if (helper->user_callback)
+               helper->user_callback (helper->mail_op, self, helper->user_data);
+
+       modest_mail_operation_notify_end (helper->mail_op);
+
+       /* Frees */
+       g_object_unref (helper->mail_op);
+       g_slice_free (SyncFolderHelper, helper);
 }
 
 void
 modest_mail_operation_sync_folder (ModestMailOperation *self,
-                                  TnyFolder *folder, gboolean expunge)
+                                  TnyFolder *folder,
+                                  gboolean expunge,
+                                  SyncFolderCallback callback,
+                                  gpointer user_data)
 {
        ModestMailOperationPrivate *priv;
+       SyncFolderHelper *helper;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_FOLDER (folder));
@@ -3720,11 +4080,16 @@ modest_mail_operation_sync_folder (ModestMailOperation *self,
        priv->account = modest_tny_folder_get_account (folder);
        priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
 
+       /* Create helper */
+       helper = g_slice_new0 (SyncFolderHelper);
+       helper->mail_op = g_object_ref (self);
+       helper->user_callback = callback;
+       helper->user_data = user_data;
+
        modest_mail_operation_notify_start (self);
-       g_object_ref (self);
-       tny_folder_sync_async (folder, expunge, 
-                              (TnyFolderCallback) sync_folder_finish_callback, 
-                              NULL, self);
+       tny_folder_sync_async (folder, expunge,
+                              (TnyFolderCallback) sync_folder_finish_callback,
+                              NULL, helper);
 }
 
 static void