* Fixes NB#85656, update the folder count properly when transferring messages. Added...
[modest] / src / modest-mail-operation.c
index 930b104..7c518d4 100644 (file)
@@ -60,6 +60,7 @@
 #include <modest-count-stream.h>
 #include <libgnomevfs/gnome-vfs.h>
 #include "modest-utils.h"
+#include "modest-debug.h"
 
 #define KB 1024
 
@@ -101,6 +102,13 @@ static guint    compute_message_array_size (GPtrArray *headers);
 static int      compare_headers_by_date   (gconstpointer a,
                                           gconstpointer b);
 
+static void     sync_folder_finish_callback (TnyFolder *self, 
+                                            gboolean cancelled, 
+                                            GError *err, 
+                                            gpointer user_data);
+
+static gboolean _check_memory_low         (ModestMailOperation *mail_op);
+
 enum _ModestMailOperationSignals 
 {
        PROGRESS_CHANGED_SIGNAL,
@@ -498,7 +506,8 @@ modest_mail_operation_cancel (ModestMailOperation *self)
 
        if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
                ModestTnySendQueue *queue;
-               queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
+               queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account),
+                                                      TRUE);
 
                /* Cancel the sending of the following next messages */
                tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
@@ -593,6 +602,35 @@ modest_mail_operation_clone_state (ModestMailOperation *self)
 /* ************************** SEND   ACTIONS ************************* */
 /* ******************************************************************* */
 
+static void
+send_mail_on_added_to_outbox (TnySendQueue *send_queue, 
+                             gboolean cancelled, 
+                             TnyMsg *msg, 
+                             GError *err,
+                             gpointer user_data)
+{
+       ModestMailOperationPrivate *priv;
+       ModestMailOperation *self;
+
+       self = MODEST_MAIL_OPERATION (user_data);
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
+
+       if (cancelled || err)
+               goto end;
+
+       if (err) {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
+                            "Error adding a msg to the send queue\n");
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
+       } else {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+       }
+ end:
+       modest_mail_operation_notify_end (self);
+       g_object_unref (self);
+}
+
 void
 modest_mail_operation_send_mail (ModestMailOperation *self,
                                 TnyTransportAccount *transport_account,
@@ -613,25 +651,26 @@ modest_mail_operation_send_mail (ModestMailOperation *self,
        priv->done = 1;
        priv->total = 1;
 
-       send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
+       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);
-
        } else {
-               /* Add the msg to the queue */
                modest_mail_operation_notify_start (self);
-
-               tny_send_queue_add_async (send_queue, msg, NULL, NULL, NULL);
-               modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue), FALSE);
-
-               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
-               modest_mail_operation_notify_end (self);
+               /* Add the msg to the queue. The callback will
+                  finalize the mail operation */
+               tny_send_queue_add_async (send_queue, msg, send_mail_on_added_to_outbox, 
+                                         NULL, g_object_ref (self));
+               modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue), 
+                                                                 FALSE);
        }
-
 }
 
 
@@ -666,12 +705,14 @@ create_msg_thread (gpointer thread_data)
        if (info->html_body == NULL) {
                new_msg = modest_tny_msg_new (info->to, info->from, info->cc, 
                                              info->bcc, info->subject, info->plain_body, 
-                                             info->attachments_list);
+                                             info->attachments_list,
+                                             &(priv->error));
        } else {
                new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
                                                         info->bcc, info->subject, info->html_body,
                                                         info->plain_body, info->attachments_list,
-                                                        info->images_list);
+                                                        info->images_list,
+                                                        &(priv->error));
        }
 
        if (new_msg) {
@@ -688,9 +729,10 @@ create_msg_thread (gpointer thread_data)
                g_object_unref (G_OBJECT(header));
        } else {
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
-                            "modest: failed to create a new msg\n");
+               if (!priv->error)
+                       g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                                    MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
+                                    "modest: failed to create a new msg\n");
        }
 
 
@@ -777,15 +819,16 @@ modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
        TnyFolder *draft_folder = NULL;
        TnyFolder *outbox_folder = NULL;
        TnyHeader *header = NULL;
-       GError *err = NULL;
+
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
        if (!msg) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               modest_mail_operation_notify_end (self);
                goto end;
        }
 
-       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
-
-       if (priv->error) {
+       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);
                goto end;
@@ -795,6 +838,7 @@ modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
        modest_mail_operation_send_mail (self, info->transport_account, msg);
 
        if (info->draft_msg != NULL) {
+               TnyList *tmp_headers = NULL;
                TnyFolder *folder = NULL;
                TnyFolder *src_folder = NULL;
                TnyFolderType folder_type;              
@@ -838,11 +882,12 @@ modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
                        src_folder = draft_folder;
 
                /* Note: This can fail (with a warning) if the message is not really already in a folder,
-                * because this function requires it to have a UID. */          
-               tny_folder_remove_msg (src_folder, header, NULL);
-
-               tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
-/*             tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);  /\* expunge *\/ */
+                * because this function requires it to have a UID. */
+               tmp_headers = tny_simple_list_new ();
+               tny_list_append (tmp_headers, (GObject*) header);
+               tny_folder_remove_msgs_async (src_folder, tmp_headers, NULL, NULL, NULL);
+               g_object_unref (tmp_headers);
+               tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);  /* expunge */
                
                g_object_unref (folder);
        }
@@ -850,8 +895,6 @@ modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
 end:
        if (header)
                g_object_unref (header);
-       if (err != NULL)
-               g_error_free(err);      
        if (info->draft_msg)
                g_object_unref (info->draft_msg);
        if (draft_folder)
@@ -930,9 +973,14 @@ modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
 {
        ModestMailOperationPrivate *priv = NULL;
        SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
+       GError *io_error = NULL;
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
 
+       if (priv->error && priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
+               io_error = priv->error;
+               priv->error = NULL;
+       }
        if (priv->error) {
                g_warning ("%s: priv->error != NULL", __FUNCTION__);
                g_error_free(priv->error);
@@ -955,10 +1003,18 @@ modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
                g_object_unref (G_OBJECT(src_folder));
        }
 
-       if (!priv->error)
-               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
-       else
+       if (priv->error) {
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               if (io_error) {
+                       g_error_free (io_error);
+                       io_error = NULL;
+               }
+       } else if (io_error) {
+               priv->error = io_error;
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
+       } else {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+       }
 
        /* Call the user callback */
        if (info->callback)
@@ -1013,7 +1069,7 @@ modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
                }
        }
 
-       if (!priv->error) {
+       if (!priv->error || priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
                SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
                cb_info->transport_account = g_object_ref(info->transport_account);
                cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
@@ -1245,13 +1301,16 @@ inbox_refreshed_cb (TnyFolder *inbox,
        ModestAccountMgr *mgr;
        ModestAccountRetrieveType retrieve_type;
        TnyList *new_headers = NULL;
-       gboolean headers_only, ignore_limit, succeeded;
+       gboolean headers_only, ignore_limit;
        TnyTransportAccount *transport_account = NULL;
 
        info = (UpdateAccountInfo *) user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
        mgr = modest_runtime_get_account_mgr ();
 
+       /* Set the last updated as the current time, do it even if the inbox refresh failed */
+       modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
+
        if (canceled || err) {
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                if (err)
@@ -1260,6 +1319,7 @@ inbox_refreshed_cb (TnyFolder *inbox,
                        g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                                     MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
                                     "canceled");
+
                /* Notify the user about the error and then exit */
                update_account_notify_user_and_free (info, NULL);
                return;
@@ -1298,11 +1358,6 @@ inbox_refreshed_cb (TnyFolder *inbox,
        g_object_unref (info->inbox_observer);
        info->inbox_observer = NULL;
 
-       /* Update the last updated key, even if we don't have to get new headers */
-       modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
-       if (!canceled && !err) 
-               modest_account_mgr_set_server_account_username_has_succeeded (mgr, tny_account_get_id (priv->account), TRUE);
-       
        if (new_headers_array->len == 0)
                goto send_mail;
 
@@ -1371,13 +1426,6 @@ inbox_refreshed_cb (TnyFolder *inbox,
        g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
        g_ptr_array_free (new_headers_array, FALSE);
 
-       if (priv->error)
-               succeeded = FALSE;
-       else
-               succeeded = TRUE;
-       modest_account_mgr_set_server_account_username_has_succeeded (modest_runtime_get_account_mgr (), 
-                                                                     tny_account_get_name (priv->account), 
-                                                                     succeeded);
  send_mail:
        /* Get the transport account */
        transport_account = (TnyTransportAccount *)
@@ -1389,7 +1437,7 @@ inbox_refreshed_cb (TnyFolder *inbox,
                TnyFolder *outbox;
                guint num_messages;
 
-               send_queue = modest_runtime_get_send_queue (transport_account);
+               send_queue = modest_runtime_get_send_queue (transport_account, TRUE);
                g_object_unref (transport_account);
 
                /* Get outbox folder */
@@ -1421,6 +1469,41 @@ inbox_refreshed_cb (TnyFolder *inbox,
        update_account_notify_user_and_free (info, new_headers);
 }
 
+static void
+inbox_refresh_status_update (GObject *obj,
+                            TnyStatus *status,
+                            gpointer user_data)
+{
+       UpdateAccountInfo *info = NULL;
+       ModestMailOperation *self = NULL;
+       ModestMailOperationPrivate *priv = NULL;
+       ModestMailOperationState *state;
+
+       g_return_if_fail (user_data != NULL);
+       g_return_if_fail (status != NULL);
+
+       /* Show only the status information we want */
+       if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
+               return;
+
+       info = (UpdateAccountInfo *) user_data;
+       self = info->mail_op;
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
+
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
+
+       priv->done = status->position;
+       priv->total = status->of_total;
+
+       state = modest_mail_operation_clone_state (self);
+
+       /* This is not a GDK lock because we are a Tinymail callback and
+        * Tinymail already acquires the Gdk lock */
+       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
+
+       g_slice_free (ModestMailOperationState, state);
+}
+
 static void 
 recurse_folders_async_cb (TnyFolderStore *folder_store, 
                          gboolean canceled,
@@ -1521,7 +1604,7 @@ recurse_folders_async_cb (TnyFolderStore *folder_store,
                        tny_folder_add_observer (inbox, info->inbox_observer);
 
                        /* Refresh the INBOX */
-                       tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
+                       tny_folder_refresh_async (inbox, inbox_refreshed_cb, inbox_refresh_status_update, info);
                        g_object_unref (inbox);
                } else {
                        /* We could not perform the inbox refresh but
@@ -1577,6 +1660,11 @@ modest_mail_operation_update_account (ModestMailOperation *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);
@@ -1610,6 +1698,9 @@ modest_mail_operation_update_account (ModestMailOperation *self,
                                            recurse_folders_async_cb, 
                                            NULL, info);
        g_object_unref (folders);
+       
+       g_object_unref (priv->account);
+       
 }
 
 /*
@@ -1842,7 +1933,10 @@ transfer_folder_status_cb (GObject *obj,
        XFerFolderAsyncHelper *helper;
 
        g_return_if_fail (status != NULL);
-       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
+
+       /* Show only the status information we want */
+       if (status->code != TNY_FOLDER_STATUS_CODE_COPY_FOLDER)
+               return;
 
        helper = (XFerFolderAsyncHelper *) user_data;
        g_return_if_fail (helper != NULL);
@@ -2102,10 +2196,11 @@ modest_mail_operation_rename_folder (ModestMailOperation *self,
                                               transfer_folder_cb,
                                               transfer_folder_status_cb,
                                               helper);
+                       g_object_unref (into);
                } else {
+                       g_object_unref (into);
                        goto error;
                }
-               g_object_unref (into);
 
                return;
        }
@@ -2130,6 +2225,7 @@ modest_mail_operation_rename_folder (ModestMailOperation *self,
 void 
 modest_mail_operation_get_msg (ModestMailOperation *self,
                               TnyHeader *header,
+                              gboolean progress_feedback,
                               GetMsgAsyncUserCallback user_callback,
                               gpointer user_data)
 {
@@ -2141,20 +2237,31 @@ modest_mail_operation_get_msg (ModestMailOperation *self,
        g_return_if_fail (TNY_IS_HEADER (header));
        
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
-       folder = tny_header_get_folder (header);
-
        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);
        priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
        
        /* Check for cached messages */
-       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;
+       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);
@@ -2166,6 +2273,7 @@ modest_mail_operation_get_msg (ModestMailOperation *self,
        helper->last_total_bytes = 0;
        helper->sum_total_bytes = 0;
        helper->total_bytes = tny_header_get_message_size (header);
+       helper->more_msgs = NULL;
 
        modest_mail_operation_notify_start (self);
        
@@ -2176,6 +2284,7 @@ modest_mail_operation_get_msg (ModestMailOperation *self,
        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);
 
@@ -2190,7 +2299,10 @@ get_msg_status_cb (GObject *obj,
        GetMsgInfo *helper = NULL;
 
        g_return_if_fail (status != NULL);
-       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
+
+       /* Show only the status information we want */
+       if (status->code != TNY_FOLDER_STATUS_CODE_GET_MSG)
+               return;
 
        helper = (GetMsgInfo *) user_data;
        g_return_if_fail (helper != NULL);       
@@ -2224,9 +2336,10 @@ get_msg_async_cb (TnyFolder *folder,
        }
 
        /* If canceled by the user, ignore the error given by Tinymail */
-       if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED || canceled) {
+       if (canceled) {
                canceled = TRUE;
                finished = TRUE;
+               priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
        } else if (err) {
                priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
                if (err) {
@@ -2301,6 +2414,28 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
        priv->done = 0;
        priv->total = tny_list_get_length(header_list);
 
+       /* Check memory low */
+       if (_check_memory_low (self)) {
+               if (user_callback) {
+                       TnyHeader *header = NULL;
+                       TnyIterator *iter;
+
+                       if (tny_list_get_length (header_list) > 0) {
+                               iter = tny_list_create_iterator (header_list);
+                               header = (TnyHeader *) tny_iterator_get_current (iter);
+                               g_object_unref (iter);
+                       }
+                       user_callback (self, header, FALSE, NULL, priv->error, user_data);
+                       if (header)
+                               g_object_unref (header);
+               }
+               if (notify)
+                       notify (user_data);
+               /* Notify about operation end */
+               modest_mail_operation_notify_end (self);
+               return;
+       }
+
        /* Check uncached messages */
        for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
             !has_uncached_messages && !tny_iterator_is_done (iter); 
@@ -2371,81 +2506,64 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
 }
 
 
-void 
-modest_mail_operation_remove_msg (ModestMailOperation *self,  
-                                 TnyHeader *header,
-                                 gboolean remove_to_trash /*ignored*/)
-{
-       TnyFolder *folder;
+static void
+remove_msgs_async_cb (TnyFolder *folder, 
+                     gboolean canceled, 
+                     GError *err, 
+                     gpointer user_data)
+{
+       gboolean expunge, leave_on_server;
+       const gchar *account_name;
+       const gchar *proto;
+       TnyAccount *account;
+       ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
+       ModestMailOperation *self;
        ModestMailOperationPrivate *priv;
 
-       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
-       g_return_if_fail (TNY_IS_HEADER (header));
-
-       if (remove_to_trash)
-               g_warning ("remove to trash is not implemented");
-
+       self = (ModestMailOperation *) user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
-       folder = tny_header_get_folder (header);
-
-       /* Get account and set it into mail_operation */
-       priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
-       priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
-       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
-
-       /* remove message from folder */
-       tny_folder_remove_msg (folder, header, &(priv->error));
-       if (!priv->error) {
-               gboolean expunge, leave_on_server;
-               const gchar *account_name;
-               TnyAccount *account;
-               ModestTransportStoreProtocol account_proto;
-
-               tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
-               tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
-
-               modest_mail_operation_notify_start (self);
-
-               /* Get leave on server setting */
-               account = 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_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
 
-               if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
-                   modest_tny_folder_is_remote_folder (folder) == FALSE)
-                       expunge = TRUE;
-               else
-                       expunge = FALSE;
+       if (canceled || err) {
+               /* If canceled by the user, ignore the error given by Tinymail */
+               if (canceled) {
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
+               } else if (err) {
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
+                       priv->error = g_error_copy ((const GError *) err);
+                       priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
+               }
+               /* Exit */
+               modest_mail_operation_notify_end (self);
+               g_object_unref (self);
+               return;
+       }
 
-               /* Sync folder */
-               tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
+       account = 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);  
+       proto = tny_account_get_proto (account);
+       g_object_unref (account);
 
-               /* Unref */
-               g_object_unref (account);
-       }
+       if (proto)
+               account_proto = modest_protocol_info_get_transport_store_protocol (proto);
        
-       
-       /* Set status */
-       if (!priv->error)
-               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+       if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
+                   modest_tny_folder_is_remote_folder (folder) == FALSE)
+               expunge = TRUE;
        else
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-
-       /* Free */
-       g_object_unref (G_OBJECT (folder));
-
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+               expunge = FALSE;
+       
+       /* Sync folder */
+       tny_folder_sync_async(folder, expunge, sync_folder_finish_callback, 
+                             NULL, self);
 }
 
 void 
 modest_mail_operation_remove_msgs (ModestMailOperation *self,  
                                   TnyList *headers,
-                                 gboolean remove_to_trash /*ignored*/)
+                                  gboolean remove_to_trash /*ignored*/)
 {
        TnyFolder *folder = NULL;
        ModestMailOperationPrivate *priv;
@@ -2488,7 +2606,7 @@ modest_mail_operation_remove_msgs (ModestMailOperation *self,
                traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
                if (traccount) {
                        ModestTnySendQueueStatus status;
-                       ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
+                       ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount, TRUE);
                        TnyIterator *iter = tny_list_create_iterator(headers);
                        g_object_unref(remove_headers);
                        remove_headers = TNY_LIST(tny_simple_list_new());
@@ -2516,46 +2634,9 @@ modest_mail_operation_remove_msgs (ModestMailOperation *self,
 
        /* remove message from folder */
        modest_mail_operation_notify_start (self);
+       tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb, 
+                                     NULL, g_object_ref (self));
 
-       tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
-       if (!priv->error) {
-               gboolean expunge, leave_on_server;
-               const gchar *account_name;
-               const gchar *proto;
-               TnyAccount *account;
-               ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
-               
-               account = 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);
-               
-               proto = tny_account_get_proto (account);
-               if (proto) {
-                       account_proto = modest_protocol_info_get_transport_store_protocol (proto);
-               }
-               
-               if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
-                   modest_tny_folder_is_remote_folder (folder) == FALSE)
-                       expunge = TRUE;
-               else
-                       expunge = FALSE;
-
-               /* Sync folder */
-               tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
-               
-               g_object_unref (account);
-       }
-       
-       
-       /* Set status */
-       if (!priv->error)
-               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
-       else
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-
-       /* Free */
 cleanup:
        if (remove_headers)
                g_object_unref (remove_headers);
@@ -2565,9 +2646,6 @@ cleanup:
                g_object_unref (iter);
        if (folder)
                g_object_unref (folder);
-
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
 }
 
 static void
@@ -2630,7 +2708,10 @@ transfer_msgs_status_cb (GObject *obj,
        XFerMsgsAsyncHelper *helper;
 
        g_return_if_fail (status != NULL);
-       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
+
+       /* Show only the status information we want */
+       if (status->code != TNY_FOLDER_STATUS_CODE_XFER_MSGS)
+               return;
 
        helper = (XFerMsgsAsyncHelper *) user_data;
        g_return_if_fail (helper != NULL);       
@@ -2640,6 +2721,35 @@ transfer_msgs_status_cb (GObject *obj,
                                              &(helper->sum_total_bytes), helper->total_bytes, TRUE);
 }
 
+static void
+transfer_msgs_sync_folder_cb (TnyFolder *self, 
+                             gboolean cancelled, 
+                             GError *err, 
+                             gpointer user_data)
+{
+       XFerMsgsAsyncHelper *helper;
+       /* We don't care here about the results of the
+          synchronization */
+       helper = (XFerMsgsAsyncHelper *) user_data;
+
+       /* Notify about operation end */
+       modest_mail_operation_notify_end (helper->mail_op);
+
+       /* If user defined callback function was defined, call it */
+       if (helper->user_callback)
+               helper->user_callback (helper->mail_op, helper->user_data);
+       
+       /* Free */
+       if (helper->more_msgs)
+               g_object_unref (helper->more_msgs);
+       if (helper->headers)
+               g_object_unref (helper->headers);
+       if (helper->dest_folder)
+               g_object_unref (helper->dest_folder);
+       if (helper->mail_op)
+               g_object_unref (helper->mail_op);
+       g_slice_free (XFerMsgsAsyncHelper, helper);
+}
 
 static void
 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
@@ -2654,16 +2764,12 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer u
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
-       if (err) {
+       if (cancelled) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
+       } else if (err) {
                priv->error = g_error_copy (err);
                priv->done = 0;
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;     
-       } else if (cancelled) {
-               priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
-               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
-                            _("Error trying to refresh the contents of %s"),
-                            tny_folder_get_name (folder));
        } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
                if (helper->more_msgs) {
                        /* We'll transfer the next message in the list */
@@ -2678,7 +2784,6 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer u
                                finished = FALSE;
                        }
                }
-
                if (finished) {
                        priv->done = 1;
                        priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
@@ -2686,34 +2791,13 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer u
        }
 
        if (finished) {
-
-               /* Update folder counts */
-               tny_folder_poke_status (folder);
-               tny_folder_poke_status (helper->dest_folder);
-
-               /* Notify about operation end */
-               modest_mail_operation_notify_end (self);
-
-               /* If user defined callback function was defined, call it */
-               if (helper->user_callback) {
-                       /* This is not a GDK lock because we are a Tinymail callback and
-                        * Tinymail already acquires the Gdk lock */
-
-                       /* no gdk_threads_enter (), CHECKED */
-                       helper->user_callback (self, helper->user_data);
-                       /* no gdk_threads_leave (), CHECKED */
-               }
-
-               /* Free */
-               if (helper->more_msgs)
-                       g_object_unref (helper->more_msgs);
-               if (helper->headers)
-                       g_object_unref (helper->headers);
-               if (helper->dest_folder)
-                       g_object_unref (helper->dest_folder);
-               if (helper->mail_op)
-                       g_object_unref (helper->mail_op);
-               g_slice_free (XFerMsgsAsyncHelper, helper);
+               /* 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
+                  because it's supposed to cause hangs */
+               tny_folder_sync_async (folder, helper->delete, 
+                                      transfer_msgs_sync_folder_cb, 
+                                      NULL, helper);
        } else {
                /* Transfer more messages */
                tny_folder_transfer_msgs_async (folder,
@@ -2839,7 +2923,6 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
        helper->dest_folder = g_object_ref(folder);
        helper->user_callback = user_callback;
        helper->user_data = user_data;
-       helper->delete = delete_original;
        helper->last_total_bytes = 0;
        helper->sum_total_bytes = 0;
        helper->total_bytes = compute_message_list_size (headers);
@@ -2883,11 +2966,14 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
                leave_on_server = FALSE;
        }
 
+       /* Do not delete messages if leave on server is TRUE */
+       helper->delete = (leave_on_server) ? FALSE : delete_original;
+
        modest_mail_operation_notify_start (self);
        tny_folder_transfer_msgs_async (src_folder, 
                                        helper->headers, 
                                        folder, 
-                                       (leave_on_server) ? FALSE : delete_original, 
+                                       helper->delete, 
                                        transfer_msgs_cb, 
                                        transfer_msgs_status_cb,
                                        helper);
@@ -2958,7 +3044,10 @@ on_refresh_folder_status_update (GObject *obj,
 
        g_return_if_fail (user_data != NULL);
        g_return_if_fail (status != NULL);
-       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
+
+       /* Show only the status information we want */
+       if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
+               return;
 
        helper = (RefreshAsyncHelper *) user_data;
        self = helper->mail_op;
@@ -2989,9 +3078,17 @@ modest_mail_operation_refresh_folder  (ModestMailOperation *self,
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
 
-       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
+       /* Check memory low */
+       if (_check_memory_low (self)) {
+               if (user_callback)
+                       user_callback (self, folder, user_data);
+               /* Notify about operation end */
+               modest_mail_operation_notify_end (self);
+               return;
+       }
 
        /* Get account and set it into mail_operation */
+       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
        priv->account = modest_tny_folder_get_account  (folder);
        priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
 
@@ -3055,19 +3152,35 @@ modest_mail_operation_run_queue (ModestMailOperation *self,
 }
 
 static void
-sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
+sync_folder_finish_callback (TnyFolder *self, 
+                            gboolean cancelled, 
+                            GError *err, 
+                            gpointer user_data)
+
 {
+       ModestMailOperation *mail_op;
        ModestMailOperationPrivate *priv;
 
+       mail_op = (ModestMailOperation *) user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
-       if (err != NULL) {
-               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
-                            err->message);
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+
+       /* If canceled by the user, ignore the error given by Tinymail */
+       if (cancelled) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
+       } else if (err) {
+               /* If the operation was a sync then the status is
+                  failed, but if it's part of another operation then
+                  just set it as finished with errors */
+               if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               else
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
+               priv->error = g_error_copy ((const GError *) err);
+               priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
        } else {
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
+
        modest_mail_operation_notify_end (mail_op);
        g_object_unref (mail_op);
 }
@@ -3083,12 +3196,14 @@ modest_mail_operation_sync_folder (ModestMailOperation *self,
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
-       priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
+       priv->account = modest_tny_folder_get_account (folder);
        priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
 
        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, self);
 }
 
 static void
@@ -3209,3 +3324,25 @@ modest_mail_operation_to_string (ModestMailOperation *self)
                                priv->done, priv->total,
                                priv->error && priv->error->message ? priv->error->message : "");
 }
+
+/* 
+ * Once the mail operations were objects this will be no longer
+ * needed. I don't like it, but we need it for the moment
+ */
+static gboolean
+_check_memory_low (ModestMailOperation *mail_op)
+{
+       if (modest_platform_check_memory_low (NULL, FALSE)) {
+               ModestMailOperationPrivate *priv;
+
+               priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               g_set_error (&(priv->error),
+                            MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY,
+                            "Not enough memory to complete the operation");
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}