1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <tny-mime-part.h>
33 #include <tny-store-account.h>
34 #include <tny-folder-store.h>
35 #include <tny-folder-store-query.h>
36 #include <tny-camel-stream.h>
37 #include <tny-camel-pop-store-account.h>
38 #include <tny-camel-pop-folder.h>
39 #include <tny-camel-imap-folder.h>
40 #include <tny-camel-mem-stream.h>
41 #include <tny-simple-list.h>
42 #include <tny-send-queue.h>
43 #include <tny-status.h>
44 #include <tny-error.h>
45 #include <tny-folder-observer.h>
46 #include <camel/camel-stream-mem.h>
47 #include <glib/gi18n.h>
48 #include <modest-defs.h>
49 #include "modest-platform.h"
50 #include "modest-account-mgr-helpers.h"
51 #include <modest-tny-account.h>
52 #include <modest-tny-send-queue.h>
53 #include <modest-runtime.h>
54 #include "modest-text-utils.h"
55 #include "modest-tny-msg.h"
56 #include "modest-tny-folder.h"
57 #include "modest-tny-account-store.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-marshal.h"
60 #include "modest-error.h"
61 #include "modest-mail-operation.h"
62 #include <modest-count-stream.h>
63 #include <libgnomevfs/gnome-vfs.h>
64 #include "modest-utils.h"
65 #include "modest-debug.h"
66 #ifdef MODEST_USE_LIBTIME
67 #include <clockd/libtime.h>
73 * Remove all these #ifdef stuff when the tinymail's idle calls become
76 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
78 /* 'private'/'protected' functions */
79 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
80 static void modest_mail_operation_init (ModestMailOperation *obj);
81 static void modest_mail_operation_finalize (GObject *obj);
83 static void get_msg_async_cb (TnyFolder *folder,
89 static void get_msg_status_cb (GObject *obj,
93 static void modest_mail_operation_notify_start (ModestMailOperation *self);
94 static void modest_mail_operation_notify_end (ModestMailOperation *self);
96 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
98 gint *last_total_bytes,
99 gint *sum_total_bytes,
101 gboolean increment_done);
103 static guint compute_message_list_size (TnyList *headers, guint num_elements);
105 static int compare_headers_by_date (gconstpointer a,
108 static void sync_folder_finish_callback (TnyFolder *self,
113 static gboolean _check_memory_low (ModestMailOperation *mail_op);
117 ModestTnySendQueue *queue;
118 ModestMailOperation *self;
124 static void run_queue_notify_and_destroy (RunQueueHelper *helper,
125 ModestMailOperationStatus status);
127 /* Helpers for the update account operation (send & receive)*/
130 ModestMailOperation *mail_op;
132 UpdateAccountCallback callback;
137 TnyFolderObserver *inbox_observer;
138 RetrieveAllCallback retrieve_all_cb;
139 gboolean interactive;
143 static void destroy_update_account_info (UpdateAccountInfo *info);
145 static void update_account_send_mail (UpdateAccountInfo *info);
147 static void update_account_get_msg_async_cb (TnyFolder *folder,
153 static void update_account_notify_user_and_free (UpdateAccountInfo *info,
154 TnyList *new_headers);
156 enum _ModestMailOperationSignals
158 PROGRESS_CHANGED_SIGNAL,
159 OPERATION_STARTED_SIGNAL,
160 OPERATION_FINISHED_SIGNAL,
164 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
165 struct _ModestMailOperationPrivate {
171 ErrorCheckingUserCallback error_checking;
172 gpointer error_checking_user_data;
173 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
174 ModestMailOperationStatus status;
175 ModestMailOperationTypeOperation op_type;
178 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
179 MODEST_TYPE_MAIL_OPERATION, \
180 ModestMailOperationPrivate))
182 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
183 priv->status = new_status;\
188 GetMsgAsyncUserCallback user_callback;
190 TnyIterator *more_msgs;
192 ModestMailOperation *mail_op;
193 GDestroyNotify destroy_notify;
194 gint last_total_bytes;
195 gint sum_total_bytes;
199 typedef struct _RefreshAsyncHelper {
200 ModestMailOperation *mail_op;
201 RefreshAsyncUserCallback user_callback;
203 } RefreshAsyncHelper;
205 typedef struct _XFerMsgsAsyncHelper
207 ModestMailOperation *mail_op;
209 TnyIterator *more_msgs;
210 TnyFolder *dest_folder;
211 XferMsgsAsyncUserCallback user_callback;
214 gint last_total_bytes;
215 gint sum_total_bytes;
217 } XFerMsgsAsyncHelper;
219 typedef struct _XFerFolderAsyncHelper
221 ModestMailOperation *mail_op;
222 XferFolderAsyncUserCallback user_callback;
224 } XFerFolderAsyncHelper;
226 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
230 static void modest_mail_operation_create_msg (ModestMailOperation *self,
231 const gchar *from, const gchar *to,
232 const gchar *cc, const gchar *bcc,
233 const gchar *subject, const gchar *plain_body,
234 const gchar *html_body, const GList *attachments_list,
235 const GList *images_list,
236 TnyHeaderFlags priority_flags,
237 const gchar *references, const gchar *in_reply_to,
238 ModestMailOperationCreateMsgCallback callback,
241 static gboolean idle_notify_queue (gpointer data);
244 ModestMailOperation *mail_op;
254 GList *attachments_list;
256 TnyHeaderFlags priority_flags;
257 ModestMailOperationCreateMsgCallback callback;
263 ModestMailOperation *mail_op;
265 ModestMailOperationCreateMsgCallback callback;
270 static GObjectClass *parent_class = NULL;
272 static guint signals[NUM_SIGNALS] = {0};
275 modest_mail_operation_get_type (void)
277 static GType my_type = 0;
279 static const GTypeInfo my_info = {
280 sizeof(ModestMailOperationClass),
281 NULL, /* base init */
282 NULL, /* base finalize */
283 (GClassInitFunc) modest_mail_operation_class_init,
284 NULL, /* class finalize */
285 NULL, /* class data */
286 sizeof(ModestMailOperation),
288 (GInstanceInitFunc) modest_mail_operation_init,
291 my_type = g_type_register_static (G_TYPE_OBJECT,
292 "ModestMailOperation",
299 modest_mail_operation_class_init (ModestMailOperationClass *klass)
301 GObjectClass *gobject_class;
302 gobject_class = (GObjectClass*) klass;
304 parent_class = g_type_class_peek_parent (klass);
305 gobject_class->finalize = modest_mail_operation_finalize;
307 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
310 * ModestMailOperation::progress-changed
311 * @self: the #MailOperation that emits the signal
312 * @user_data: user data set when the signal handler was connected
314 * Emitted when the progress of a mail operation changes
316 signals[PROGRESS_CHANGED_SIGNAL] =
317 g_signal_new ("progress-changed",
318 G_TYPE_FROM_CLASS (gobject_class),
320 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
322 g_cclosure_marshal_VOID__POINTER,
323 G_TYPE_NONE, 1, G_TYPE_POINTER);
327 * This signal is issued whenever a mail operation starts, and
328 * starts mean when the tinymail operation is issued. This
329 * means that it could happen that something wrong happens and
330 * the tinymail function is never called. In this situation a
331 * operation-finished will be issued without any
334 signals[OPERATION_STARTED_SIGNAL] =
335 g_signal_new ("operation-started",
336 G_TYPE_FROM_CLASS (gobject_class),
338 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
340 g_cclosure_marshal_VOID__VOID,
345 * This signal is issued whenever a mail operation
346 * finishes. Note that this signal could be issued without any
347 * previous "operation-started" signal, because this last one
348 * is only issued when the tinymail operation is successfully
351 signals[OPERATION_FINISHED_SIGNAL] =
352 g_signal_new ("operation-finished",
353 G_TYPE_FROM_CLASS (gobject_class),
355 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
357 g_cclosure_marshal_VOID__VOID,
362 modest_mail_operation_init (ModestMailOperation *obj)
364 ModestMailOperationPrivate *priv;
366 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
368 priv->account = NULL;
369 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
370 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
375 priv->error_checking = NULL;
376 priv->error_checking_user_data = NULL;
380 modest_mail_operation_finalize (GObject *obj)
382 ModestMailOperationPrivate *priv;
384 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
389 g_error_free (priv->error);
393 g_object_unref (priv->source);
397 g_object_unref (priv->account);
398 priv->account = NULL;
402 G_OBJECT_CLASS(parent_class)->finalize (obj);
406 modest_mail_operation_new (GObject *source)
408 ModestMailOperation *obj;
409 ModestMailOperationPrivate *priv;
411 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
412 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
415 priv->source = g_object_ref(source);
421 modest_mail_operation_new_with_error_handling (GObject *source,
422 ErrorCheckingUserCallback error_handler,
424 ErrorCheckingUserDataDestroyer error_handler_destroyer)
426 ModestMailOperation *obj;
427 ModestMailOperationPrivate *priv;
429 obj = modest_mail_operation_new (source);
430 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
432 g_return_val_if_fail (error_handler != NULL, obj);
433 priv->error_checking = error_handler;
434 priv->error_checking_user_data = user_data;
435 priv->error_checking_user_data_destroyer = error_handler_destroyer;
441 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
443 ModestMailOperationPrivate *priv;
445 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
447 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
448 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
450 /* Call the user callback */
451 if (priv->error_checking != NULL)
452 priv->error_checking (self, priv->error_checking_user_data);
456 ModestMailOperationTypeOperation
457 modest_mail_operation_get_type_operation (ModestMailOperation *self)
459 ModestMailOperationPrivate *priv;
461 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
462 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
464 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
466 return priv->op_type;
470 modest_mail_operation_is_mine (ModestMailOperation *self,
473 ModestMailOperationPrivate *priv;
475 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
478 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
479 if (priv->source == NULL) return FALSE;
481 return priv->source == me;
485 modest_mail_operation_get_source (ModestMailOperation *self)
487 ModestMailOperationPrivate *priv;
489 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
492 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
494 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
498 return (priv->source) ? g_object_ref (priv->source) : NULL;
501 ModestMailOperationStatus
502 modest_mail_operation_get_status (ModestMailOperation *self)
504 ModestMailOperationPrivate *priv;
506 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
507 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
508 MODEST_MAIL_OPERATION_STATUS_INVALID);
510 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
512 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
513 return MODEST_MAIL_OPERATION_STATUS_INVALID;
520 modest_mail_operation_get_error (ModestMailOperation *self)
522 ModestMailOperationPrivate *priv;
524 g_return_val_if_fail (self, NULL);
525 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
527 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
530 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
538 modest_mail_operation_cancel (ModestMailOperation *self)
540 ModestMailOperationPrivate *priv;
541 gboolean canceled = FALSE;
543 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
545 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
548 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
550 /* Cancel the mail operation */
551 g_return_val_if_fail (priv->account, FALSE);
552 tny_account_cancel (priv->account);
554 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
555 ModestTnySendQueue *queue;
556 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account),
559 /* Cancel the sending of the following next messages */
560 if (TNY_IS_SEND_QUEUE (queue))
561 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
568 modest_mail_operation_get_task_done (ModestMailOperation *self)
570 ModestMailOperationPrivate *priv;
572 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
575 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
580 modest_mail_operation_get_task_total (ModestMailOperation *self)
582 ModestMailOperationPrivate *priv;
584 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
587 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
592 modest_mail_operation_is_finished (ModestMailOperation *self)
594 ModestMailOperationPrivate *priv;
595 gboolean retval = FALSE;
597 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
600 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
602 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
603 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
604 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
605 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
615 * Creates an image of the current state of a mail operation, the
616 * caller must free it
618 static ModestMailOperationState *
619 modest_mail_operation_clone_state (ModestMailOperation *self)
621 ModestMailOperationState *state;
622 ModestMailOperationPrivate *priv;
624 g_return_val_if_fail (self, NULL);
625 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
626 g_return_val_if_fail (priv, NULL);
631 state = g_slice_new (ModestMailOperationState);
633 state->status = priv->status;
634 state->op_type = priv->op_type;
635 state->done = priv->done;
636 state->total = priv->total;
637 state->finished = modest_mail_operation_is_finished (self);
638 state->bytes_done = 0;
639 state->bytes_total = 0;
644 /* ******************************************************************* */
645 /* ************************** SEND ACTIONS ************************* */
646 /* ******************************************************************* */
650 ModestMailOperation *mail_op;
655 send_mail_on_sync_async_cb (TnyFolder *folder,
660 ModestMailOperationPrivate *priv;
661 ModestMailOperation *self;
662 SendNewMailHelper *helper;
664 helper = (SendNewMailHelper *) user_data;
665 self = helper->mail_op;
666 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
672 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
673 MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
674 "Error adding a msg to the send queue\n");
675 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
677 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
682 modest_mail_operation_notify_end (self);
684 g_object_unref (helper->mail_op);
685 g_slice_free (SendNewMailHelper, helper);
689 run_queue_start (TnySendQueue *self,
692 RunQueueHelper *helper = (RunQueueHelper *) user_data;
693 ModestMailOperation *mail_op;
695 g_debug ("%s sending queue successfully started", __FUNCTION__);
697 /* Wait for the message to be sent */
698 mail_op = modest_mail_operation_new (NULL);
699 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
701 modest_mail_operation_run_queue (mail_op, helper->queue);
702 g_object_unref (mail_op);
704 /* Free the helper and end operation */
705 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
709 run_queue_error_happened (TnySendQueue *queue,
715 RunQueueHelper *helper = (RunQueueHelper *) user_data;
716 ModestMailOperationPrivate *priv;
718 /* If we are here this means that the send queue could not
719 start to send emails. Shouldn't happen as this means that
720 we could not create the thread */
721 g_debug ("%s sending queue failed to create the thread", __FUNCTION__);
723 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
724 priv->error = g_error_copy ((const GError *) error);
726 if (error->code != TNY_SYSTEM_ERROR_UNKNOWN) {
727 /* This code is here for safety reasons. It should
728 never be called, because that would mean that we
729 are not controlling some error case */
730 g_warning ("%s Error %s should not happen",
731 __FUNCTION__, error->message);
734 /* Free helper and end operation */
735 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_FAILED);
739 send_mail_on_added_to_outbox (TnySendQueue *send_queue,
745 ModestMailOperationPrivate *priv;
746 ModestMailOperation *self;
747 SendNewMailHelper *helper;
749 helper = (SendNewMailHelper *) user_data;
750 self = helper->mail_op;
751 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
757 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
758 MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
759 "Error adding a msg to the send queue\n");
760 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
762 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
766 if (helper->notify) {
767 TnyTransportAccount *trans_account;
768 ModestTnySendQueue *queue;
770 trans_account = (TnyTransportAccount *) modest_mail_operation_get_account (self);
772 queue = modest_runtime_get_send_queue (trans_account, TRUE);
774 RunQueueHelper *helper;
776 /* Create the helper */
777 helper = g_slice_new0 (RunQueueHelper);
778 helper->queue = g_object_ref (queue);
779 helper->self = g_object_ref (self);
781 /* if sending is ongoing wait for the queue to
782 stop. Otherwise wait for the queue-start
783 signal. It could happen that the queue
784 could not start, then check also the error
786 if (modest_tny_send_queue_sending_in_progress (queue)) {
787 run_queue_start (TNY_SEND_QUEUE (queue), helper);
789 helper->start_handler = g_signal_connect (queue, "queue-start",
790 G_CALLBACK (run_queue_start),
792 helper->error_handler = g_signal_connect (queue, "error-happened",
793 G_CALLBACK (run_queue_error_happened),
797 /* Finalize this mail operation */
798 modest_mail_operation_notify_end (self);
800 g_object_unref (trans_account);
802 g_warning ("No transport account for the operation");
806 g_object_unref (helper->mail_op);
807 g_slice_free (SendNewMailHelper, helper);
811 idle_create_msg_cb (gpointer idle_data)
813 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
815 /* This is a GDK lock because we are an idle callback and
816 * info->callback can contain Gtk+ code */
818 gdk_threads_enter (); /* CHECKED */
819 info->callback (info->mail_op, info->msg, info->userdata);
821 g_object_unref (info->mail_op);
823 g_object_unref (info->msg);
824 g_slice_free (CreateMsgIdleInfo, info);
825 gdk_threads_leave (); /* CHECKED */
831 create_msg_thread (gpointer thread_data)
833 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
834 TnyMsg *new_msg = NULL;
835 ModestMailOperationPrivate *priv;
838 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
839 if (info->html_body == NULL) {
840 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
841 info->bcc, info->subject,
842 info->references, info->in_reply_to,
844 info->attachments_list, &attached,
847 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
848 info->bcc, info->subject,
849 info->references, info->in_reply_to,
851 info->plain_body, info->attachments_list,
852 info->images_list, &attached,
859 /* Set priority flags in message */
860 header = tny_msg_get_header (new_msg);
861 tny_header_set_flag (header, info->priority_flags);
863 /* Set attachment flags in message */
864 if (info->attachments_list != NULL && attached > 0)
865 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
867 g_object_unref (G_OBJECT(header));
869 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
871 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
872 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
873 "modest: failed to create a new msg\n");
881 g_free (info->plain_body);
882 g_free (info->html_body);
883 g_free (info->subject);
884 g_free (info->references);
885 g_free (info->in_reply_to);
886 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
887 g_list_free (info->attachments_list);
888 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
889 g_list_free (info->images_list);
891 if (info->callback) {
892 CreateMsgIdleInfo *idle_info;
893 idle_info = g_slice_new0 (CreateMsgIdleInfo);
894 idle_info->mail_op = g_object_ref (info->mail_op);
895 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
896 idle_info->callback = info->callback;
897 idle_info->userdata = info->userdata;
898 g_idle_add (idle_create_msg_cb, idle_info);
900 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
903 g_object_unref (info->mail_op);
904 g_slice_free (CreateMsgInfo, info);
905 if (new_msg) g_object_unref(new_msg);
911 modest_mail_operation_create_msg (ModestMailOperation *self,
912 const gchar *from, const gchar *to,
913 const gchar *cc, const gchar *bcc,
914 const gchar *subject, const gchar *plain_body,
915 const gchar *html_body,
916 const GList *attachments_list,
917 const GList *images_list,
918 TnyHeaderFlags priority_flags,
919 const gchar *references,
920 const gchar *in_reply_to,
921 ModestMailOperationCreateMsgCallback callback,
924 CreateMsgInfo *info = NULL;
926 info = g_slice_new0 (CreateMsgInfo);
927 info->mail_op = g_object_ref (self);
929 info->from = g_strdup (from);
930 info->to = g_strdup (to);
931 info->cc = g_strdup (cc);
932 info->bcc = g_strdup (bcc);
933 info->subject = g_strdup (subject);
934 info->plain_body = g_strdup (plain_body);
935 info->html_body = g_strdup (html_body);
936 info->references = g_strdup (references);
937 info->in_reply_to = g_strdup (in_reply_to);
938 info->attachments_list = g_list_copy ((GList *) attachments_list);
939 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
940 info->images_list = g_list_copy ((GList *) images_list);
941 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
942 info->priority_flags = priority_flags;
944 info->callback = callback;
945 info->userdata = userdata;
947 g_thread_create (create_msg_thread, info, FALSE, NULL);
952 TnyTransportAccount *transport_account;
957 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
961 TnySendQueue *send_queue = NULL;
962 ModestMailOperationPrivate *priv = NULL;
963 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
964 TnyFolder *draft_folder = NULL;
965 TnyFolder *outbox_folder = NULL;
966 TnyHeader *header = NULL;
968 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
971 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
972 modest_mail_operation_notify_end (self);
976 if (priv->error && priv->error->code != MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
977 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
978 modest_mail_operation_notify_end (self);
982 /* Add message to send queue */
983 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (info->transport_account, TRUE));
984 if (!TNY_IS_SEND_QUEUE(send_queue)) {
986 g_error_free (priv->error);
989 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
990 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
991 "modest: could not find send queue for account\n");
992 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
993 modest_mail_operation_notify_end (self);
996 SendNewMailHelper *helper = g_slice_new (SendNewMailHelper);
997 helper->mail_op = g_object_ref (self);
998 helper->notify = (info->draft_msg == NULL);
1000 /* Add the msg to the queue. The callback will free
1002 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1004 tny_send_queue_add_async (send_queue, msg, send_mail_on_added_to_outbox,
1008 if (info->draft_msg != NULL) {
1009 TnyList *tmp_headers = NULL;
1010 TnyFolder *folder = NULL;
1011 TnyFolder *src_folder = NULL;
1012 TnyFolderType folder_type;
1013 TnyTransportAccount *transport_account = NULL;
1014 SendNewMailHelper *helper = NULL;
1016 /* To remove the old mail from its source folder, we need to get the
1017 * transport account of the original draft message (the transport account
1018 * might have been changed by the user) */
1019 header = tny_msg_get_header (info->draft_msg);
1020 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
1021 modest_runtime_get_account_store(), header);
1022 if (transport_account == NULL)
1023 transport_account = g_object_ref(info->transport_account);
1024 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
1025 TNY_FOLDER_TYPE_DRAFTS);
1026 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
1027 TNY_FOLDER_TYPE_OUTBOX);
1028 g_object_unref(transport_account);
1030 if (!draft_folder) {
1031 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
1033 modest_mail_operation_notify_end (self);
1036 if (!outbox_folder) {
1037 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
1039 modest_mail_operation_notify_end (self);
1043 folder = tny_msg_get_folder (info->draft_msg);
1044 if (folder == NULL) {
1045 modest_mail_operation_notify_end (self);
1048 folder_type = modest_tny_folder_guess_folder_type (folder);
1050 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1051 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1053 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
1054 src_folder = outbox_folder;
1056 src_folder = draft_folder;
1058 /* Note: This can fail (with a warning) if the message is not really already in a folder,
1059 * because this function requires it to have a UID. */
1060 helper = g_slice_new (SendNewMailHelper);
1061 helper->mail_op = g_object_ref (self);
1062 helper->notify = TRUE;
1064 tmp_headers = tny_simple_list_new ();
1065 tny_list_append (tmp_headers, (GObject*) header);
1066 tny_folder_remove_msgs_async (src_folder, tmp_headers, NULL, NULL, NULL);
1067 g_object_unref (tmp_headers);
1068 tny_folder_sync_async (src_folder, TRUE, send_mail_on_sync_async_cb,
1070 g_object_unref (folder);
1075 g_object_unref (header);
1076 if (info->draft_msg)
1077 g_object_unref (info->draft_msg);
1079 g_object_unref (draft_folder);
1081 g_object_unref (outbox_folder);
1082 if (info->transport_account)
1083 g_object_unref (info->transport_account);
1084 g_slice_free (SendNewMailInfo, info);
1088 modest_mail_operation_send_new_mail (ModestMailOperation *self,
1089 TnyTransportAccount *transport_account,
1091 const gchar *from, const gchar *to,
1092 const gchar *cc, const gchar *bcc,
1093 const gchar *subject, const gchar *plain_body,
1094 const gchar *html_body,
1095 const GList *attachments_list,
1096 const GList *images_list,
1097 const gchar *references,
1098 const gchar *in_reply_to,
1099 TnyHeaderFlags priority_flags)
1101 ModestMailOperationPrivate *priv = NULL;
1102 SendNewMailInfo *info;
1104 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1105 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1107 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1108 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
1109 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
1110 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1112 modest_mail_operation_notify_start (self);
1114 /* Check parametters */
1116 /* Set status failed and set an error */
1117 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1118 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1119 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
1120 _("Error trying to send a mail. You need to set at least one recipient"));
1121 modest_mail_operation_notify_end (self);
1124 info = g_slice_new0 (SendNewMailInfo);
1125 info->transport_account = transport_account;
1126 if (transport_account)
1127 g_object_ref (transport_account);
1128 info->draft_msg = draft_msg;
1130 g_object_ref (draft_msg);
1133 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1134 attachments_list, images_list, priority_flags,
1135 references, in_reply_to,
1136 modest_mail_operation_send_new_mail_cb, info);
1142 TnyTransportAccount *transport_account;
1144 SaveToDraftstCallback callback;
1148 ModestMailOperation *mailop;
1149 } SaveToDraftsAddMsgInfo;
1152 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1157 ModestMailOperationPrivate *priv = NULL;
1158 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1159 GError *io_error = NULL;
1161 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1163 if (priv->error && priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1164 io_error = priv->error;
1168 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1169 g_error_free(priv->error);
1172 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1174 if ((!priv->error) && (info->draft_msg != NULL)) {
1175 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1176 TnyFolder *src_folder = tny_header_get_folder (header);
1178 g_debug ("--- REMOVE AND SYNC");
1179 /* Remove the old draft */
1180 tny_folder_remove_msg (src_folder, header, NULL);
1182 /* Synchronize to expunge and to update the msg counts */
1183 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1184 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1185 g_debug ("--- REMOVED - SYNCED");
1187 g_object_unref (G_OBJECT(header));
1188 g_object_unref (G_OBJECT(src_folder));
1192 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1194 g_error_free (io_error);
1197 } else if (io_error) {
1198 priv->error = io_error;
1199 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
1201 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1204 /* Call the user callback */
1206 info->callback (info->mailop, info->msg, info->user_data);
1208 if (info->transport_account)
1209 g_object_unref (G_OBJECT(info->transport_account));
1210 if (info->draft_msg)
1211 g_object_unref (G_OBJECT (info->draft_msg));
1213 g_object_unref (G_OBJECT(info->drafts));
1215 g_object_unref (G_OBJECT (info->msg));
1217 modest_mail_operation_notify_end (info->mailop);
1218 g_object_unref(info->mailop);
1219 g_slice_free (SaveToDraftsAddMsgInfo, info);
1224 TnyTransportAccount *transport_account;
1226 SaveToDraftstCallback callback;
1231 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1235 TnyFolder *drafts = NULL;
1236 ModestMailOperationPrivate *priv = NULL;
1237 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1239 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1242 if (!(priv->error)) {
1243 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1244 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1245 "modest: failed to create a new msg\n");
1248 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1249 TNY_FOLDER_TYPE_DRAFTS);
1250 if (!drafts && !(priv->error)) {
1251 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1252 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1253 "modest: failed to create a new msg\n");
1257 if (!priv->error || priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1259 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1260 cb_info->transport_account = g_object_ref(info->transport_account);
1261 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1262 cb_info->callback = info->callback;
1263 cb_info->user_data = info->user_data;
1264 cb_info->drafts = g_object_ref(drafts);
1265 cb_info->msg = g_object_ref(msg);
1266 cb_info->mailop = g_object_ref(self);
1267 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1271 /* Call the user callback */
1272 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1274 info->callback (self, msg, info->user_data);
1275 modest_mail_operation_notify_end (self);
1279 g_object_unref (G_OBJECT(drafts));
1280 if (info->draft_msg)
1281 g_object_unref (G_OBJECT (info->draft_msg));
1282 if (info->transport_account)
1283 g_object_unref (G_OBJECT(info->transport_account));
1284 g_slice_free (SaveToDraftsInfo, info);
1288 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1289 TnyTransportAccount *transport_account,
1291 const gchar *from, const gchar *to,
1292 const gchar *cc, const gchar *bcc,
1293 const gchar *subject, const gchar *plain_body,
1294 const gchar *html_body,
1295 const GList *attachments_list,
1296 const GList *images_list,
1297 TnyHeaderFlags priority_flags,
1298 const gchar *references,
1299 const gchar *in_reply_to,
1300 SaveToDraftstCallback callback,
1303 ModestMailOperationPrivate *priv = NULL;
1304 SaveToDraftsInfo *info = NULL;
1306 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1307 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1309 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1311 /* Get account and set it into mail_operation */
1312 priv->account = g_object_ref (transport_account);
1313 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1315 info = g_slice_new0 (SaveToDraftsInfo);
1316 info->transport_account = g_object_ref (transport_account);
1317 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1318 info->callback = callback;
1319 info->user_data = user_data;
1321 g_debug ("--- CREATE MESSAGE");
1322 modest_mail_operation_notify_start (self);
1323 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1324 attachments_list, images_list, priority_flags,
1325 references, in_reply_to,
1326 modest_mail_operation_save_to_drafts_cb, info);
1331 ModestMailOperation *mail_op;
1332 TnyMimePart *mime_part;
1334 GetMimePartSizeCallback callback;
1336 } GetMimePartSizeInfo;
1338 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1339 /* We use this folder observer to track the headers that have been
1340 * added to a folder */
1343 TnyList *new_headers;
1344 } InternalFolderObserver;
1347 GObjectClass parent;
1348 } InternalFolderObserverClass;
1350 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1352 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1353 internal_folder_observer,
1355 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1359 foreach_add_item (gpointer header, gpointer user_data)
1361 tny_list_append (TNY_LIST (user_data), G_OBJECT (header));
1364 /* This is the method that looks for new messages in a folder */
1366 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1368 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1370 TnyFolderChangeChanged changed;
1372 changed = tny_folder_change_get_changed (change);
1374 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1377 /* Get added headers */
1378 list = tny_simple_list_new ();
1379 tny_folder_change_get_added_headers (change, list);
1381 /* Add them to the folder observer */
1382 tny_list_foreach (list, foreach_add_item,
1383 derived->new_headers);
1385 g_object_unref (G_OBJECT (list));
1390 internal_folder_observer_init (InternalFolderObserver *self)
1392 self->new_headers = tny_simple_list_new ();
1395 internal_folder_observer_finalize (GObject *object)
1397 InternalFolderObserver *self;
1399 self = (InternalFolderObserver *) object;
1400 g_object_unref (self->new_headers);
1402 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1405 tny_folder_observer_init (TnyFolderObserverIface *iface)
1407 iface->update = internal_folder_observer_update;
1410 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1412 GObjectClass *object_class;
1414 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1415 object_class = (GObjectClass*) klass;
1416 object_class->finalize = internal_folder_observer_finalize;
1420 destroy_update_account_info (UpdateAccountInfo *info)
1422 g_free (info->account_name);
1423 g_object_unref (info->folders);
1424 g_object_unref (info->mail_op);
1425 g_slice_free (UpdateAccountInfo, info);
1430 update_account_send_mail (UpdateAccountInfo *info)
1432 TnyTransportAccount *transport_account = NULL;
1433 ModestTnyAccountStore *account_store;
1435 account_store = modest_runtime_get_account_store ();
1437 /* We don't try to send messages while sending mails is blocked */
1438 if (modest_tny_account_store_is_send_mail_blocked (account_store))
1441 /* Get the transport account */
1442 transport_account = (TnyTransportAccount *)
1443 modest_tny_account_store_get_server_account (account_store, info->account_name,
1444 TNY_ACCOUNT_TYPE_TRANSPORT);
1446 if (transport_account) {
1447 ModestTnySendQueue *send_queue;
1451 send_queue = modest_runtime_get_send_queue (transport_account, TRUE);
1452 g_object_unref (transport_account);
1454 if (TNY_IS_SEND_QUEUE (send_queue)) {
1455 /* Get outbox folder */
1456 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1457 if (outbox) { /* this could fail in some cases */
1458 num_messages = tny_folder_get_all_count (outbox);
1459 g_object_unref (outbox);
1461 g_warning ("%s: could not get outbox", __FUNCTION__);
1465 if (num_messages != 0) {
1466 ModestMailOperation *mail_op;
1467 /* Reenable suspended items */
1468 mail_op = modest_mail_operation_new (NULL);
1469 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1471 modest_mail_operation_queue_wakeup (mail_op, MODEST_TNY_SEND_QUEUE (send_queue));
1474 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1482 update_account_get_msg_async_cb (TnyFolder *folder,
1488 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1489 ModestMailOperationPrivate *priv;
1491 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (msg_info->mail_op);
1494 if (TNY_IS_MSG (msg)) {
1495 TnyHeader *header = tny_msg_get_header (msg);
1498 ModestMailOperationState *state;
1499 state = modest_mail_operation_clone_state (msg_info->mail_op);
1500 msg_info->sum_total_bytes += tny_header_get_message_size (header);
1501 state->bytes_done = msg_info->sum_total_bytes;
1502 state->bytes_total = msg_info->total_bytes;
1504 /* Notify the status change. Only notify about changes
1505 referred to bytes */
1506 g_signal_emit (G_OBJECT (msg_info->mail_op),
1507 signals[PROGRESS_CHANGED_SIGNAL],
1510 g_object_unref (header);
1511 g_slice_free (ModestMailOperationState, state);
1515 if (priv->done == priv->total) {
1516 TnyList *new_headers;
1517 UpdateAccountInfo *info;
1519 /* After getting all the messages send the ones in the
1521 info = (UpdateAccountInfo *) msg_info->user_data;
1522 update_account_send_mail (info);
1524 /* Check if the operation was a success */
1526 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1528 /* Call the user callback and free */
1529 new_headers = tny_iterator_get_list (msg_info->more_msgs);
1530 update_account_notify_user_and_free (info, new_headers);
1531 g_object_unref (new_headers);
1533 /* Delete the helper */
1534 g_object_unref (msg_info->more_msgs);
1535 g_object_unref (msg_info->mail_op);
1536 g_slice_free (GetMsgInfo, msg_info);
1541 update_account_notify_user_and_free (UpdateAccountInfo *info,
1542 TnyList *new_headers)
1544 /* Set the account back to not busy */
1545 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (),
1546 info->account_name, FALSE);
1550 info->callback (info->mail_op, new_headers, info->user_data);
1552 /* Mail operation end */
1553 modest_mail_operation_notify_end (info->mail_op);
1557 g_object_unref (new_headers);
1558 destroy_update_account_info (info);
1562 inbox_refreshed_cb (TnyFolder *inbox,
1567 UpdateAccountInfo *info;
1568 ModestMailOperationPrivate *priv;
1569 TnyIterator *new_headers_iter;
1570 GPtrArray *new_headers_array = NULL;
1571 gint max_size, retrieve_limit, i;
1572 ModestAccountMgr *mgr;
1573 ModestAccountRetrieveType retrieve_type;
1574 TnyList *new_headers = NULL;
1575 gboolean headers_only, ignore_limit;
1576 time_t time_to_store;
1578 info = (UpdateAccountInfo *) user_data;
1579 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1580 mgr = modest_runtime_get_account_mgr ();
1582 if (canceled || err) {
1583 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1585 priv->error = g_error_copy (err);
1587 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1588 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1592 tny_folder_remove_observer (inbox, info->inbox_observer);
1593 g_object_unref (info->inbox_observer);
1594 info->inbox_observer = NULL;
1596 /* Notify the user about the error and then exit */
1597 update_account_notify_user_and_free (info, NULL);
1602 /* Try to send anyway */
1606 /* Set the last updated as the current time */
1607 #ifdef MODEST_USE_LIBTIME
1609 time_get_utc (&utc_tm);
1610 time_to_store = time_mktime (&utc_tm, "GMT");
1612 time_to_store = time (NULL);
1614 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
1616 /* Get the message max size */
1617 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1618 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1620 max_size = G_MAXINT;
1622 max_size = max_size * KB;
1624 /* Create the new headers array. We need it to sort the
1625 new headers by date */
1626 new_headers_array = g_ptr_array_new ();
1627 if (info->inbox_observer) {
1628 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1629 while (!tny_iterator_is_done (new_headers_iter)) {
1630 TnyHeader *header = NULL;
1632 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1633 /* Apply per-message size limits */
1634 if (tny_header_get_message_size (header) < max_size)
1635 g_ptr_array_add (new_headers_array, g_object_ref (header));
1637 g_object_unref (header);
1638 tny_iterator_next (new_headers_iter);
1640 g_object_unref (new_headers_iter);
1642 tny_folder_remove_observer (inbox, info->inbox_observer);
1643 g_object_unref (info->inbox_observer);
1644 info->inbox_observer = NULL;
1647 if (new_headers_array->len == 0) {
1648 g_ptr_array_free (new_headers_array, FALSE);
1652 /* Get per-account message amount retrieval limit */
1653 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1654 if (retrieve_limit == 0)
1655 retrieve_limit = G_MAXINT;
1657 /* Get per-account retrieval type */
1658 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1659 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1662 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1664 /* Ask the users if they want to retrieve all the messages
1665 even though the limit was exceeded */
1666 ignore_limit = FALSE;
1667 if (new_headers_array->len > retrieve_limit) {
1668 /* Ask the user if a callback has been specified and
1669 if the mail operation has a source (this means that
1670 was invoked by the user and not automatically by a
1672 if (info->retrieve_all_cb && info->interactive)
1673 ignore_limit = info->retrieve_all_cb (priv->source,
1674 new_headers_array->len,
1678 /* Copy the headers to a list and free the array */
1679 new_headers = tny_simple_list_new ();
1680 for (i=0; i < new_headers_array->len; i++) {
1681 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1682 /* We want the first element to be the most recent
1683 one, that's why we reverse the list */
1684 tny_list_prepend (new_headers, G_OBJECT (header));
1686 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1687 g_ptr_array_free (new_headers_array, FALSE);
1689 if (!headers_only && (tny_list_get_length (new_headers) > 0)) {
1692 GetMsgInfo *msg_info;
1696 priv->total = tny_list_get_length (new_headers);
1698 priv->total = MIN (tny_list_get_length (new_headers), retrieve_limit);
1700 iter = tny_list_create_iterator (new_headers);
1702 /* Create the message info */
1703 msg_info = g_slice_new0 (GetMsgInfo);
1704 msg_info->mail_op = g_object_ref (info->mail_op);
1705 msg_info->total_bytes = compute_message_list_size (new_headers, priv->total);
1706 msg_info->more_msgs = g_object_ref (iter);
1707 msg_info->user_data = info;
1709 while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) {
1710 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1711 TnyFolder *folder = tny_header_get_folder (header);
1713 /* Get message in an async way */
1714 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1717 g_object_unref (folder);
1720 tny_iterator_next (iter);
1722 g_object_unref (iter);
1724 /* The mail operation will finish when the last
1725 message is retrieved */
1729 /* If we don't have to retrieve the new messages then
1731 update_account_send_mail (info);
1733 /* Check if the operation was a success */
1735 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1737 /* Call the user callback and free */
1738 update_account_notify_user_and_free (info, new_headers);
1742 inbox_refresh_status_update (GObject *obj,
1746 UpdateAccountInfo *info = NULL;
1747 ModestMailOperation *self = NULL;
1748 ModestMailOperationPrivate *priv = NULL;
1749 ModestMailOperationState *state;
1751 g_return_if_fail (user_data != NULL);
1752 g_return_if_fail (status != NULL);
1754 /* Show only the status information we want */
1755 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
1758 info = (UpdateAccountInfo *) user_data;
1759 self = info->mail_op;
1760 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1762 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1764 priv->done = status->position;
1765 priv->total = status->of_total;
1767 state = modest_mail_operation_clone_state (self);
1769 /* This is not a GDK lock because we are a Tinymail callback and
1770 * Tinymail already acquires the Gdk lock */
1771 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1773 g_slice_free (ModestMailOperationState, state);
1777 recurse_folders_async_cb (TnyFolderStore *folder_store,
1783 UpdateAccountInfo *info;
1784 ModestMailOperationPrivate *priv;
1786 info = (UpdateAccountInfo *) user_data;
1787 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1789 if (err || canceled) {
1790 /* If the error was previosly set by another callback
1791 don't set it again */
1793 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1795 priv->error = g_error_copy (err);
1797 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1798 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1802 /* We're not getting INBOX children if we don't want to poke all */
1803 TnyIterator *iter = tny_list_create_iterator (list);
1804 while (!tny_iterator_is_done (iter)) {
1805 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1807 /* Add to the list of all folders */
1808 tny_list_append (info->folders, (GObject *) folder);
1810 if (info->poke_all) {
1811 TnyList *folders = tny_simple_list_new ();
1812 /* Add pending call */
1813 info->pending_calls++;
1815 tny_folder_store_get_folders_async (folder, folders, NULL, FALSE,
1816 recurse_folders_async_cb,
1818 g_object_unref (folders);
1821 g_object_unref (G_OBJECT (folder));
1823 tny_iterator_next (iter);
1825 g_object_unref (G_OBJECT (iter));
1828 /* Remove my own pending call */
1829 info->pending_calls--;
1831 /* This means that we have all the folders */
1832 if (info->pending_calls == 0) {
1833 TnyIterator *iter_all_folders;
1834 TnyFolder *inbox = NULL;
1836 /* If there was any error do not continue */
1838 update_account_notify_user_and_free (info, NULL);
1842 iter_all_folders = tny_list_create_iterator (info->folders);
1844 /* Do a poke status over all folders */
1845 while (!tny_iterator_is_done (iter_all_folders) &&
1846 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1847 TnyFolder *folder = NULL;
1849 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1851 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1852 /* Get a reference to the INBOX */
1853 inbox = g_object_ref (folder);
1855 /* Issue a poke status over the folder */
1857 tny_folder_poke_status (folder);
1860 /* Free and go to next */
1861 g_object_unref (folder);
1862 tny_iterator_next (iter_all_folders);
1864 g_object_unref (iter_all_folders);
1866 /* Refresh the INBOX */
1868 /* Refresh the folder. Our observer receives
1869 * the new emails during folder refreshes, so
1870 * we can use observer->new_headers
1872 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1873 tny_folder_add_observer (inbox, info->inbox_observer);
1875 /* Refresh the INBOX */
1876 tny_folder_refresh_async (inbox, inbox_refreshed_cb, inbox_refresh_status_update, info);
1877 g_object_unref (inbox);
1879 /* We could not perform the inbox refresh but
1880 we'll try to send mails anyway */
1881 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1887 modest_mail_operation_update_account (ModestMailOperation *self,
1888 const gchar *account_name,
1890 gboolean interactive,
1891 RetrieveAllCallback retrieve_all_cb,
1892 UpdateAccountCallback callback,
1895 UpdateAccountInfo *info = NULL;
1896 ModestMailOperationPrivate *priv = NULL;
1897 ModestTnyAccountStore *account_store = NULL;
1899 ModestMailOperationState *state;
1901 /* Init mail operation */
1902 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1905 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1906 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1908 /* Get the store account */
1909 account_store = modest_runtime_get_account_store ();
1911 modest_tny_account_store_get_server_account (account_store,
1913 TNY_ACCOUNT_TYPE_STORE);
1915 /* The above function could return NULL */
1916 if (!priv->account) {
1917 /* Check if the operation was a success */
1918 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1919 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1921 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1923 /* Call the user callback */
1925 callback (self, NULL, user_data);
1927 /* Notify about operation end */
1928 modest_mail_operation_notify_end (self);
1933 /* We have once seen priv->account getting finalized during this code,
1934 * therefore adding a reference (bug #82296) */
1936 g_object_ref (priv->account);
1938 /* Create the helper object */
1939 info = g_slice_new0 (UpdateAccountInfo);
1940 info->pending_calls = 1;
1941 info->folders = tny_simple_list_new ();
1942 info->mail_op = g_object_ref (self);
1943 info->poke_all = poke_all;
1944 info->interactive = interactive;
1945 info->account_name = g_strdup (account_name);
1946 info->callback = callback;
1947 info->user_data = user_data;
1948 info->retrieve_all_cb = retrieve_all_cb;
1950 /* Set account busy */
1951 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1952 modest_mail_operation_notify_start (self);
1954 /* notify about the start of the operation */
1955 state = modest_mail_operation_clone_state (self);
1959 /* Start notifying progress */
1960 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1961 g_slice_free (ModestMailOperationState, state);
1963 /* Get all folders and continue in the callback */
1964 folders = tny_simple_list_new ();
1965 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
1966 folders, NULL, FALSE,
1967 recurse_folders_async_cb,
1969 g_object_unref (folders);
1971 g_object_unref (priv->account);
1976 * Used to notify the queue from the main
1977 * loop. We call it inside an idle call to achieve that
1980 idle_notify_queue (gpointer data)
1982 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1984 gdk_threads_enter ();
1985 modest_mail_operation_notify_end (mail_op);
1986 gdk_threads_leave ();
1987 g_object_unref (mail_op);
1993 compare_headers_by_date (gconstpointer a,
1996 TnyHeader **header1, **header2;
1997 time_t sent1, sent2;
1999 header1 = (TnyHeader **) a;
2000 header2 = (TnyHeader **) b;
2002 sent1 = tny_header_get_date_sent (*header1);
2003 sent2 = tny_header_get_date_sent (*header2);
2005 /* We want the most recent ones (greater time_t) at the
2014 /* ******************************************************************* */
2015 /* ************************** STORE ACTIONS ************************* */
2016 /* ******************************************************************* */
2019 ModestMailOperation *mail_op;
2020 CreateFolderUserCallback callback;
2026 create_folder_cb (TnyFolderStore *parent_folder,
2028 TnyFolder *new_folder,
2032 ModestMailOperationPrivate *priv;
2033 CreateFolderInfo *info;
2035 info = (CreateFolderInfo *) user_data;
2036 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2038 if (canceled || err) {
2039 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2041 priv->error = g_error_copy (err);
2043 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2044 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2047 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2050 /* The user will unref the new_folder */
2052 info->callback (info->mail_op, parent_folder,
2053 new_folder, info->user_data);
2055 /* Notify about operation end */
2056 modest_mail_operation_notify_end (info->mail_op);
2059 g_object_unref (info->mail_op);
2060 g_slice_free (CreateFolderInfo, info);
2064 modest_mail_operation_create_folder (ModestMailOperation *self,
2065 TnyFolderStore *parent,
2067 CreateFolderUserCallback callback,
2070 ModestMailOperationPrivate *priv;
2072 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2073 g_return_if_fail (name);
2075 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2076 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2077 priv->account = (TNY_IS_ACCOUNT (parent)) ?
2078 g_object_ref (parent) :
2079 modest_tny_folder_get_account (TNY_FOLDER (parent));
2081 /* Check for already existing folder */
2082 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
2083 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2084 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2085 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2086 _CS("ckdg_ib_folder_already_exists"));
2090 if (TNY_IS_FOLDER (parent)) {
2091 /* Check folder rules */
2092 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2093 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2094 /* Set status failed and set an error */
2095 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2096 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2097 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2098 _("mail_in_ui_folder_create_error"));
2102 if (!priv->error && (!strcmp (name, " ") || strchr (name, '/'))) {
2103 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2104 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2105 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2106 _("mail_in_ui_folder_create_error"));
2110 CreateFolderInfo *info;
2112 info = g_slice_new0 (CreateFolderInfo);
2113 info->mail_op = g_object_ref (self);
2114 info->callback = callback;
2115 info->user_data = user_data;
2117 modest_mail_operation_notify_start (self);
2119 /* Create the folder */
2120 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
2123 /* Call the user callback anyway */
2125 callback (self, parent, NULL, user_data);
2126 /* Notify about operation end */
2127 modest_mail_operation_notify_end (self);
2132 modest_mail_operation_remove_folder (ModestMailOperation *self,
2134 gboolean remove_to_trash)
2136 ModestMailOperationPrivate *priv;
2137 ModestTnyFolderRules rules;
2139 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2140 g_return_if_fail (TNY_IS_FOLDER (folder));
2142 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2144 /* Check folder rules */
2145 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2146 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
2147 /* Set status failed and set an error */
2148 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2149 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2150 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2151 _("mail_in_ui_folder_delete_error"));
2155 /* Get the account */
2156 priv->account = modest_tny_folder_get_account (folder);
2157 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2159 /* Delete folder or move to trash */
2160 if (remove_to_trash) {
2161 TnyFolder *trash_folder = NULL;
2162 trash_folder = modest_tny_account_get_special_folder (priv->account,
2163 TNY_FOLDER_TYPE_TRASH);
2164 /* TODO: error_handling */
2166 modest_mail_operation_notify_start (self);
2167 modest_mail_operation_xfer_folder (self, folder,
2168 TNY_FOLDER_STORE (trash_folder),
2170 g_object_unref (trash_folder);
2172 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
2175 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
2177 modest_mail_operation_notify_start (self);
2178 tny_folder_store_remove_folder (parent, folder, &(priv->error));
2179 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
2182 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2184 g_object_unref (parent);
2186 g_warning ("%s: could not get parent folder", __FUNCTION__);
2190 /* Notify about operation end */
2191 modest_mail_operation_notify_end (self);
2195 transfer_folder_status_cb (GObject *obj,
2199 ModestMailOperation *self;
2200 ModestMailOperationPrivate *priv;
2201 ModestMailOperationState *state;
2202 XFerFolderAsyncHelper *helper;
2204 g_return_if_fail (status != NULL);
2206 /* Show only the status information we want */
2207 if (status->code != TNY_FOLDER_STATUS_CODE_COPY_FOLDER)
2210 helper = (XFerFolderAsyncHelper *) user_data;
2211 g_return_if_fail (helper != NULL);
2213 self = helper->mail_op;
2214 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2216 priv->done = status->position;
2217 priv->total = status->of_total;
2219 state = modest_mail_operation_clone_state (self);
2221 /* This is not a GDK lock because we are a Tinymail callback
2222 * which is already GDK locked by Tinymail */
2224 /* no gdk_threads_enter (), CHECKED */
2226 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2228 /* no gdk_threads_leave (), CHECKED */
2230 g_slice_free (ModestMailOperationState, state);
2234 transfer_folder_cb (TnyFolder *folder,
2236 TnyFolderStore *into,
2237 TnyFolder *new_folder,
2241 XFerFolderAsyncHelper *helper;
2242 ModestMailOperation *self = NULL;
2243 ModestMailOperationPrivate *priv = NULL;
2245 helper = (XFerFolderAsyncHelper *) user_data;
2246 g_return_if_fail (helper != NULL);
2248 self = helper->mail_op;
2249 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2252 priv->error = g_error_copy (err);
2254 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2255 } else if (cancelled) {
2256 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2257 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2258 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2259 _("Transference of %s was cancelled."),
2260 tny_folder_get_name (folder));
2263 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2266 /* Update state of new folder */
2268 tny_folder_refresh_async (new_folder, NULL, NULL, NULL);
2269 tny_folder_poke_status (new_folder);
2272 /* Notify about operation end */
2273 modest_mail_operation_notify_end (self);
2275 /* If user defined callback function was defined, call it */
2276 if (helper->user_callback) {
2278 /* This is not a GDK lock because we are a Tinymail callback
2279 * which is already GDK locked by Tinymail */
2281 /* no gdk_threads_enter (), CHECKED */
2282 helper->user_callback (self, new_folder, helper->user_data);
2283 /* no gdk_threads_leave () , CHECKED */
2287 g_object_unref (helper->mail_op);
2288 g_slice_free (XFerFolderAsyncHelper, helper);
2293 * This function checks if the new name is a valid name for our local
2294 * folders account. The new name could not be the same than then name
2295 * of any of the mandatory local folders
2297 * We can not rely on tinymail because tinymail does not check the
2298 * name of the virtual folders that the account could have in the case
2299 * that we're doing a rename (because it directly calls Camel which
2300 * knows nothing about our virtual folders).
2302 * In the case of an actual copy/move (i.e. move/copy a folder between
2303 * accounts) tinymail uses the tny_folder_store_create_account which
2304 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2305 * checks the new name of the folder, so this call in that case
2306 * wouldn't be needed. *But* NOTE that if tinymail changes its
2307 * implementation (if folder transfers within the same account is no
2308 * longer implemented as a rename) this call will allow Modest to work
2311 * If the new name is not valid, this function will set the status to
2312 * failed and will set also an error in the mail operation
2315 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2316 TnyFolderStore *into,
2317 const gchar *new_name)
2319 if (TNY_IS_ACCOUNT (into) &&
2320 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2321 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2323 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2324 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2325 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2326 _CS("ckdg_ib_folder_already_exists"));
2333 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2335 TnyFolderStore *parent,
2336 gboolean delete_original,
2337 XferFolderAsyncUserCallback user_callback,
2340 ModestMailOperationPrivate *priv = NULL;
2341 ModestTnyFolderRules parent_rules = 0, rules;
2342 XFerFolderAsyncHelper *helper = NULL;
2343 const gchar *folder_name = NULL;
2344 const gchar *error_msg;
2346 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2347 g_return_if_fail (TNY_IS_FOLDER (folder));
2348 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2350 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2351 folder_name = tny_folder_get_name (folder);
2353 /* Set the error msg */
2354 error_msg = _("mail_in_ui_folder_move_target_error");
2356 /* Get account and set it into mail_operation */
2357 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2358 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2359 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2361 /* Get folder rules */
2362 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2363 if (TNY_IS_FOLDER (parent))
2364 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2366 /* Apply operation constraints */
2367 if ((gpointer) parent == (gpointer) folder ||
2368 (!TNY_IS_FOLDER_STORE (parent)) ||
2369 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2372 } else if (TNY_IS_FOLDER (parent) &&
2373 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2377 } else if (TNY_IS_FOLDER (parent) &&
2378 TNY_IS_FOLDER_STORE (folder) &&
2379 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2380 TNY_FOLDER_STORE (folder))) {
2381 /* Do not move a parent into a child */
2383 } else if (TNY_IS_FOLDER_STORE (parent) &&
2384 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2385 /* Check that the new folder name is not used by any
2388 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2389 /* Check that the new folder name is not used by any
2390 special local folder */
2393 /* Create the helper */
2394 helper = g_slice_new0 (XFerFolderAsyncHelper);
2395 helper->mail_op = g_object_ref (self);
2396 helper->user_callback = user_callback;
2397 helper->user_data = user_data;
2399 /* Move/Copy folder */
2400 modest_mail_operation_notify_start (self);
2401 tny_folder_copy_async (folder,
2403 tny_folder_get_name (folder),
2406 transfer_folder_status_cb,
2412 /* Set status failed and set an error */
2413 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2414 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2415 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2418 /* Call the user callback if exists */
2420 user_callback (self, NULL, user_data);
2422 /* Notify the queue */
2423 modest_mail_operation_notify_end (self);
2427 modest_mail_operation_rename_folder (ModestMailOperation *self,
2430 XferFolderAsyncUserCallback user_callback,
2433 ModestMailOperationPrivate *priv;
2434 ModestTnyFolderRules rules;
2435 XFerFolderAsyncHelper *helper;
2437 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2438 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2439 g_return_if_fail (name);
2441 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2443 /* Get account and set it into mail_operation */
2444 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2445 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2447 /* Check folder rules */
2448 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2449 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2451 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2454 TnyFolderStore *into;
2456 into = tny_folder_get_folder_store (folder);
2458 /* Check that the new folder name is not used by any
2459 special local folder */
2460 if (new_name_valid_if_local_account (priv, into, name)) {
2461 /* Create the helper */
2462 helper = g_slice_new0 (XFerFolderAsyncHelper);
2463 helper->mail_op = g_object_ref(self);
2464 helper->user_callback = user_callback;
2465 helper->user_data = user_data;
2467 /* Rename. Camel handles folder subscription/unsubscription */
2468 modest_mail_operation_notify_start (self);
2469 tny_folder_copy_async (folder, into, name, TRUE,
2471 transfer_folder_status_cb,
2473 g_object_unref (into);
2475 g_object_unref (into);
2482 /* Set status failed and set an error */
2483 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2484 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2485 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2486 _("FIXME: unable to rename"));
2489 user_callback (self, NULL, user_data);
2491 /* Notify about operation end */
2492 modest_mail_operation_notify_end (self);
2495 /* ******************************************************************* */
2496 /* ************************** MSG ACTIONS ************************* */
2497 /* ******************************************************************* */
2500 modest_mail_operation_find_msg (ModestMailOperation *self,
2502 const gchar *msg_uid,
2503 gboolean progress_feedback,
2504 GetMsgAsyncUserCallback user_callback,
2507 GetMsgInfo *helper = NULL;
2508 ModestMailOperationPrivate *priv;
2510 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2511 g_return_if_fail (msg_uid != NULL);
2513 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2514 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2518 /* Check memory low */
2519 if (_check_memory_low (self)) {
2521 user_callback (self, NULL, FALSE, NULL, priv->error, user_data);
2522 modest_mail_operation_notify_end (self);
2526 /* Get account and set it into mail_operation */
2527 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2529 /* Check for cached messages */
2530 if (progress_feedback) {
2531 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2533 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2536 /* Create the helper */
2537 helper = g_slice_new0 (GetMsgInfo);
2538 helper->header = NULL;
2539 helper->mail_op = g_object_ref (self);
2540 helper->user_callback = user_callback;
2541 helper->user_data = user_data;
2542 helper->destroy_notify = NULL;
2543 helper->last_total_bytes = 0;
2544 helper->sum_total_bytes = 0;
2545 helper->total_bytes = 0;
2546 helper->more_msgs = NULL;
2548 modest_mail_operation_notify_start (self);
2550 /* notify about the start of the operation */
2551 ModestMailOperationState *state;
2552 state = modest_mail_operation_clone_state (self);
2555 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2557 g_slice_free (ModestMailOperationState, state);
2559 tny_folder_find_msg_async (folder, msg_uid, get_msg_async_cb, get_msg_status_cb, helper);
2563 modest_mail_operation_get_msg (ModestMailOperation *self,
2565 gboolean progress_feedback,
2566 GetMsgAsyncUserCallback user_callback,
2569 GetMsgInfo *helper = NULL;
2571 ModestMailOperationPrivate *priv;
2573 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2574 g_return_if_fail (TNY_IS_HEADER (header));
2576 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2577 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2581 /* Check memory low */
2582 if (_check_memory_low (self)) {
2584 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2585 modest_mail_operation_notify_end (self);
2589 /* Get account and set it into mail_operation */
2590 folder = tny_header_get_folder (header);
2591 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2593 /* Check for cached messages */
2594 if (progress_feedback) {
2595 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2596 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2598 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2600 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2603 /* Create the helper */
2604 helper = g_slice_new0 (GetMsgInfo);
2605 helper->header = g_object_ref (header);
2606 helper->mail_op = g_object_ref (self);
2607 helper->user_callback = user_callback;
2608 helper->user_data = user_data;
2609 helper->destroy_notify = NULL;
2610 helper->last_total_bytes = 0;
2611 helper->sum_total_bytes = 0;
2612 helper->total_bytes = tny_header_get_message_size (header);
2613 helper->more_msgs = NULL;
2615 modest_mail_operation_notify_start (self);
2617 /* notify about the start of the operation */
2618 ModestMailOperationState *state;
2619 state = modest_mail_operation_clone_state (self);
2622 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2624 g_slice_free (ModestMailOperationState, state);
2626 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2628 g_object_unref (G_OBJECT (folder));
2632 get_msg_status_cb (GObject *obj,
2636 GetMsgInfo *helper = NULL;
2638 g_return_if_fail (status != NULL);
2640 /* Show only the status information we want */
2641 if (status->code != TNY_FOLDER_STATUS_CODE_GET_MSG)
2644 helper = (GetMsgInfo *) user_data;
2645 g_return_if_fail (helper != NULL);
2647 /* Notify progress */
2648 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2649 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2653 get_msg_async_cb (TnyFolder *folder,
2659 GetMsgInfo *info = NULL;
2660 ModestMailOperationPrivate *priv = NULL;
2663 info = (GetMsgInfo *) user_data;
2665 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2668 if (info->more_msgs) {
2669 tny_iterator_next (info->more_msgs);
2670 finished = (tny_iterator_is_done (info->more_msgs));
2672 finished = (priv->done == priv->total) ? TRUE : FALSE;
2675 /* If canceled by the user, ignore the error given by Tinymail */
2679 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2681 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2682 priv->error = g_error_copy ((const GError *) err);
2684 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2686 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2687 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2690 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2691 /* Set the success status before calling the user callback */
2692 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2695 if (info->header == NULL && msg)
2696 info->header = tny_msg_get_header (msg);
2698 /* Call the user callback */
2699 if (info->user_callback)
2700 info->user_callback (info->mail_op, info->header, canceled,
2701 msg, err, info->user_data);
2703 /* Notify about operation end if this is the last callback */
2705 /* Free user data */
2706 if (info->destroy_notify)
2707 info->destroy_notify (info->user_data);
2709 /* Notify about operation end */
2710 modest_mail_operation_notify_end (info->mail_op);
2713 if (info->more_msgs)
2714 g_object_unref (info->more_msgs);
2716 g_object_unref (info->header);
2717 g_object_unref (info->mail_op);
2718 g_slice_free (GetMsgInfo, info);
2719 } else if (info->more_msgs) {
2720 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2721 TnyFolder *folder = tny_header_get_folder (header);
2723 g_object_unref (info->header);
2724 info->header = g_object_ref (header);
2726 /* Retrieve the next message */
2727 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2729 g_object_unref (header);
2730 g_object_unref (folder);
2732 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2737 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2738 TnyList *header_list,
2739 GetMsgAsyncUserCallback user_callback,
2741 GDestroyNotify notify)
2743 ModestMailOperationPrivate *priv = NULL;
2745 TnyIterator *iter = NULL;
2746 gboolean has_uncached_messages;
2748 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2750 /* Init mail operation */
2751 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2752 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2754 priv->total = tny_list_get_length(header_list);
2756 /* Check memory low */
2757 if (_check_memory_low (self)) {
2758 if (user_callback) {
2759 TnyHeader *header = NULL;
2762 if (tny_list_get_length (header_list) > 0) {
2763 iter = tny_list_create_iterator (header_list);
2764 header = (TnyHeader *) tny_iterator_get_current (iter);
2765 g_object_unref (iter);
2767 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2769 g_object_unref (header);
2773 /* Notify about operation end */
2774 modest_mail_operation_notify_end (self);
2778 /* Check uncached messages */
2779 for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
2780 !has_uncached_messages && !tny_iterator_is_done (iter);
2781 tny_iterator_next (iter)) {
2784 header = (TnyHeader *) tny_iterator_get_current (iter);
2785 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
2786 has_uncached_messages = TRUE;
2787 g_object_unref (header);
2789 g_object_unref (iter);
2790 priv->op_type = has_uncached_messages?MODEST_MAIL_OPERATION_TYPE_RECEIVE:MODEST_MAIL_OPERATION_TYPE_OPEN;
2792 /* Get account and set it into mail_operation */
2793 if (tny_list_get_length (header_list) >= 1) {
2794 TnyIterator *iterator = tny_list_create_iterator (header_list);
2795 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2797 TnyFolder *folder = tny_header_get_folder (header);
2799 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2800 g_object_unref (folder);
2802 g_object_unref (header);
2804 g_object_unref (iterator);
2807 msg_list_size = compute_message_list_size (header_list, 0);
2809 modest_mail_operation_notify_start (self);
2810 iter = tny_list_create_iterator (header_list);
2811 if (!tny_iterator_is_done (iter)) {
2812 /* notify about the start of the operation */
2813 ModestMailOperationState *state;
2814 state = modest_mail_operation_clone_state (self);
2817 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2820 GetMsgInfo *msg_info = NULL;
2821 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2822 TnyFolder *folder = tny_header_get_folder (header);
2824 /* Create the message info */
2825 msg_info = g_slice_new0 (GetMsgInfo);
2826 msg_info->mail_op = g_object_ref (self);
2827 msg_info->header = g_object_ref (header);
2828 msg_info->more_msgs = g_object_ref (iter);
2829 msg_info->user_callback = user_callback;
2830 msg_info->user_data = user_data;
2831 msg_info->destroy_notify = notify;
2832 msg_info->last_total_bytes = 0;
2833 msg_info->sum_total_bytes = 0;
2834 msg_info->total_bytes = msg_list_size;
2836 /* The callback will call it per each header */
2837 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2839 /* Free and go on */
2840 g_object_unref (header);
2841 g_object_unref (folder);
2842 g_slice_free (ModestMailOperationState, state);
2844 g_object_unref (iter);
2849 remove_msgs_async_cb (TnyFolder *folder,
2854 gboolean expunge, leave_on_server;
2855 const gchar *account_name;
2856 TnyAccount *account;
2857 ModestProtocolType account_proto = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2858 ModestMailOperation *self;
2859 ModestMailOperationPrivate *priv;
2860 ModestProtocolRegistry *protocol_registry;
2862 self = (ModestMailOperation *) user_data;
2863 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2864 protocol_registry = modest_runtime_get_protocol_registry ();
2866 if (canceled || err) {
2867 /* If canceled by the user, ignore the error given by Tinymail */
2869 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2871 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2872 priv->error = g_error_copy ((const GError *) err);
2873 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2876 modest_mail_operation_notify_end (self);
2877 g_object_unref (self);
2881 account = modest_tny_folder_get_account (folder);
2882 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2884 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2886 account_proto = modest_tny_account_get_protocol_type (account);
2887 g_object_unref (account);
2889 if ((modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto) &&
2890 !leave_on_server) ||
2891 !modest_tny_folder_is_remote_folder (folder))
2897 tny_folder_sync_async(folder, expunge, sync_folder_finish_callback,
2902 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2904 gboolean remove_to_trash /*ignored*/)
2906 TnyFolder *folder = NULL;
2907 ModestMailOperationPrivate *priv;
2908 TnyIterator *iter = NULL;
2909 TnyHeader *header = NULL;
2910 TnyList *remove_headers = NULL;
2911 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2912 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2914 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2915 g_return_if_fail (TNY_IS_LIST (headers));
2917 if (remove_to_trash)
2918 g_warning ("remove to trash is not implemented");
2920 if (tny_list_get_length(headers) == 0) {
2921 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2922 goto cleanup; /* nothing to do */
2925 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2927 /* Get folder from first header and sync it */
2928 iter = tny_list_create_iterator (headers);
2929 header = TNY_HEADER (tny_iterator_get_current (iter));
2930 g_object_unref (iter);
2932 folder = tny_header_get_folder (header);
2933 if (!TNY_IS_FOLDER(folder)) {
2934 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2938 /* Use the merged folder if we're removing messages from outbox */
2939 if (modest_tny_folder_is_local_folder (folder)) {
2940 ModestTnyLocalFoldersAccount *local_account;
2942 local_account = (ModestTnyLocalFoldersAccount *)
2943 modest_tny_account_store_get_local_folders_account (accstore);
2944 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2945 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2946 g_object_unref (folder);
2947 folder = modest_tny_local_folders_account_get_merged_outbox (local_account);
2949 g_object_unref (local_account);
2952 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2953 TnyIterator *headers_iter = tny_list_create_iterator (headers);
2955 while (!tny_iterator_is_done (headers_iter)) {
2956 TnyTransportAccount *traccount = NULL;
2957 TnyHeader *hdr = NULL;
2959 hdr = TNY_HEADER (tny_iterator_get_current (headers_iter));
2960 traccount = modest_tny_account_store_get_transport_account_from_outbox_header (accstore,
2963 ModestTnySendQueueStatus status;
2964 ModestTnySendQueue *send_queue;
2966 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
2967 if (TNY_IS_SEND_QUEUE (send_queue)) {
2970 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2971 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2972 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2973 if (G_UNLIKELY (remove_headers == NULL))
2974 remove_headers = tny_simple_list_new ();
2975 tny_list_append(remove_headers, G_OBJECT(hdr));
2979 g_object_unref(traccount);
2981 g_object_unref(hdr);
2982 tny_iterator_next (headers_iter);
2984 g_object_unref(headers_iter);
2987 /* Get account and set it into mail_operation */
2988 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2989 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2990 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2992 if (!remove_headers)
2993 remove_headers = g_object_ref (headers);
2995 /* remove message from folder */
2996 modest_mail_operation_notify_start (self);
2997 tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb,
2998 NULL, g_object_ref (self));
3002 g_object_unref (remove_headers);
3004 g_object_unref (header);
3006 g_object_unref (folder);
3010 notify_progress_of_multiple_messages (ModestMailOperation *self,
3012 gint *last_total_bytes,
3013 gint *sum_total_bytes,
3015 gboolean increment_done)
3017 ModestMailOperationPrivate *priv;
3018 ModestMailOperationState *state;
3019 gboolean is_num_bytes = FALSE;
3021 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3023 /* We know that tinymail sends us information about
3024 * transferred bytes with this particular message
3026 if (status->message)
3027 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
3029 state = modest_mail_operation_clone_state (self);
3030 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
3031 /* We know that we're in a different message when the
3032 total number of bytes to transfer is different. Of
3033 course it could fail if we're transferring messages
3034 of the same size, but this is a workarround */
3035 if (status->of_total != *last_total_bytes) {
3036 /* We need to increment the done when there is
3037 no information about each individual
3038 message, we need to do this in message
3039 transfers, and we don't do it for getting
3043 *sum_total_bytes += *last_total_bytes;
3044 *last_total_bytes = status->of_total;
3046 state->bytes_done += status->position + *sum_total_bytes;
3047 state->bytes_total = total_bytes;
3049 /* Notify the status change. Only notify about changes
3050 referred to bytes */
3051 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3055 g_slice_free (ModestMailOperationState, state);
3059 transfer_msgs_status_cb (GObject *obj,
3063 XFerMsgsAsyncHelper *helper;
3065 g_return_if_fail (status != NULL);
3067 /* Show only the status information we want */
3068 if (status->code != TNY_FOLDER_STATUS_CODE_XFER_MSGS)
3071 helper = (XFerMsgsAsyncHelper *) user_data;
3072 g_return_if_fail (helper != NULL);
3074 /* Notify progress */
3075 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
3076 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
3080 transfer_msgs_sync_folder_cb (TnyFolder *self,
3085 XFerMsgsAsyncHelper *helper;
3086 /* We don't care here about the results of the
3088 helper = (XFerMsgsAsyncHelper *) user_data;
3090 /* Notify about operation end */
3091 modest_mail_operation_notify_end (helper->mail_op);
3093 /* If user defined callback function was defined, call it */
3094 if (helper->user_callback)
3095 helper->user_callback (helper->mail_op, helper->user_data);
3098 if (helper->more_msgs)
3099 g_object_unref (helper->more_msgs);
3100 if (helper->headers)
3101 g_object_unref (helper->headers);
3102 if (helper->dest_folder)
3103 g_object_unref (helper->dest_folder);
3104 if (helper->mail_op)
3105 g_object_unref (helper->mail_op);
3106 g_slice_free (XFerMsgsAsyncHelper, helper);
3110 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
3112 XFerMsgsAsyncHelper *helper;
3113 ModestMailOperation *self;
3114 ModestMailOperationPrivate *priv;
3115 gboolean finished = TRUE;
3117 helper = (XFerMsgsAsyncHelper *) user_data;
3118 self = helper->mail_op;
3120 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3123 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3125 priv->error = g_error_copy (err);
3127 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3128 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
3129 if (helper->more_msgs) {
3130 /* We'll transfer the next message in the list */
3131 tny_iterator_next (helper->more_msgs);
3132 if (!tny_iterator_is_done (helper->more_msgs)) {
3133 GObject *next_header;
3134 g_object_unref (helper->headers);
3135 helper->headers = tny_simple_list_new ();
3136 next_header = tny_iterator_get_current (helper->more_msgs);
3137 tny_list_append (helper->headers, next_header);
3138 g_object_unref (next_header);
3144 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3149 /* Synchronize the source folder contents. This should
3150 be done by tinymail but the camel_folder_sync it's
3151 actually disabled in transfer_msgs_thread_clean
3152 because it's supposed to cause hangs */
3153 tny_folder_sync_async (folder, helper->delete,
3154 transfer_msgs_sync_folder_cb,
3157 /* Transfer more messages */
3158 tny_folder_transfer_msgs_async (folder,
3160 helper->dest_folder,
3163 transfer_msgs_status_cb,
3168 /* Computes the size of the messages the headers in the list belongs
3169 to. If num_elements is different from 0 then it only takes into
3170 account the first num_elements for the calculation */
3172 compute_message_list_size (TnyList *headers,
3176 guint size = 0, element = 0;
3178 /* If num_elements is not valid then take all into account */
3179 if ((num_elements <= 0) || (num_elements > tny_list_get_length (headers)))
3180 num_elements = tny_list_get_length (headers);
3182 iter = tny_list_create_iterator (headers);
3183 while (!tny_iterator_is_done (iter) && element < num_elements) {
3184 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
3185 size += tny_header_get_message_size (header);
3186 g_object_unref (header);
3187 tny_iterator_next (iter);
3190 g_object_unref (iter);
3196 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
3199 gboolean delete_original,
3200 XferMsgsAsyncUserCallback user_callback,
3203 ModestMailOperationPrivate *priv = NULL;
3204 TnyIterator *iter = NULL;
3205 TnyFolder *src_folder = NULL;
3206 XFerMsgsAsyncHelper *helper = NULL;
3207 TnyHeader *header = NULL;
3208 ModestTnyFolderRules rules = 0;
3209 TnyAccount *dst_account = NULL;
3210 gboolean leave_on_server;
3211 ModestMailOperationState *state;
3212 ModestProtocolRegistry *protocol_registry;
3213 ModestProtocolType account_protocol;
3215 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
3216 g_return_if_fail (headers && TNY_IS_LIST (headers));
3217 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
3219 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3220 protocol_registry = modest_runtime_get_protocol_registry ();
3222 priv->total = tny_list_get_length (headers);
3224 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3225 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3227 /* Apply folder rules */
3228 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
3229 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3230 /* Set status failed and set an error */
3231 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3232 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3233 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
3234 _CS("ckct_ib_unable_to_paste_here"));
3235 /* Notify the queue */
3236 modest_mail_operation_notify_end (self);
3240 /* Get source folder */
3241 iter = tny_list_create_iterator (headers);
3242 header = TNY_HEADER (tny_iterator_get_current (iter));
3244 src_folder = tny_header_get_folder (header);
3245 g_object_unref (header);
3247 g_object_unref (iter);
3249 if (src_folder == NULL) {
3250 /* Notify the queue */
3251 modest_mail_operation_notify_end (self);
3253 g_warning ("%s: cannot find folder from header", __FUNCTION__);
3258 /* Check folder source and destination */
3259 if (src_folder == folder) {
3260 /* Set status failed and set an error */
3261 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3262 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3263 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
3264 _("mail_in_ui_folder_copy_target_error"));
3266 /* Notify the queue */
3267 modest_mail_operation_notify_end (self);
3270 g_object_unref (src_folder);
3274 /* Create the helper */
3275 helper = g_slice_new0 (XFerMsgsAsyncHelper);
3276 helper->mail_op = g_object_ref(self);
3277 helper->dest_folder = g_object_ref(folder);
3278 helper->user_callback = user_callback;
3279 helper->user_data = user_data;
3280 helper->last_total_bytes = 0;
3281 helper->sum_total_bytes = 0;
3282 helper->total_bytes = compute_message_list_size (headers, 0);
3284 /* Get account and set it into mail_operation */
3285 priv->account = modest_tny_folder_get_account (src_folder);
3286 dst_account = modest_tny_folder_get_account (folder);
3288 if (priv->account == dst_account) {
3289 /* Transfer all messages at once using the fast
3290 * method. Note that depending on the server this
3291 * might not be that fast, and might not be
3292 * user-cancellable either */
3293 helper->headers = g_object_ref (headers);
3294 helper->more_msgs = NULL;
3296 /* Transfer messages one by one so the user can cancel
3299 helper->headers = tny_simple_list_new ();
3300 helper->more_msgs = tny_list_create_iterator (headers);
3301 hdr = tny_iterator_get_current (helper->more_msgs);
3302 tny_list_append (helper->headers, hdr);
3303 g_object_unref (hdr);
3306 /* If leave_on_server is set to TRUE then don't use
3307 delete_original, we always pass FALSE. This is because
3308 otherwise tinymail will try to sync the source folder and
3309 this could cause an error if we're offline while
3310 transferring an already downloaded message from a POP
3312 account_protocol = modest_tny_account_get_protocol_type (priv->account);
3313 if (modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_protocol)) {
3314 const gchar *account_name;
3316 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
3317 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
3320 leave_on_server = FALSE;
3323 /* Do not delete messages if leave on server is TRUE */
3324 helper->delete = (leave_on_server) ? FALSE : delete_original;
3326 modest_mail_operation_notify_start (self);
3328 /* Start notifying progress */
3329 state = modest_mail_operation_clone_state (self);
3332 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3333 g_slice_free (ModestMailOperationState, state);
3335 tny_folder_transfer_msgs_async (src_folder,
3340 transfer_msgs_status_cb,
3342 g_object_unref (src_folder);
3343 g_object_unref (dst_account);
3348 on_refresh_folder (TnyFolder *folder,
3353 RefreshAsyncHelper *helper = NULL;
3354 ModestMailOperation *self = NULL;
3355 ModestMailOperationPrivate *priv = NULL;
3357 helper = (RefreshAsyncHelper *) user_data;
3358 self = helper->mail_op;
3359 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3361 g_return_if_fail(priv!=NULL);
3364 priv->error = g_error_copy (error);
3365 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3370 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3371 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3372 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
3373 _("Error trying to refresh the contents of %s"),
3374 tny_folder_get_name (folder));
3378 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3381 /* Call user defined callback, if it exists */
3382 if (helper->user_callback) {
3384 /* This is not a GDK lock because we are a Tinymail callback and
3385 * Tinymail already acquires the Gdk lock */
3386 helper->user_callback (self, folder, helper->user_data);
3390 g_slice_free (RefreshAsyncHelper, helper);
3392 /* Notify about operation end */
3393 modest_mail_operation_notify_end (self);
3394 g_object_unref(self);
3398 on_refresh_folder_status_update (GObject *obj,
3402 RefreshAsyncHelper *helper = NULL;
3403 ModestMailOperation *self = NULL;
3404 ModestMailOperationPrivate *priv = NULL;
3405 ModestMailOperationState *state;
3407 g_return_if_fail (user_data != NULL);
3408 g_return_if_fail (status != NULL);
3410 /* Show only the status information we want */
3411 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
3414 helper = (RefreshAsyncHelper *) user_data;
3415 self = helper->mail_op;
3416 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
3418 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3420 priv->done = status->position;
3421 priv->total = status->of_total;
3423 state = modest_mail_operation_clone_state (self);
3425 /* This is not a GDK lock because we are a Tinymail callback and
3426 * Tinymail already acquires the Gdk lock */
3427 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3429 g_slice_free (ModestMailOperationState, state);
3433 modest_mail_operation_refresh_folder (ModestMailOperation *self,
3435 RefreshAsyncUserCallback user_callback,
3438 ModestMailOperationPrivate *priv = NULL;
3439 RefreshAsyncHelper *helper = NULL;
3441 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3443 /* Check memory low */
3444 if (_check_memory_low (self)) {
3446 user_callback (self, folder, user_data);
3447 /* Notify about operation end */
3448 modest_mail_operation_notify_end (self);
3452 /* Get account and set it into mail_operation */
3453 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3454 priv->account = modest_tny_folder_get_account (folder);
3455 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3457 /* Create the helper */
3458 helper = g_slice_new0 (RefreshAsyncHelper);
3459 helper->mail_op = g_object_ref(self);
3460 helper->user_callback = user_callback;
3461 helper->user_data = user_data;
3463 modest_mail_operation_notify_start (self);
3465 /* notify that the operation was started */
3466 ModestMailOperationState *state;
3467 state = modest_mail_operation_clone_state (self);
3470 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3472 g_slice_free (ModestMailOperationState, state);
3474 tny_folder_refresh_async (folder,
3476 on_refresh_folder_status_update,
3481 run_queue_notify_and_destroy (RunQueueHelper *helper,
3482 ModestMailOperationStatus status)
3484 ModestMailOperationPrivate *priv;
3487 if (helper->error_handler &&
3488 g_signal_handler_is_connected (helper->queue, helper->error_handler))
3489 g_signal_handler_disconnect (helper->queue, helper->error_handler);
3490 if (helper->start_handler &&
3491 g_signal_handler_is_connected (helper->queue, helper->start_handler))
3492 g_signal_handler_disconnect (helper->queue, helper->start_handler);
3493 if (helper->stop_handler &&
3494 g_signal_handler_is_connected (helper->queue, helper->stop_handler))
3495 g_signal_handler_disconnect (helper->queue, helper->stop_handler);
3498 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
3499 priv->status = status;
3502 modest_mail_operation_notify_end (helper->self);
3505 g_object_unref (helper->queue);
3506 g_object_unref (helper->self);
3507 g_slice_free (RunQueueHelper, helper);
3511 run_queue_stop (ModestTnySendQueue *queue,
3514 RunQueueHelper *helper;
3516 g_debug ("%s sending queue stopped", __FUNCTION__);
3518 helper = (RunQueueHelper *) user_data;
3519 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
3523 modest_mail_operation_run_queue (ModestMailOperation *self,
3524 ModestTnySendQueue *queue)
3526 ModestMailOperationPrivate *priv;
3527 RunQueueHelper *helper;
3529 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3530 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3531 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3533 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3534 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3535 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
3537 /* Create the helper */
3538 helper = g_slice_new0 (RunQueueHelper);
3539 helper->queue = g_object_ref (queue);
3540 helper->self = g_object_ref (self);
3541 helper->stop_handler = g_signal_connect (queue, "queue-stop",
3542 G_CALLBACK (run_queue_stop),
3545 /* Notify operation has started */
3546 modest_mail_operation_notify_start (self);
3547 g_debug ("%s, run queue started", __FUNCTION__);
3551 queue_wakeup_callback (ModestTnySendQueue *queue,
3556 ModestMailOperation *mail_op;
3557 ModestMailOperationPrivate *priv;
3559 mail_op = (ModestMailOperation *) userdata;
3560 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3562 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3563 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (queue));
3566 modest_mail_operation_notify_end (mail_op);
3567 g_object_unref (mail_op);
3571 modest_mail_operation_queue_wakeup (ModestMailOperation *self,
3572 ModestTnySendQueue *queue)
3574 ModestMailOperationPrivate *priv;
3576 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3577 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3578 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3580 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3581 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3582 priv->op_type = MODEST_MAIL_OPERATION_TYPE_QUEUE_WAKEUP;
3584 g_object_ref (self);
3586 modest_tny_send_queue_wakeup (queue, queue_wakeup_callback, self);
3587 modest_mail_operation_notify_start (self);
3591 shutdown_callback (ModestTnyAccountStore *account_store, gpointer userdata)
3593 ModestMailOperation *self = (ModestMailOperation *) userdata;
3594 ModestMailOperationPrivate *priv;
3596 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3597 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3598 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3600 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3602 modest_mail_operation_notify_end (self);
3603 g_object_unref (self);
3607 modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore *account_store)
3609 ModestMailOperationPrivate *priv;
3611 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3612 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3613 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3615 modest_mail_operation_queue_set_running_shutdown (modest_runtime_get_mail_operation_queue ());
3617 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3618 priv->account = NULL;
3619 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SHUTDOWN;
3621 modest_mail_operation_notify_start (self);
3622 g_object_ref (self);
3623 modest_tny_account_store_shutdown (account_store, shutdown_callback, self);
3627 sync_folder_finish_callback (TnyFolder *self,
3633 ModestMailOperation *mail_op;
3634 ModestMailOperationPrivate *priv;
3636 mail_op = (ModestMailOperation *) user_data;
3637 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3639 /* If canceled by the user, ignore the error given by Tinymail */
3641 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3643 /* If the operation was a sync then the status is
3644 failed, but if it's part of another operation then
3645 just set it as finished with errors */
3646 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
3647 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3649 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
3650 priv->error = g_error_copy ((const GError *) err);
3651 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
3653 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3656 modest_mail_operation_notify_end (mail_op);
3657 g_object_unref (mail_op);
3661 modest_mail_operation_sync_folder (ModestMailOperation *self,
3662 TnyFolder *folder, gboolean expunge)
3664 ModestMailOperationPrivate *priv;
3666 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3667 g_return_if_fail (TNY_IS_FOLDER (folder));
3668 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3670 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3671 priv->account = modest_tny_folder_get_account (folder);
3672 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3674 modest_mail_operation_notify_start (self);
3675 g_object_ref (self);
3676 tny_folder_sync_async (folder, expunge,
3677 (TnyFolderCallback) sync_folder_finish_callback,
3682 modest_mail_operation_notify_start (ModestMailOperation *self)
3684 ModestMailOperationPrivate *priv = NULL;
3686 g_return_if_fail (self);
3688 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3690 /* Ensure that all the fields are filled correctly */
3691 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3693 /* Notify the observers about the mail operation. We do not
3694 wrapp this emission because we assume that this function is
3695 always called from within the main lock */
3696 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3701 * It's used by the mail operation queue to notify the observers
3702 * attached to that signal that the operation finished. We need to use
3703 * that because tinymail does not give us the progress of a given
3704 * operation when it finishes (it directly calls the operation
3708 modest_mail_operation_notify_end (ModestMailOperation *self)
3710 ModestMailOperationPrivate *priv = NULL;
3712 g_return_if_fail (self);
3714 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3716 /* Notify the observers about the mail operation end. We do
3717 not wrapp this emission because we assume that this
3718 function is always called from within the main lock */
3719 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3721 /* Remove the error user data */
3722 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3723 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3727 modest_mail_operation_get_account (ModestMailOperation *self)
3729 ModestMailOperationPrivate *priv = NULL;
3731 g_return_val_if_fail (self, NULL);
3733 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3735 return (priv->account) ? g_object_ref (priv->account) : NULL;
3739 modest_mail_operation_noop (ModestMailOperation *self)
3741 ModestMailOperationPrivate *priv = NULL;
3743 g_return_if_fail (self);
3745 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3746 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3747 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3751 /* This mail operation does nothing actually */
3752 modest_mail_operation_notify_start (self);
3753 modest_mail_operation_notify_end (self);
3758 modest_mail_operation_to_string (ModestMailOperation *self)
3760 const gchar *type, *status, *account_id;
3761 ModestMailOperationPrivate *priv = NULL;
3763 g_return_val_if_fail (self, NULL);
3765 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3767 /* new operations don't have anything interesting */
3768 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3769 return g_strdup_printf ("%p <new operation>", self);
3771 switch (priv->op_type) {
3772 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3773 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3774 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3775 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3776 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3777 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3778 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3779 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3780 default: type = "UNEXPECTED"; break;
3783 switch (priv->status) {
3784 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3785 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3786 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3787 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3788 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3789 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3790 default: status= "UNEXPECTED"; break;
3793 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3795 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3796 priv->done, priv->total,
3797 priv->error && priv->error->message ? priv->error->message : "");
3801 * Once the mail operations were objects this will be no longer
3802 * needed. I don't like it, but we need it for the moment
3805 _check_memory_low (ModestMailOperation *mail_op)
3807 if (modest_platform_check_memory_low (NULL, FALSE)) {
3808 ModestMailOperationPrivate *priv;
3810 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3811 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3812 g_set_error (&(priv->error),
3813 MODEST_MAIL_OPERATION_ERROR,
3814 MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY,
3815 "Not enough memory to complete the operation");