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>
69 #include "modest-account-protocol.h"
74 * Remove all these #ifdef stuff when the tinymail's idle calls become
77 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
79 /* 'private'/'protected' functions */
80 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
81 static void modest_mail_operation_init (ModestMailOperation *obj);
82 static void modest_mail_operation_finalize (GObject *obj);
84 static void get_msg_async_cb (TnyFolder *folder,
90 static void get_msg_status_cb (GObject *obj,
94 static void modest_mail_operation_notify_start (ModestMailOperation *self);
95 static void modest_mail_operation_notify_end (ModestMailOperation *self);
97 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
99 gint *last_total_bytes,
100 gint *sum_total_bytes,
102 gboolean increment_done);
104 static guint compute_message_list_size (TnyList *headers, guint num_elements);
106 static int compare_headers_by_date (gconstpointer a,
109 static void sync_folder_finish_callback (TnyFolder *self,
114 static gboolean _check_memory_low (ModestMailOperation *mail_op);
118 ModestTnySendQueue *queue;
119 ModestMailOperation *self;
125 static void run_queue_notify_and_destroy (RunQueueHelper *helper,
126 ModestMailOperationStatus status);
128 /* Helpers for the update account operation (send & receive)*/
131 ModestMailOperation *mail_op;
133 UpdateAccountCallback callback;
138 TnyFolderObserver *inbox_observer;
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 ModestMailOperation *mailop;
1144 SaveToDraftstCallback callback;
1146 } FinishSaveRemoteDraftInfo;
1149 finish_save_remote_draft (ModestAccountProtocol *protocol,
1151 const gchar *account_id,
1152 TnyMsg *new_remote_msg,
1157 FinishSaveRemoteDraftInfo *info = (FinishSaveRemoteDraftInfo *) userdata;
1158 ModestMailOperationPrivate *priv = NULL;
1160 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1162 if (!priv->error && err != NULL) {
1163 /* Priority for errors in save to local stage */
1164 priv->error = g_error_copy (err);
1165 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1169 info->callback (info->mailop, info->msg, info->userdata);
1172 g_object_unref (info->msg);
1174 modest_mail_operation_notify_end (info->mailop);
1175 g_object_unref (info->mailop);
1177 g_slice_free (FinishSaveRemoteDraftInfo, info);
1182 TnyTransportAccount *transport_account;
1184 SaveToDraftstCallback callback;
1188 ModestMailOperation *mailop;
1189 } SaveToDraftsAddMsgInfo;
1192 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1197 ModestMailOperationPrivate *priv = NULL;
1198 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1199 GError *io_error = NULL;
1200 gboolean callback_called = FALSE;
1202 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1204 if (priv->error && priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1205 io_error = priv->error;
1209 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1210 g_error_free(priv->error);
1213 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1215 if ((!priv->error) && (info->draft_msg != NULL)) {
1216 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1217 TnyFolder *src_folder = tny_header_get_folder (header);
1219 g_debug ("--- REMOVE AND SYNC");
1220 /* Remove the old draft */
1221 tny_folder_remove_msg (src_folder, header, NULL);
1223 /* Synchronize to expunge and to update the msg counts */
1224 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1225 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1226 g_debug ("--- REMOVED - SYNCED");
1228 g_object_unref (G_OBJECT(header));
1229 g_object_unref (G_OBJECT(src_folder));
1233 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1235 g_error_free (io_error);
1238 } else if (io_error) {
1239 priv->error = io_error;
1240 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
1242 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1245 if (info->transport_account) {
1246 ModestProtocolType transport_protocol_type;
1247 ModestProtocol *transport_protocol;
1249 transport_protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (info->transport_account));
1251 transport_protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
1252 transport_protocol_type);
1253 if (transport_protocol && MODEST_IS_ACCOUNT_PROTOCOL (transport_protocol)) {
1254 FinishSaveRemoteDraftInfo *srd_info = g_slice_new (FinishSaveRemoteDraftInfo);
1255 srd_info->mailop = info->mailop?g_object_ref (info->mailop):NULL;
1256 srd_info->msg = info->msg?g_object_ref (info->msg):NULL;
1257 srd_info->callback = info->callback;
1258 srd_info->userdata = info->user_data;
1259 modest_account_protocol_save_remote_draft (MODEST_ACCOUNT_PROTOCOL (transport_protocol),
1260 tny_account_get_id (TNY_ACCOUNT (info->transport_account)),
1261 info->msg, info->draft_msg,
1262 finish_save_remote_draft,
1265 callback_called = TRUE;
1269 /* Call the user callback */
1270 if (!callback_called && info->callback)
1271 info->callback (info->mailop, info->msg, info->user_data);
1273 if (info->transport_account)
1274 g_object_unref (G_OBJECT(info->transport_account));
1275 if (info->draft_msg)
1276 g_object_unref (G_OBJECT (info->draft_msg));
1278 g_object_unref (G_OBJECT(info->drafts));
1280 g_object_unref (G_OBJECT (info->msg));
1282 if (!callback_called)
1283 modest_mail_operation_notify_end (info->mailop);
1285 g_object_unref(info->mailop);
1286 g_slice_free (SaveToDraftsAddMsgInfo, info);
1291 TnyTransportAccount *transport_account;
1293 SaveToDraftstCallback callback;
1298 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1302 TnyFolder *drafts = NULL;
1303 ModestMailOperationPrivate *priv = NULL;
1304 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1306 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1309 if (!(priv->error)) {
1310 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1311 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1312 "modest: failed to create a new msg\n");
1315 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1316 TNY_FOLDER_TYPE_DRAFTS);
1317 if (!drafts && !(priv->error)) {
1318 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1319 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1320 "modest: failed to create a new msg\n");
1324 if (!priv->error || priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1326 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1327 cb_info->transport_account = g_object_ref(info->transport_account);
1328 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1329 cb_info->callback = info->callback;
1330 cb_info->user_data = info->user_data;
1331 cb_info->drafts = g_object_ref(drafts);
1332 cb_info->msg = g_object_ref(msg);
1333 cb_info->mailop = g_object_ref(self);
1334 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1338 /* Call the user callback */
1339 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1341 info->callback (self, msg, info->user_data);
1342 modest_mail_operation_notify_end (self);
1346 g_object_unref (G_OBJECT(drafts));
1347 if (info->draft_msg)
1348 g_object_unref (G_OBJECT (info->draft_msg));
1349 if (info->transport_account)
1350 g_object_unref (G_OBJECT(info->transport_account));
1351 g_slice_free (SaveToDraftsInfo, info);
1355 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1356 TnyTransportAccount *transport_account,
1358 const gchar *from, const gchar *to,
1359 const gchar *cc, const gchar *bcc,
1360 const gchar *subject, const gchar *plain_body,
1361 const gchar *html_body,
1362 const GList *attachments_list,
1363 const GList *images_list,
1364 TnyHeaderFlags priority_flags,
1365 const gchar *references,
1366 const gchar *in_reply_to,
1367 SaveToDraftstCallback callback,
1370 ModestMailOperationPrivate *priv = NULL;
1371 SaveToDraftsInfo *info = NULL;
1373 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1374 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1376 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1378 /* Get account and set it into mail_operation */
1379 priv->account = g_object_ref (transport_account);
1380 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1382 info = g_slice_new0 (SaveToDraftsInfo);
1383 info->transport_account = g_object_ref (transport_account);
1384 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1385 info->callback = callback;
1386 info->user_data = user_data;
1388 g_debug ("--- CREATE MESSAGE");
1389 modest_mail_operation_notify_start (self);
1390 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1391 attachments_list, images_list, priority_flags,
1392 references, in_reply_to,
1393 modest_mail_operation_save_to_drafts_cb, info);
1398 ModestMailOperation *mail_op;
1399 TnyMimePart *mime_part;
1401 GetMimePartSizeCallback callback;
1403 } GetMimePartSizeInfo;
1405 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1406 /* We use this folder observer to track the headers that have been
1407 * added to a folder */
1410 TnyList *new_headers;
1411 } InternalFolderObserver;
1414 GObjectClass parent;
1415 } InternalFolderObserverClass;
1417 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1419 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1420 internal_folder_observer,
1422 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1426 foreach_add_item (gpointer header, gpointer user_data)
1428 tny_list_append (TNY_LIST (user_data), G_OBJECT (header));
1431 /* This is the method that looks for new messages in a folder */
1433 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1435 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1437 TnyFolderChangeChanged changed;
1439 changed = tny_folder_change_get_changed (change);
1441 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1444 /* Get added headers */
1445 list = tny_simple_list_new ();
1446 tny_folder_change_get_added_headers (change, list);
1448 /* Add them to the folder observer */
1449 tny_list_foreach (list, foreach_add_item,
1450 derived->new_headers);
1452 g_object_unref (G_OBJECT (list));
1457 internal_folder_observer_init (InternalFolderObserver *self)
1459 self->new_headers = tny_simple_list_new ();
1462 internal_folder_observer_finalize (GObject *object)
1464 InternalFolderObserver *self;
1466 self = (InternalFolderObserver *) object;
1467 g_object_unref (self->new_headers);
1469 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1472 tny_folder_observer_init (TnyFolderObserverIface *iface)
1474 iface->update = internal_folder_observer_update;
1477 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1479 GObjectClass *object_class;
1481 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1482 object_class = (GObjectClass*) klass;
1483 object_class->finalize = internal_folder_observer_finalize;
1487 destroy_update_account_info (UpdateAccountInfo *info)
1489 g_free (info->account_name);
1490 g_object_unref (info->folders);
1491 g_object_unref (info->mail_op);
1492 g_slice_free (UpdateAccountInfo, info);
1497 update_account_send_mail (UpdateAccountInfo *info)
1499 TnyTransportAccount *transport_account = NULL;
1500 ModestTnyAccountStore *account_store;
1502 account_store = modest_runtime_get_account_store ();
1504 /* We don't try to send messages while sending mails is blocked */
1505 if (modest_tny_account_store_is_send_mail_blocked (account_store))
1508 /* Get the transport account */
1509 transport_account = (TnyTransportAccount *)
1510 modest_tny_account_store_get_server_account (account_store, info->account_name,
1511 TNY_ACCOUNT_TYPE_TRANSPORT);
1513 if (transport_account) {
1514 ModestTnySendQueue *send_queue;
1518 send_queue = modest_runtime_get_send_queue (transport_account, TRUE);
1519 g_object_unref (transport_account);
1521 if (TNY_IS_SEND_QUEUE (send_queue)) {
1522 /* Get outbox folder */
1523 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1524 if (outbox) { /* this could fail in some cases */
1525 num_messages = tny_folder_get_all_count (outbox);
1526 g_object_unref (outbox);
1528 g_warning ("%s: could not get outbox", __FUNCTION__);
1532 if (num_messages != 0) {
1533 ModestMailOperation *mail_op;
1534 /* Reenable suspended items */
1535 mail_op = modest_mail_operation_new (NULL);
1536 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1538 modest_mail_operation_queue_wakeup (mail_op, MODEST_TNY_SEND_QUEUE (send_queue));
1541 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1549 update_account_get_msg_async_cb (TnyFolder *folder,
1555 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1556 ModestMailOperationPrivate *priv;
1558 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (msg_info->mail_op);
1561 if (TNY_IS_MSG (msg)) {
1562 TnyHeader *header = tny_msg_get_header (msg);
1565 ModestMailOperationState *state;
1566 state = modest_mail_operation_clone_state (msg_info->mail_op);
1567 msg_info->sum_total_bytes += tny_header_get_message_size (header);
1568 state->bytes_done = msg_info->sum_total_bytes;
1569 state->bytes_total = msg_info->total_bytes;
1571 /* Notify the status change. Only notify about changes
1572 referred to bytes */
1573 g_signal_emit (G_OBJECT (msg_info->mail_op),
1574 signals[PROGRESS_CHANGED_SIGNAL],
1577 g_object_unref (header);
1578 g_slice_free (ModestMailOperationState, state);
1582 if (priv->done == priv->total) {
1583 TnyList *new_headers;
1584 UpdateAccountInfo *info;
1586 /* After getting all the messages send the ones in the
1588 info = (UpdateAccountInfo *) msg_info->user_data;
1589 update_account_send_mail (info);
1591 /* Check if the operation was a success */
1593 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1595 /* Call the user callback and free */
1596 new_headers = tny_iterator_get_list (msg_info->more_msgs);
1597 update_account_notify_user_and_free (info, new_headers);
1599 /* Delete the helper */
1600 g_object_unref (msg_info->more_msgs);
1601 g_object_unref (msg_info->mail_op);
1602 g_slice_free (GetMsgInfo, msg_info);
1607 update_account_notify_user_and_free (UpdateAccountInfo *info,
1608 TnyList *new_headers)
1610 /* Set the account back to not busy */
1611 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (),
1612 info->account_name, FALSE);
1616 info->callback (info->mail_op, new_headers, info->user_data);
1618 /* Mail operation end */
1619 modest_mail_operation_notify_end (info->mail_op);
1623 g_object_unref (new_headers);
1624 destroy_update_account_info (info);
1628 inbox_refreshed_cb (TnyFolder *inbox,
1633 UpdateAccountInfo *info;
1634 ModestMailOperationPrivate *priv;
1635 TnyIterator *new_headers_iter;
1636 GPtrArray *new_headers_array = NULL;
1637 gint max_size, retrieve_limit, i;
1638 ModestAccountMgr *mgr;
1639 ModestAccountRetrieveType retrieve_type;
1640 TnyList *new_headers = NULL;
1641 gboolean headers_only;
1642 time_t time_to_store;
1644 info = (UpdateAccountInfo *) user_data;
1645 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1646 mgr = modest_runtime_get_account_mgr ();
1648 if (canceled || err) {
1649 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1651 priv->error = g_error_copy (err);
1653 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1654 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1658 tny_folder_remove_observer (inbox, info->inbox_observer);
1659 g_object_unref (info->inbox_observer);
1660 info->inbox_observer = NULL;
1662 /* Notify the user about the error and then exit */
1663 update_account_notify_user_and_free (info, NULL);
1668 /* Try to send anyway */
1672 /* Set the last updated as the current time */
1673 #ifdef MODEST_USE_LIBTIME
1675 time_get_utc (&utc_tm);
1676 time_to_store = time_mktime (&utc_tm, "GMT");
1678 time_to_store = time (NULL);
1680 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
1682 /* Get the message max size */
1683 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1684 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1686 max_size = G_MAXINT;
1688 max_size = max_size * KB;
1690 /* Create the new headers array. We need it to sort the
1691 new headers by date */
1692 new_headers_array = g_ptr_array_new ();
1693 if (info->inbox_observer) {
1694 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1695 while (!tny_iterator_is_done (new_headers_iter)) {
1696 TnyHeader *header = NULL;
1698 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1699 /* Apply per-message size limits */
1700 if (tny_header_get_message_size (header) < max_size)
1701 g_ptr_array_add (new_headers_array, g_object_ref (header));
1703 g_object_unref (header);
1704 tny_iterator_next (new_headers_iter);
1706 g_object_unref (new_headers_iter);
1708 tny_folder_remove_observer (inbox, info->inbox_observer);
1709 g_object_unref (info->inbox_observer);
1710 info->inbox_observer = NULL;
1713 if (new_headers_array->len == 0) {
1714 g_ptr_array_free (new_headers_array, FALSE);
1718 /* Get per-account message amount retrieval limit */
1719 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1720 if (retrieve_limit == 0)
1721 retrieve_limit = G_MAXINT;
1723 /* Get per-account retrieval type */
1724 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1725 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1728 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1730 /* Copy the headers to a list and free the array */
1731 new_headers = tny_simple_list_new ();
1732 for (i=0; i < new_headers_array->len; i++) {
1733 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1734 /* We want the first element to be the most recent
1735 one, that's why we reverse the list */
1736 tny_list_prepend (new_headers, G_OBJECT (header));
1738 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1739 g_ptr_array_free (new_headers_array, FALSE);
1741 if (!headers_only && (tny_list_get_length (new_headers) > 0)) {
1744 GetMsgInfo *msg_info;
1747 priv->total = MIN (tny_list_get_length (new_headers), retrieve_limit);
1749 iter = tny_list_create_iterator (new_headers);
1751 /* Create the message info */
1752 msg_info = g_slice_new0 (GetMsgInfo);
1753 msg_info->mail_op = g_object_ref (info->mail_op);
1754 msg_info->total_bytes = compute_message_list_size (new_headers, priv->total);
1755 msg_info->more_msgs = g_object_ref (iter);
1756 msg_info->user_data = info;
1758 while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) {
1759 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1760 TnyFolder *folder = tny_header_get_folder (header);
1762 /* Get message in an async way */
1763 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1766 g_object_unref (folder);
1767 g_object_unref (header);
1770 tny_iterator_next (iter);
1772 g_object_unref (iter);
1773 g_object_unref (new_headers);
1775 /* The mail operation will finish when the last
1776 message is retrieved */
1780 /* If we don't have to retrieve the new messages then
1782 update_account_send_mail (info);
1784 /* Check if the operation was a success */
1786 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1788 /* Call the user callback and free */
1789 update_account_notify_user_and_free (info, new_headers);
1793 inbox_refresh_status_update (GObject *obj,
1797 UpdateAccountInfo *info = NULL;
1798 ModestMailOperation *self = NULL;
1799 ModestMailOperationPrivate *priv = NULL;
1800 ModestMailOperationState *state;
1802 g_return_if_fail (user_data != NULL);
1803 g_return_if_fail (status != NULL);
1805 /* Show only the status information we want */
1806 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
1809 info = (UpdateAccountInfo *) user_data;
1810 self = info->mail_op;
1811 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1813 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1815 priv->done = status->position;
1816 priv->total = status->of_total;
1818 state = modest_mail_operation_clone_state (self);
1820 /* This is not a GDK lock because we are a Tinymail callback and
1821 * Tinymail already acquires the Gdk lock */
1822 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1824 g_slice_free (ModestMailOperationState, state);
1828 recurse_folders_async_cb (TnyFolderStore *folder_store,
1834 UpdateAccountInfo *info;
1835 ModestMailOperationPrivate *priv;
1837 info = (UpdateAccountInfo *) user_data;
1838 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1840 if (err || canceled) {
1841 /* If the error was previosly set by another callback
1842 don't set it again */
1844 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1846 priv->error = g_error_copy (err);
1848 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1849 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1853 /* We're not getting INBOX children if we don't want to poke all */
1854 TnyIterator *iter = tny_list_create_iterator (list);
1855 while (!tny_iterator_is_done (iter)) {
1856 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1858 /* Add to the list of all folders */
1859 tny_list_append (info->folders, (GObject *) folder);
1861 if (info->poke_all) {
1862 TnyList *folders = tny_simple_list_new ();
1863 /* Add pending call */
1864 info->pending_calls++;
1866 tny_folder_store_get_folders_async (folder, folders, NULL, FALSE,
1867 recurse_folders_async_cb,
1869 g_object_unref (folders);
1872 g_object_unref (G_OBJECT (folder));
1874 tny_iterator_next (iter);
1876 g_object_unref (G_OBJECT (iter));
1879 /* Remove my own pending call */
1880 info->pending_calls--;
1882 /* This means that we have all the folders */
1883 if (info->pending_calls == 0) {
1884 TnyIterator *iter_all_folders;
1885 TnyFolder *inbox = NULL;
1887 /* If there was any error do not continue */
1889 update_account_notify_user_and_free (info, NULL);
1893 iter_all_folders = tny_list_create_iterator (info->folders);
1895 /* Do a poke status over all folders */
1896 while (!tny_iterator_is_done (iter_all_folders) &&
1897 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1898 TnyFolder *folder = NULL;
1900 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1902 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1903 /* Get a reference to the INBOX */
1904 inbox = g_object_ref (folder);
1906 /* Issue a poke status over the folder */
1908 tny_folder_poke_status (folder);
1911 /* Free and go to next */
1912 g_object_unref (folder);
1913 tny_iterator_next (iter_all_folders);
1915 g_object_unref (iter_all_folders);
1917 /* Refresh the INBOX */
1919 /* Refresh the folder. Our observer receives
1920 * the new emails during folder refreshes, so
1921 * we can use observer->new_headers
1923 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1924 tny_folder_add_observer (inbox, info->inbox_observer);
1926 /* Refresh the INBOX */
1927 tny_folder_refresh_async (inbox, inbox_refreshed_cb, inbox_refresh_status_update, info);
1928 g_object_unref (inbox);
1930 /* We could not perform the inbox refresh but
1931 we'll try to send mails anyway */
1932 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1938 modest_mail_operation_update_account (ModestMailOperation *self,
1939 const gchar *account_name,
1941 gboolean interactive,
1942 UpdateAccountCallback callback,
1945 UpdateAccountInfo *info = NULL;
1946 ModestMailOperationPrivate *priv = NULL;
1947 ModestTnyAccountStore *account_store = NULL;
1949 ModestMailOperationState *state;
1951 /* Init mail operation */
1952 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1955 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1956 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1958 /* Get the store account */
1959 account_store = modest_runtime_get_account_store ();
1961 modest_tny_account_store_get_server_account (account_store,
1963 TNY_ACCOUNT_TYPE_STORE);
1965 /* The above function could return NULL */
1966 if (!priv->account) {
1967 /* Check if the operation was a success */
1968 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1969 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1971 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1973 /* Call the user callback */
1975 callback (self, NULL, user_data);
1977 /* Notify about operation end */
1978 modest_mail_operation_notify_end (self);
1983 /* We have once seen priv->account getting finalized during this code,
1984 * therefore adding a reference (bug #82296) */
1986 g_object_ref (priv->account);
1988 /* Create the helper object */
1989 info = g_slice_new0 (UpdateAccountInfo);
1990 info->pending_calls = 1;
1991 info->folders = tny_simple_list_new ();
1992 info->mail_op = g_object_ref (self);
1993 info->poke_all = poke_all;
1994 info->interactive = interactive;
1995 info->account_name = g_strdup (account_name);
1996 info->callback = callback;
1997 info->user_data = user_data;
1999 /* Set account busy */
2000 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
2001 modest_mail_operation_notify_start (self);
2003 /* notify about the start of the operation */
2004 state = modest_mail_operation_clone_state (self);
2008 /* Start notifying progress */
2009 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2010 g_slice_free (ModestMailOperationState, state);
2012 /* Get all folders and continue in the callback */
2013 folders = tny_simple_list_new ();
2014 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
2015 folders, NULL, FALSE,
2016 recurse_folders_async_cb,
2018 g_object_unref (folders);
2020 g_object_unref (priv->account);
2025 * Used to notify the queue from the main
2026 * loop. We call it inside an idle call to achieve that
2029 idle_notify_queue (gpointer data)
2031 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
2033 gdk_threads_enter ();
2034 modest_mail_operation_notify_end (mail_op);
2035 gdk_threads_leave ();
2036 g_object_unref (mail_op);
2042 compare_headers_by_date (gconstpointer a,
2045 TnyHeader **header1, **header2;
2046 time_t sent1, sent2;
2048 header1 = (TnyHeader **) a;
2049 header2 = (TnyHeader **) b;
2051 sent1 = tny_header_get_date_sent (*header1);
2052 sent2 = tny_header_get_date_sent (*header2);
2054 /* We want the most recent ones (greater time_t) at the
2063 /* ******************************************************************* */
2064 /* ************************** STORE ACTIONS ************************* */
2065 /* ******************************************************************* */
2068 ModestMailOperation *mail_op;
2069 CreateFolderUserCallback callback;
2075 create_folder_cb (TnyFolderStore *parent_folder,
2077 TnyFolder *new_folder,
2081 ModestMailOperationPrivate *priv;
2082 CreateFolderInfo *info;
2084 info = (CreateFolderInfo *) user_data;
2085 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2087 if (canceled || err) {
2088 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2090 priv->error = g_error_copy (err);
2092 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2093 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2096 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2099 /* The user will unref the new_folder */
2101 info->callback (info->mail_op, parent_folder,
2102 new_folder, info->user_data);
2104 /* Notify about operation end */
2105 modest_mail_operation_notify_end (info->mail_op);
2108 g_object_unref (info->mail_op);
2109 g_slice_free (CreateFolderInfo, info);
2113 modest_mail_operation_create_folder (ModestMailOperation *self,
2114 TnyFolderStore *parent,
2116 CreateFolderUserCallback callback,
2119 ModestMailOperationPrivate *priv;
2121 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2122 g_return_if_fail (name);
2124 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2125 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2126 priv->account = (TNY_IS_ACCOUNT (parent)) ?
2127 g_object_ref (parent) :
2128 modest_tny_folder_get_account (TNY_FOLDER (parent));
2130 /* Check for already existing folder */
2131 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
2132 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2133 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2134 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2135 _CS("ckdg_ib_folder_already_exists"));
2139 if (TNY_IS_FOLDER (parent)) {
2140 /* Check folder rules */
2141 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2142 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2143 /* Set status failed and set an error */
2144 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2145 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2146 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2147 _("mail_in_ui_folder_create_error"));
2151 if (!priv->error && (!strcmp (name, " ") || strchr (name, '/'))) {
2152 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2153 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2154 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2155 _("mail_in_ui_folder_create_error"));
2159 CreateFolderInfo *info;
2161 info = g_slice_new0 (CreateFolderInfo);
2162 info->mail_op = g_object_ref (self);
2163 info->callback = callback;
2164 info->user_data = user_data;
2166 modest_mail_operation_notify_start (self);
2168 /* Create the folder */
2169 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
2172 /* Call the user callback anyway */
2174 callback (self, parent, NULL, user_data);
2175 /* Notify about operation end */
2176 modest_mail_operation_notify_end (self);
2181 modest_mail_operation_remove_folder (ModestMailOperation *self,
2183 gboolean remove_to_trash)
2185 ModestMailOperationPrivate *priv;
2186 ModestTnyFolderRules rules;
2188 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2189 g_return_if_fail (TNY_IS_FOLDER (folder));
2191 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2193 /* Check folder rules */
2194 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2195 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
2196 /* Set status failed and set an error */
2197 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2198 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2199 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2200 _("mail_in_ui_folder_delete_error"));
2204 /* Get the account */
2205 priv->account = modest_tny_folder_get_account (folder);
2206 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2208 /* Delete folder or move to trash */
2209 if (remove_to_trash) {
2210 TnyFolder *trash_folder = NULL;
2211 trash_folder = modest_tny_account_get_special_folder (priv->account,
2212 TNY_FOLDER_TYPE_TRASH);
2213 /* TODO: error_handling */
2215 modest_mail_operation_notify_start (self);
2216 modest_mail_operation_xfer_folder (self, folder,
2217 TNY_FOLDER_STORE (trash_folder),
2219 g_object_unref (trash_folder);
2221 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
2224 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
2226 modest_mail_operation_notify_start (self);
2227 tny_folder_store_remove_folder (parent, folder, &(priv->error));
2228 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
2231 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2233 g_object_unref (parent);
2235 g_warning ("%s: could not get parent folder", __FUNCTION__);
2239 /* Notify about operation end */
2240 modest_mail_operation_notify_end (self);
2244 transfer_folder_status_cb (GObject *obj,
2248 ModestMailOperation *self;
2249 ModestMailOperationPrivate *priv;
2250 ModestMailOperationState *state;
2251 XFerFolderAsyncHelper *helper;
2253 g_return_if_fail (status != NULL);
2255 /* Show only the status information we want */
2256 if (status->code != TNY_FOLDER_STATUS_CODE_COPY_FOLDER)
2259 helper = (XFerFolderAsyncHelper *) user_data;
2260 g_return_if_fail (helper != NULL);
2262 self = helper->mail_op;
2263 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2265 priv->done = status->position;
2266 priv->total = status->of_total;
2268 state = modest_mail_operation_clone_state (self);
2270 /* This is not a GDK lock because we are a Tinymail callback
2271 * which is already GDK locked by Tinymail */
2273 /* no gdk_threads_enter (), CHECKED */
2275 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2277 /* no gdk_threads_leave (), CHECKED */
2279 g_slice_free (ModestMailOperationState, state);
2283 transfer_folder_cb (TnyFolder *folder,
2285 TnyFolderStore *into,
2286 TnyFolder *new_folder,
2290 XFerFolderAsyncHelper *helper;
2291 ModestMailOperation *self = NULL;
2292 ModestMailOperationPrivate *priv = NULL;
2294 helper = (XFerFolderAsyncHelper *) user_data;
2295 g_return_if_fail (helper != NULL);
2297 self = helper->mail_op;
2298 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2301 priv->error = g_error_copy (err);
2303 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2304 } else if (cancelled) {
2305 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2306 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2307 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2308 _("Transference of %s was cancelled."),
2309 tny_folder_get_name (folder));
2312 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2315 /* Update state of new folder */
2317 tny_folder_refresh_async (new_folder, NULL, NULL, NULL);
2318 tny_folder_poke_status (new_folder);
2321 /* Notify about operation end */
2322 modest_mail_operation_notify_end (self);
2324 /* If user defined callback function was defined, call it */
2325 if (helper->user_callback) {
2327 /* This is not a GDK lock because we are a Tinymail callback
2328 * which is already GDK locked by Tinymail */
2330 /* no gdk_threads_enter (), CHECKED */
2331 helper->user_callback (self, new_folder, helper->user_data);
2332 /* no gdk_threads_leave () , CHECKED */
2336 g_object_unref (helper->mail_op);
2337 g_slice_free (XFerFolderAsyncHelper, helper);
2342 * This function checks if the new name is a valid name for our local
2343 * folders account. The new name could not be the same than then name
2344 * of any of the mandatory local folders
2346 * We can not rely on tinymail because tinymail does not check the
2347 * name of the virtual folders that the account could have in the case
2348 * that we're doing a rename (because it directly calls Camel which
2349 * knows nothing about our virtual folders).
2351 * In the case of an actual copy/move (i.e. move/copy a folder between
2352 * accounts) tinymail uses the tny_folder_store_create_account which
2353 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2354 * checks the new name of the folder, so this call in that case
2355 * wouldn't be needed. *But* NOTE that if tinymail changes its
2356 * implementation (if folder transfers within the same account is no
2357 * longer implemented as a rename) this call will allow Modest to work
2360 * If the new name is not valid, this function will set the status to
2361 * failed and will set also an error in the mail operation
2364 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2365 TnyFolderStore *into,
2366 const gchar *new_name)
2368 if (TNY_IS_ACCOUNT (into) &&
2369 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2370 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2372 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2373 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2374 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2375 _CS("ckdg_ib_folder_already_exists"));
2382 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2384 TnyFolderStore *parent,
2385 gboolean delete_original,
2386 XferFolderAsyncUserCallback user_callback,
2389 ModestMailOperationPrivate *priv = NULL;
2390 ModestTnyFolderRules parent_rules = 0, rules;
2391 XFerFolderAsyncHelper *helper = NULL;
2392 const gchar *folder_name = NULL;
2393 const gchar *error_msg;
2395 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2396 g_return_if_fail (TNY_IS_FOLDER (folder));
2397 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2399 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2400 folder_name = tny_folder_get_name (folder);
2402 /* Set the error msg */
2403 error_msg = _("mail_in_ui_folder_move_target_error");
2405 /* Get account and set it into mail_operation */
2406 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2407 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2408 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2410 /* Get folder rules */
2411 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2412 if (TNY_IS_FOLDER (parent))
2413 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2415 /* Apply operation constraints */
2416 if ((gpointer) parent == (gpointer) folder ||
2417 (!TNY_IS_FOLDER_STORE (parent)) ||
2418 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2421 } else if (TNY_IS_FOLDER (parent) &&
2422 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2426 } else if (TNY_IS_FOLDER (parent) &&
2427 TNY_IS_FOLDER_STORE (folder) &&
2428 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2429 TNY_FOLDER_STORE (folder))) {
2430 /* Do not move a parent into a child */
2432 } else if (TNY_IS_FOLDER_STORE (parent) &&
2433 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2434 /* Check that the new folder name is not used by any
2437 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2438 /* Check that the new folder name is not used by any
2439 special local folder */
2442 /* Create the helper */
2443 helper = g_slice_new0 (XFerFolderAsyncHelper);
2444 helper->mail_op = g_object_ref (self);
2445 helper->user_callback = user_callback;
2446 helper->user_data = user_data;
2448 /* Move/Copy folder */
2449 modest_mail_operation_notify_start (self);
2450 tny_folder_copy_async (folder,
2452 tny_folder_get_name (folder),
2455 transfer_folder_status_cb,
2461 /* Set status failed and set an error */
2462 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2463 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2464 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2467 /* Call the user callback if exists */
2469 user_callback (self, NULL, user_data);
2471 /* Notify the queue */
2472 modest_mail_operation_notify_end (self);
2476 modest_mail_operation_rename_folder (ModestMailOperation *self,
2479 XferFolderAsyncUserCallback user_callback,
2482 ModestMailOperationPrivate *priv;
2483 ModestTnyFolderRules rules;
2484 XFerFolderAsyncHelper *helper;
2486 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2487 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2488 g_return_if_fail (name);
2490 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2492 /* Get account and set it into mail_operation */
2493 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2494 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2496 /* Check folder rules */
2497 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2498 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2500 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2503 TnyFolderStore *into;
2505 into = tny_folder_get_folder_store (folder);
2507 /* Check that the new folder name is not used by any
2508 special local folder */
2509 if (new_name_valid_if_local_account (priv, into, name)) {
2510 /* Create the helper */
2511 helper = g_slice_new0 (XFerFolderAsyncHelper);
2512 helper->mail_op = g_object_ref(self);
2513 helper->user_callback = user_callback;
2514 helper->user_data = user_data;
2516 /* Rename. Camel handles folder subscription/unsubscription */
2517 modest_mail_operation_notify_start (self);
2518 tny_folder_copy_async (folder, into, name, TRUE,
2520 transfer_folder_status_cb,
2522 g_object_unref (into);
2524 g_object_unref (into);
2531 /* Set status failed and set an error */
2532 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2533 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2534 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2535 _("FIXME: unable to rename"));
2538 user_callback (self, NULL, user_data);
2540 /* Notify about operation end */
2541 modest_mail_operation_notify_end (self);
2544 /* ******************************************************************* */
2545 /* ************************** MSG ACTIONS ************************* */
2546 /* ******************************************************************* */
2549 modest_mail_operation_find_msg (ModestMailOperation *self,
2551 const gchar *msg_uid,
2552 gboolean progress_feedback,
2553 GetMsgAsyncUserCallback user_callback,
2556 GetMsgInfo *helper = NULL;
2557 ModestMailOperationPrivate *priv;
2559 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2560 g_return_if_fail (msg_uid != NULL);
2562 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2563 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2567 /* Check memory low */
2568 if (_check_memory_low (self)) {
2570 user_callback (self, NULL, FALSE, NULL, priv->error, user_data);
2571 modest_mail_operation_notify_end (self);
2575 /* Get account and set it into mail_operation */
2576 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2578 /* Check for cached messages */
2579 if (progress_feedback) {
2580 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2582 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2585 /* Create the helper */
2586 helper = g_slice_new0 (GetMsgInfo);
2587 helper->header = NULL;
2588 helper->mail_op = g_object_ref (self);
2589 helper->user_callback = user_callback;
2590 helper->user_data = user_data;
2591 helper->destroy_notify = NULL;
2592 helper->last_total_bytes = 0;
2593 helper->sum_total_bytes = 0;
2594 helper->total_bytes = 0;
2595 helper->more_msgs = NULL;
2597 modest_mail_operation_notify_start (self);
2599 /* notify about the start of the operation */
2600 ModestMailOperationState *state;
2601 state = modest_mail_operation_clone_state (self);
2604 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2606 g_slice_free (ModestMailOperationState, state);
2608 tny_folder_find_msg_async (folder, msg_uid, get_msg_async_cb, get_msg_status_cb, helper);
2612 modest_mail_operation_get_msg (ModestMailOperation *self,
2614 gboolean progress_feedback,
2615 GetMsgAsyncUserCallback user_callback,
2618 GetMsgInfo *helper = NULL;
2620 ModestMailOperationPrivate *priv;
2622 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2623 g_return_if_fail (TNY_IS_HEADER (header));
2625 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2626 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2630 /* Check memory low */
2631 if (_check_memory_low (self)) {
2633 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2634 modest_mail_operation_notify_end (self);
2638 /* Get account and set it into mail_operation */
2639 folder = tny_header_get_folder (header);
2640 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2642 /* Check for cached messages */
2643 if (progress_feedback) {
2644 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2645 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2647 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2649 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2652 /* Create the helper */
2653 helper = g_slice_new0 (GetMsgInfo);
2654 helper->header = g_object_ref (header);
2655 helper->mail_op = g_object_ref (self);
2656 helper->user_callback = user_callback;
2657 helper->user_data = user_data;
2658 helper->destroy_notify = NULL;
2659 helper->last_total_bytes = 0;
2660 helper->sum_total_bytes = 0;
2661 helper->total_bytes = tny_header_get_message_size (header);
2662 helper->more_msgs = NULL;
2664 modest_mail_operation_notify_start (self);
2666 /* notify about the start of the operation */
2667 ModestMailOperationState *state;
2668 state = modest_mail_operation_clone_state (self);
2671 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2673 g_slice_free (ModestMailOperationState, state);
2675 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2677 g_object_unref (G_OBJECT (folder));
2681 get_msg_status_cb (GObject *obj,
2685 GetMsgInfo *helper = NULL;
2687 g_return_if_fail (status != NULL);
2689 /* Show only the status information we want */
2690 if (status->code != TNY_FOLDER_STATUS_CODE_GET_MSG)
2693 helper = (GetMsgInfo *) user_data;
2694 g_return_if_fail (helper != NULL);
2696 /* Notify progress */
2697 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2698 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2702 get_msg_async_cb (TnyFolder *folder,
2708 GetMsgInfo *info = NULL;
2709 ModestMailOperationPrivate *priv = NULL;
2712 info = (GetMsgInfo *) user_data;
2714 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2717 if (info->more_msgs) {
2718 tny_iterator_next (info->more_msgs);
2719 finished = (tny_iterator_is_done (info->more_msgs));
2721 finished = (priv->done == priv->total) ? TRUE : FALSE;
2724 /* If canceled by the user, ignore the error given by Tinymail */
2728 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2730 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2731 priv->error = g_error_copy ((const GError *) err);
2733 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2735 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2736 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2739 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2740 /* Set the success status before calling the user callback */
2741 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2744 if (info->header == NULL && msg)
2745 info->header = tny_msg_get_header (msg);
2747 /* Call the user callback */
2748 if (info->user_callback)
2749 info->user_callback (info->mail_op, info->header, canceled,
2750 msg, err, info->user_data);
2752 /* Notify about operation end if this is the last callback */
2754 /* Free user data */
2755 if (info->destroy_notify)
2756 info->destroy_notify (info->user_data);
2758 /* Notify about operation end */
2759 modest_mail_operation_notify_end (info->mail_op);
2762 if (info->more_msgs)
2763 g_object_unref (info->more_msgs);
2765 g_object_unref (info->header);
2766 g_object_unref (info->mail_op);
2767 g_slice_free (GetMsgInfo, info);
2768 } else if (info->more_msgs) {
2769 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2770 TnyFolder *folder = tny_header_get_folder (header);
2772 g_object_unref (info->header);
2773 info->header = g_object_ref (header);
2775 /* Retrieve the next message */
2776 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2778 g_object_unref (header);
2779 g_object_unref (folder);
2781 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2786 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2787 TnyList *header_list,
2788 GetMsgAsyncUserCallback user_callback,
2790 GDestroyNotify notify)
2792 ModestMailOperationPrivate *priv = NULL;
2794 TnyIterator *iter = NULL;
2795 gboolean has_uncached_messages;
2797 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2799 /* Init mail operation */
2800 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2801 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2803 priv->total = tny_list_get_length(header_list);
2805 /* Check memory low */
2806 if (_check_memory_low (self)) {
2807 if (user_callback) {
2808 TnyHeader *header = NULL;
2811 if (tny_list_get_length (header_list) > 0) {
2812 iter = tny_list_create_iterator (header_list);
2813 header = (TnyHeader *) tny_iterator_get_current (iter);
2814 g_object_unref (iter);
2816 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2818 g_object_unref (header);
2822 /* Notify about operation end */
2823 modest_mail_operation_notify_end (self);
2827 /* Check uncached messages */
2828 for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
2829 !has_uncached_messages && !tny_iterator_is_done (iter);
2830 tny_iterator_next (iter)) {
2833 header = (TnyHeader *) tny_iterator_get_current (iter);
2834 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
2835 has_uncached_messages = TRUE;
2836 g_object_unref (header);
2838 g_object_unref (iter);
2839 priv->op_type = has_uncached_messages?MODEST_MAIL_OPERATION_TYPE_RECEIVE:MODEST_MAIL_OPERATION_TYPE_OPEN;
2841 /* Get account and set it into mail_operation */
2842 if (tny_list_get_length (header_list) >= 1) {
2843 TnyIterator *iterator = tny_list_create_iterator (header_list);
2844 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2846 TnyFolder *folder = tny_header_get_folder (header);
2848 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2849 g_object_unref (folder);
2851 g_object_unref (header);
2853 g_object_unref (iterator);
2856 msg_list_size = compute_message_list_size (header_list, 0);
2858 modest_mail_operation_notify_start (self);
2859 iter = tny_list_create_iterator (header_list);
2860 if (!tny_iterator_is_done (iter)) {
2861 /* notify about the start of the operation */
2862 ModestMailOperationState *state;
2863 state = modest_mail_operation_clone_state (self);
2866 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2869 GetMsgInfo *msg_info = NULL;
2870 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2871 TnyFolder *folder = tny_header_get_folder (header);
2873 /* Create the message info */
2874 msg_info = g_slice_new0 (GetMsgInfo);
2875 msg_info->mail_op = g_object_ref (self);
2876 msg_info->header = g_object_ref (header);
2877 msg_info->more_msgs = g_object_ref (iter);
2878 msg_info->user_callback = user_callback;
2879 msg_info->user_data = user_data;
2880 msg_info->destroy_notify = notify;
2881 msg_info->last_total_bytes = 0;
2882 msg_info->sum_total_bytes = 0;
2883 msg_info->total_bytes = msg_list_size;
2885 /* The callback will call it per each header */
2886 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2888 /* Free and go on */
2889 g_object_unref (header);
2890 g_object_unref (folder);
2891 g_slice_free (ModestMailOperationState, state);
2893 g_object_unref (iter);
2898 remove_msgs_async_cb (TnyFolder *folder,
2903 gboolean expunge, leave_on_server;
2904 const gchar *account_name;
2905 TnyAccount *account;
2906 ModestProtocolType account_proto = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2907 ModestMailOperation *self;
2908 ModestMailOperationPrivate *priv;
2909 ModestProtocolRegistry *protocol_registry;
2911 self = (ModestMailOperation *) user_data;
2912 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2913 protocol_registry = modest_runtime_get_protocol_registry ();
2915 if (canceled || err) {
2916 /* If canceled by the user, ignore the error given by Tinymail */
2918 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2920 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2921 priv->error = g_error_copy ((const GError *) err);
2922 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2925 modest_mail_operation_notify_end (self);
2926 g_object_unref (self);
2930 account = modest_tny_folder_get_account (folder);
2931 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2933 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2935 account_proto = modest_tny_account_get_protocol_type (account);
2936 g_object_unref (account);
2938 if ((modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto) &&
2939 !leave_on_server) ||
2940 !modest_tny_folder_is_remote_folder (folder))
2946 tny_folder_sync_async(folder, expunge, sync_folder_finish_callback,
2951 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2953 gboolean remove_to_trash /*ignored*/)
2955 TnyFolder *folder = NULL;
2956 ModestMailOperationPrivate *priv;
2957 TnyIterator *iter = NULL;
2958 TnyHeader *header = NULL;
2959 TnyList *remove_headers = NULL;
2960 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2961 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2963 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2964 g_return_if_fail (TNY_IS_LIST (headers));
2966 if (remove_to_trash)
2967 g_warning ("remove to trash is not implemented");
2969 if (tny_list_get_length(headers) == 0) {
2970 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2971 goto cleanup; /* nothing to do */
2974 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2976 /* Get folder from first header and sync it */
2977 iter = tny_list_create_iterator (headers);
2978 header = TNY_HEADER (tny_iterator_get_current (iter));
2979 g_object_unref (iter);
2981 folder = tny_header_get_folder (header);
2982 if (!TNY_IS_FOLDER(folder)) {
2983 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2987 /* Use the merged folder if we're removing messages from outbox */
2988 if (modest_tny_folder_is_local_folder (folder)) {
2989 ModestTnyLocalFoldersAccount *local_account;
2991 local_account = (ModestTnyLocalFoldersAccount *)
2992 modest_tny_account_store_get_local_folders_account (accstore);
2993 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2994 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2995 g_object_unref (folder);
2996 folder = modest_tny_local_folders_account_get_merged_outbox (local_account);
2998 g_object_unref (local_account);
3001 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3002 TnyIterator *headers_iter = tny_list_create_iterator (headers);
3004 while (!tny_iterator_is_done (headers_iter)) {
3005 TnyTransportAccount *traccount = NULL;
3006 TnyHeader *hdr = NULL;
3008 hdr = TNY_HEADER (tny_iterator_get_current (headers_iter));
3009 traccount = modest_tny_account_store_get_transport_account_from_outbox_header (accstore,
3012 ModestTnySendQueueStatus status;
3013 ModestTnySendQueue *send_queue;
3015 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
3016 if (TNY_IS_SEND_QUEUE (send_queue)) {
3019 msg_id = modest_tny_send_queue_get_msg_id (hdr);
3020 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
3021 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
3022 if (G_UNLIKELY (remove_headers == NULL))
3023 remove_headers = tny_simple_list_new ();
3024 tny_list_append(remove_headers, G_OBJECT(hdr));
3028 g_object_unref(traccount);
3030 g_object_unref(hdr);
3031 tny_iterator_next (headers_iter);
3033 g_object_unref(headers_iter);
3036 /* Get account and set it into mail_operation */
3037 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
3038 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
3039 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3041 if (!remove_headers)
3042 remove_headers = g_object_ref (headers);
3044 /* remove message from folder */
3045 modest_mail_operation_notify_start (self);
3046 tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb,
3047 NULL, g_object_ref (self));
3051 g_object_unref (remove_headers);
3053 g_object_unref (header);
3055 g_object_unref (folder);
3059 notify_progress_of_multiple_messages (ModestMailOperation *self,
3061 gint *last_total_bytes,
3062 gint *sum_total_bytes,
3064 gboolean increment_done)
3066 ModestMailOperationPrivate *priv;
3067 ModestMailOperationState *state;
3068 gboolean is_num_bytes = FALSE;
3070 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3072 /* We know that tinymail sends us information about
3073 * transferred bytes with this particular message
3075 if (status->message)
3076 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
3078 state = modest_mail_operation_clone_state (self);
3079 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
3080 /* We know that we're in a different message when the
3081 total number of bytes to transfer is different. Of
3082 course it could fail if we're transferring messages
3083 of the same size, but this is a workarround */
3084 if (status->of_total != *last_total_bytes) {
3085 /* We need to increment the done when there is
3086 no information about each individual
3087 message, we need to do this in message
3088 transfers, and we don't do it for getting
3092 *sum_total_bytes += *last_total_bytes;
3093 *last_total_bytes = status->of_total;
3095 state->bytes_done += status->position + *sum_total_bytes;
3096 state->bytes_total = total_bytes;
3098 /* Notify the status change. Only notify about changes
3099 referred to bytes */
3100 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3104 g_slice_free (ModestMailOperationState, state);
3108 transfer_msgs_status_cb (GObject *obj,
3112 XFerMsgsAsyncHelper *helper;
3114 g_return_if_fail (status != NULL);
3116 /* Show only the status information we want */
3117 if (status->code != TNY_FOLDER_STATUS_CODE_XFER_MSGS)
3120 helper = (XFerMsgsAsyncHelper *) user_data;
3121 g_return_if_fail (helper != NULL);
3123 /* Notify progress */
3124 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
3125 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
3129 transfer_msgs_sync_folder_cb (TnyFolder *self,
3134 XFerMsgsAsyncHelper *helper;
3135 /* We don't care here about the results of the
3137 helper = (XFerMsgsAsyncHelper *) user_data;
3139 /* Notify about operation end */
3140 modest_mail_operation_notify_end (helper->mail_op);
3142 /* If user defined callback function was defined, call it */
3143 if (helper->user_callback)
3144 helper->user_callback (helper->mail_op, helper->user_data);
3147 if (helper->more_msgs)
3148 g_object_unref (helper->more_msgs);
3149 if (helper->headers)
3150 g_object_unref (helper->headers);
3151 if (helper->dest_folder)
3152 g_object_unref (helper->dest_folder);
3153 if (helper->mail_op)
3154 g_object_unref (helper->mail_op);
3155 g_slice_free (XFerMsgsAsyncHelper, helper);
3159 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
3161 XFerMsgsAsyncHelper *helper;
3162 ModestMailOperation *self;
3163 ModestMailOperationPrivate *priv;
3164 gboolean finished = TRUE;
3166 helper = (XFerMsgsAsyncHelper *) user_data;
3167 self = helper->mail_op;
3169 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3172 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3174 priv->error = g_error_copy (err);
3176 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3177 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
3178 if (helper->more_msgs) {
3179 /* We'll transfer the next message in the list */
3180 tny_iterator_next (helper->more_msgs);
3181 if (!tny_iterator_is_done (helper->more_msgs)) {
3182 GObject *next_header;
3183 g_object_unref (helper->headers);
3184 helper->headers = tny_simple_list_new ();
3185 next_header = tny_iterator_get_current (helper->more_msgs);
3186 tny_list_append (helper->headers, next_header);
3187 g_object_unref (next_header);
3193 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3198 /* Synchronize the source folder contents. This should
3199 be done by tinymail but the camel_folder_sync it's
3200 actually disabled in transfer_msgs_thread_clean
3201 because it's supposed to cause hangs */
3202 tny_folder_sync_async (folder, helper->delete,
3203 transfer_msgs_sync_folder_cb,
3206 /* Transfer more messages */
3207 tny_folder_transfer_msgs_async (folder,
3209 helper->dest_folder,
3212 transfer_msgs_status_cb,
3217 /* Computes the size of the messages the headers in the list belongs
3218 to. If num_elements is different from 0 then it only takes into
3219 account the first num_elements for the calculation */
3221 compute_message_list_size (TnyList *headers,
3225 guint size = 0, element = 0;
3227 /* If num_elements is not valid then take all into account */
3228 if ((num_elements <= 0) || (num_elements > tny_list_get_length (headers)))
3229 num_elements = tny_list_get_length (headers);
3231 iter = tny_list_create_iterator (headers);
3232 while (!tny_iterator_is_done (iter) && element < num_elements) {
3233 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
3234 size += tny_header_get_message_size (header);
3235 g_object_unref (header);
3236 tny_iterator_next (iter);
3239 g_object_unref (iter);
3245 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
3248 gboolean delete_original,
3249 XferMsgsAsyncUserCallback user_callback,
3252 ModestMailOperationPrivate *priv = NULL;
3253 TnyIterator *iter = NULL;
3254 TnyFolder *src_folder = NULL;
3255 XFerMsgsAsyncHelper *helper = NULL;
3256 TnyHeader *header = NULL;
3257 ModestTnyFolderRules rules = 0;
3258 TnyAccount *dst_account = NULL;
3259 gboolean leave_on_server;
3260 ModestMailOperationState *state;
3261 ModestProtocolRegistry *protocol_registry;
3262 ModestProtocolType account_protocol;
3264 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
3265 g_return_if_fail (headers && TNY_IS_LIST (headers));
3266 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
3268 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3269 protocol_registry = modest_runtime_get_protocol_registry ();
3271 priv->total = tny_list_get_length (headers);
3273 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3274 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3276 /* Apply folder rules */
3277 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
3278 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3279 /* Set status failed and set an error */
3280 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3281 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3282 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
3283 _CS("ckct_ib_unable_to_paste_here"));
3284 /* Notify the queue */
3285 modest_mail_operation_notify_end (self);
3289 /* Get source folder */
3290 iter = tny_list_create_iterator (headers);
3291 header = TNY_HEADER (tny_iterator_get_current (iter));
3293 src_folder = tny_header_get_folder (header);
3294 g_object_unref (header);
3296 g_object_unref (iter);
3298 if (src_folder == NULL) {
3299 /* Notify the queue */
3300 modest_mail_operation_notify_end (self);
3302 g_warning ("%s: cannot find folder from header", __FUNCTION__);
3307 /* Check folder source and destination */
3308 if (src_folder == folder) {
3309 /* Set status failed and set an error */
3310 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3311 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3312 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
3313 _("mail_in_ui_folder_copy_target_error"));
3315 /* Notify the queue */
3316 modest_mail_operation_notify_end (self);
3319 g_object_unref (src_folder);
3323 /* Create the helper */
3324 helper = g_slice_new0 (XFerMsgsAsyncHelper);
3325 helper->mail_op = g_object_ref(self);
3326 helper->dest_folder = g_object_ref(folder);
3327 helper->user_callback = user_callback;
3328 helper->user_data = user_data;
3329 helper->last_total_bytes = 0;
3330 helper->sum_total_bytes = 0;
3331 helper->total_bytes = compute_message_list_size (headers, 0);
3333 /* Get account and set it into mail_operation */
3334 priv->account = modest_tny_folder_get_account (src_folder);
3335 dst_account = modest_tny_folder_get_account (folder);
3337 if (priv->account == dst_account) {
3338 /* Transfer all messages at once using the fast
3339 * method. Note that depending on the server this
3340 * might not be that fast, and might not be
3341 * user-cancellable either */
3342 helper->headers = g_object_ref (headers);
3343 helper->more_msgs = NULL;
3345 /* Transfer messages one by one so the user can cancel
3348 helper->headers = tny_simple_list_new ();
3349 helper->more_msgs = tny_list_create_iterator (headers);
3350 hdr = tny_iterator_get_current (helper->more_msgs);
3351 tny_list_append (helper->headers, hdr);
3352 g_object_unref (hdr);
3355 /* If leave_on_server is set to TRUE then don't use
3356 delete_original, we always pass FALSE. This is because
3357 otherwise tinymail will try to sync the source folder and
3358 this could cause an error if we're offline while
3359 transferring an already downloaded message from a POP
3361 account_protocol = modest_tny_account_get_protocol_type (priv->account);
3362 if (modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_protocol)) {
3363 const gchar *account_name;
3365 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
3366 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
3369 leave_on_server = FALSE;
3372 /* Do not delete messages if leave on server is TRUE */
3373 helper->delete = (leave_on_server) ? FALSE : delete_original;
3375 modest_mail_operation_notify_start (self);
3377 /* Start notifying progress */
3378 state = modest_mail_operation_clone_state (self);
3381 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3382 g_slice_free (ModestMailOperationState, state);
3384 tny_folder_transfer_msgs_async (src_folder,
3389 transfer_msgs_status_cb,
3391 g_object_unref (src_folder);
3392 g_object_unref (dst_account);
3397 on_refresh_folder (TnyFolder *folder,
3402 RefreshAsyncHelper *helper = NULL;
3403 ModestMailOperation *self = NULL;
3404 ModestMailOperationPrivate *priv = NULL;
3406 helper = (RefreshAsyncHelper *) user_data;
3407 self = helper->mail_op;
3408 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3410 g_return_if_fail(priv!=NULL);
3413 priv->error = g_error_copy (error);
3414 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3419 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3420 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3421 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
3422 _("Error trying to refresh the contents of %s"),
3423 tny_folder_get_name (folder));
3427 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3430 /* Call user defined callback, if it exists */
3431 if (helper->user_callback) {
3433 /* This is not a GDK lock because we are a Tinymail callback and
3434 * Tinymail already acquires the Gdk lock */
3435 helper->user_callback (self, folder, helper->user_data);
3439 g_slice_free (RefreshAsyncHelper, helper);
3441 /* Notify about operation end */
3442 modest_mail_operation_notify_end (self);
3443 g_object_unref(self);
3447 on_refresh_folder_status_update (GObject *obj,
3451 RefreshAsyncHelper *helper = NULL;
3452 ModestMailOperation *self = NULL;
3453 ModestMailOperationPrivate *priv = NULL;
3454 ModestMailOperationState *state;
3456 g_return_if_fail (user_data != NULL);
3457 g_return_if_fail (status != NULL);
3459 /* Show only the status information we want */
3460 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
3463 helper = (RefreshAsyncHelper *) user_data;
3464 self = helper->mail_op;
3465 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
3467 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3469 priv->done = status->position;
3470 priv->total = status->of_total;
3472 state = modest_mail_operation_clone_state (self);
3474 /* This is not a GDK lock because we are a Tinymail callback and
3475 * Tinymail already acquires the Gdk lock */
3476 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3478 g_slice_free (ModestMailOperationState, state);
3482 modest_mail_operation_refresh_folder (ModestMailOperation *self,
3484 RefreshAsyncUserCallback user_callback,
3487 ModestMailOperationPrivate *priv = NULL;
3488 RefreshAsyncHelper *helper = NULL;
3490 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3492 /* Check memory low */
3493 if (_check_memory_low (self)) {
3495 user_callback (self, folder, user_data);
3496 /* Notify about operation end */
3497 modest_mail_operation_notify_end (self);
3501 /* Get account and set it into mail_operation */
3502 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3503 priv->account = modest_tny_folder_get_account (folder);
3504 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3506 /* Create the helper */
3507 helper = g_slice_new0 (RefreshAsyncHelper);
3508 helper->mail_op = g_object_ref(self);
3509 helper->user_callback = user_callback;
3510 helper->user_data = user_data;
3512 modest_mail_operation_notify_start (self);
3514 /* notify that the operation was started */
3515 ModestMailOperationState *state;
3516 state = modest_mail_operation_clone_state (self);
3519 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3521 g_slice_free (ModestMailOperationState, state);
3523 tny_folder_refresh_async (folder,
3525 on_refresh_folder_status_update,
3530 run_queue_notify_and_destroy (RunQueueHelper *helper,
3531 ModestMailOperationStatus status)
3533 ModestMailOperationPrivate *priv;
3536 if (helper->error_handler &&
3537 g_signal_handler_is_connected (helper->queue, helper->error_handler))
3538 g_signal_handler_disconnect (helper->queue, helper->error_handler);
3539 if (helper->start_handler &&
3540 g_signal_handler_is_connected (helper->queue, helper->start_handler))
3541 g_signal_handler_disconnect (helper->queue, helper->start_handler);
3542 if (helper->stop_handler &&
3543 g_signal_handler_is_connected (helper->queue, helper->stop_handler))
3544 g_signal_handler_disconnect (helper->queue, helper->stop_handler);
3547 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
3548 priv->status = status;
3551 modest_mail_operation_notify_end (helper->self);
3554 g_object_unref (helper->queue);
3555 g_object_unref (helper->self);
3556 g_slice_free (RunQueueHelper, helper);
3560 run_queue_stop (ModestTnySendQueue *queue,
3563 RunQueueHelper *helper;
3565 g_debug ("%s sending queue stopped", __FUNCTION__);
3567 helper = (RunQueueHelper *) user_data;
3568 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
3572 modest_mail_operation_run_queue (ModestMailOperation *self,
3573 ModestTnySendQueue *queue)
3575 ModestMailOperationPrivate *priv;
3576 RunQueueHelper *helper;
3578 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3579 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3580 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3582 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3583 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3584 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
3586 /* Create the helper */
3587 helper = g_slice_new0 (RunQueueHelper);
3588 helper->queue = g_object_ref (queue);
3589 helper->self = g_object_ref (self);
3590 helper->stop_handler = g_signal_connect (queue, "queue-stop",
3591 G_CALLBACK (run_queue_stop),
3594 /* Notify operation has started */
3595 modest_mail_operation_notify_start (self);
3596 g_debug ("%s, run queue started", __FUNCTION__);
3600 queue_wakeup_callback (ModestTnySendQueue *queue,
3605 ModestMailOperation *mail_op;
3606 ModestMailOperationPrivate *priv;
3608 mail_op = (ModestMailOperation *) userdata;
3609 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3611 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3612 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (queue));
3615 modest_mail_operation_notify_end (mail_op);
3616 g_object_unref (mail_op);
3620 modest_mail_operation_queue_wakeup (ModestMailOperation *self,
3621 ModestTnySendQueue *queue)
3623 ModestMailOperationPrivate *priv;
3625 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3626 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3627 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3629 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3630 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3631 priv->op_type = MODEST_MAIL_OPERATION_TYPE_QUEUE_WAKEUP;
3633 g_object_ref (self);
3635 modest_tny_send_queue_wakeup (queue, queue_wakeup_callback, self);
3636 modest_mail_operation_notify_start (self);
3640 shutdown_callback (ModestTnyAccountStore *account_store, gpointer userdata)
3642 ModestMailOperation *self = (ModestMailOperation *) userdata;
3643 ModestMailOperationPrivate *priv;
3645 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3646 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3647 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3649 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3651 modest_mail_operation_notify_end (self);
3652 g_object_unref (self);
3656 modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore *account_store)
3658 ModestMailOperationPrivate *priv;
3660 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3661 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3662 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3664 modest_mail_operation_queue_set_running_shutdown (modest_runtime_get_mail_operation_queue ());
3666 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3667 priv->account = NULL;
3668 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SHUTDOWN;
3670 modest_mail_operation_notify_start (self);
3671 g_object_ref (self);
3672 modest_tny_account_store_shutdown (account_store, shutdown_callback, self);
3676 sync_folder_finish_callback (TnyFolder *self,
3682 ModestMailOperation *mail_op;
3683 ModestMailOperationPrivate *priv;
3685 mail_op = (ModestMailOperation *) user_data;
3686 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3688 /* If canceled by the user, ignore the error given by Tinymail */
3690 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3692 /* If the operation was a sync then the status is
3693 failed, but if it's part of another operation then
3694 just set it as finished with errors */
3695 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
3696 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3698 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
3699 priv->error = g_error_copy ((const GError *) err);
3700 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
3702 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3705 modest_mail_operation_notify_end (mail_op);
3706 g_object_unref (mail_op);
3710 modest_mail_operation_sync_folder (ModestMailOperation *self,
3711 TnyFolder *folder, gboolean expunge)
3713 ModestMailOperationPrivate *priv;
3715 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3716 g_return_if_fail (TNY_IS_FOLDER (folder));
3717 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3719 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3720 priv->account = modest_tny_folder_get_account (folder);
3721 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3723 modest_mail_operation_notify_start (self);
3724 g_object_ref (self);
3725 tny_folder_sync_async (folder, expunge,
3726 (TnyFolderCallback) sync_folder_finish_callback,
3731 modest_mail_operation_notify_start (ModestMailOperation *self)
3733 ModestMailOperationPrivate *priv = NULL;
3735 g_return_if_fail (self);
3737 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3739 /* Ensure that all the fields are filled correctly */
3740 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3742 /* Notify the observers about the mail operation. We do not
3743 wrapp this emission because we assume that this function is
3744 always called from within the main lock */
3745 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3750 * It's used by the mail operation queue to notify the observers
3751 * attached to that signal that the operation finished. We need to use
3752 * that because tinymail does not give us the progress of a given
3753 * operation when it finishes (it directly calls the operation
3757 modest_mail_operation_notify_end (ModestMailOperation *self)
3759 ModestMailOperationPrivate *priv = NULL;
3761 g_return_if_fail (self);
3763 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3765 /* Notify the observers about the mail operation end. We do
3766 not wrapp this emission because we assume that this
3767 function is always called from within the main lock */
3768 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3770 /* Remove the error user data */
3771 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3772 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3776 modest_mail_operation_get_account (ModestMailOperation *self)
3778 ModestMailOperationPrivate *priv = NULL;
3780 g_return_val_if_fail (self, NULL);
3782 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3784 return (priv->account) ? g_object_ref (priv->account) : NULL;
3788 modest_mail_operation_noop (ModestMailOperation *self)
3790 ModestMailOperationPrivate *priv = NULL;
3792 g_return_if_fail (self);
3794 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3795 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3796 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3800 /* This mail operation does nothing actually */
3801 modest_mail_operation_notify_start (self);
3802 modest_mail_operation_notify_end (self);
3807 modest_mail_operation_to_string (ModestMailOperation *self)
3809 const gchar *type, *status, *account_id;
3810 ModestMailOperationPrivate *priv = NULL;
3812 g_return_val_if_fail (self, NULL);
3814 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3816 /* new operations don't have anything interesting */
3817 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3818 return g_strdup_printf ("%p <new operation>", self);
3820 switch (priv->op_type) {
3821 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3822 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE: type= "SEND-AND-RECEIVE"; break;
3823 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3824 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3825 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3826 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3827 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3828 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3829 case MODEST_MAIL_OPERATION_TYPE_SHUTDOWN: type= "SHUTDOWN"; break;
3830 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3831 default: type = "UNEXPECTED"; break;
3834 switch (priv->status) {
3835 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3836 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3837 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3838 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3839 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3840 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3841 default: status= "UNEXPECTED"; break;
3844 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3846 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3847 priv->done, priv->total,
3848 priv->error && priv->error->message ? priv->error->message : "");
3852 * Once the mail operations were objects this will be no longer
3853 * needed. I don't like it, but we need it for the moment
3856 _check_memory_low (ModestMailOperation *mail_op)
3858 if (modest_platform_check_memory_low (NULL, FALSE)) {
3859 ModestMailOperationPrivate *priv;
3861 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3862 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3863 g_set_error (&(priv->error),
3864 MODEST_MAIL_OPERATION_ERROR,
3865 MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY,
3866 "Not enough memory to complete the operation");