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 struct _SyncFolderHelper {
227 ModestMailOperation *mail_op;
228 SyncFolderCallback user_callback;
232 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
236 static void modest_mail_operation_create_msg (ModestMailOperation *self,
237 const gchar *from, const gchar *to,
238 const gchar *cc, const gchar *bcc,
239 const gchar *subject, const gchar *plain_body,
240 const gchar *html_body, const GList *attachments_list,
241 const GList *images_list,
242 TnyHeaderFlags priority_flags,
243 const gchar *references, const gchar *in_reply_to,
244 ModestMailOperationCreateMsgCallback callback,
247 static gboolean idle_notify_queue (gpointer data);
250 ModestMailOperation *mail_op;
260 GList *attachments_list;
262 TnyHeaderFlags priority_flags;
263 ModestMailOperationCreateMsgCallback callback;
269 ModestMailOperation *mail_op;
271 ModestMailOperationCreateMsgCallback callback;
276 static GObjectClass *parent_class = NULL;
278 static guint signals[NUM_SIGNALS] = {0};
281 modest_mail_operation_get_type (void)
283 static GType my_type = 0;
285 static const GTypeInfo my_info = {
286 sizeof(ModestMailOperationClass),
287 NULL, /* base init */
288 NULL, /* base finalize */
289 (GClassInitFunc) modest_mail_operation_class_init,
290 NULL, /* class finalize */
291 NULL, /* class data */
292 sizeof(ModestMailOperation),
294 (GInstanceInitFunc) modest_mail_operation_init,
297 my_type = g_type_register_static (G_TYPE_OBJECT,
298 "ModestMailOperation",
305 modest_mail_operation_class_init (ModestMailOperationClass *klass)
307 GObjectClass *gobject_class;
308 gobject_class = (GObjectClass*) klass;
310 parent_class = g_type_class_peek_parent (klass);
311 gobject_class->finalize = modest_mail_operation_finalize;
313 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
316 * ModestMailOperation::progress-changed
317 * @self: the #MailOperation that emits the signal
318 * @user_data: user data set when the signal handler was connected
320 * Emitted when the progress of a mail operation changes
322 signals[PROGRESS_CHANGED_SIGNAL] =
323 g_signal_new ("progress-changed",
324 G_TYPE_FROM_CLASS (gobject_class),
326 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
328 g_cclosure_marshal_VOID__POINTER,
329 G_TYPE_NONE, 1, G_TYPE_POINTER);
333 * This signal is issued whenever a mail operation starts, and
334 * starts mean when the tinymail operation is issued. This
335 * means that it could happen that something wrong happens and
336 * the tinymail function is never called. In this situation a
337 * operation-finished will be issued without any
340 signals[OPERATION_STARTED_SIGNAL] =
341 g_signal_new ("operation-started",
342 G_TYPE_FROM_CLASS (gobject_class),
344 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
346 g_cclosure_marshal_VOID__VOID,
351 * This signal is issued whenever a mail operation
352 * finishes. Note that this signal could be issued without any
353 * previous "operation-started" signal, because this last one
354 * is only issued when the tinymail operation is successfully
357 signals[OPERATION_FINISHED_SIGNAL] =
358 g_signal_new ("operation-finished",
359 G_TYPE_FROM_CLASS (gobject_class),
361 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
363 g_cclosure_marshal_VOID__VOID,
368 modest_mail_operation_init (ModestMailOperation *obj)
370 ModestMailOperationPrivate *priv;
372 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
374 priv->account = NULL;
375 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
376 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
381 priv->error_checking = NULL;
382 priv->error_checking_user_data = NULL;
386 modest_mail_operation_finalize (GObject *obj)
388 ModestMailOperationPrivate *priv;
390 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
395 g_error_free (priv->error);
399 g_object_unref (priv->source);
403 g_object_unref (priv->account);
404 priv->account = NULL;
408 G_OBJECT_CLASS(parent_class)->finalize (obj);
412 modest_mail_operation_new (GObject *source)
414 ModestMailOperation *obj;
415 ModestMailOperationPrivate *priv;
417 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
418 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
421 priv->source = g_object_ref(source);
427 modest_mail_operation_new_with_error_handling (GObject *source,
428 ErrorCheckingUserCallback error_handler,
430 ErrorCheckingUserDataDestroyer error_handler_destroyer)
432 ModestMailOperation *obj;
433 ModestMailOperationPrivate *priv;
435 obj = modest_mail_operation_new (source);
436 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
438 g_return_val_if_fail (error_handler != NULL, obj);
439 priv->error_checking = error_handler;
440 priv->error_checking_user_data = user_data;
441 priv->error_checking_user_data_destroyer = error_handler_destroyer;
447 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
449 ModestMailOperationPrivate *priv;
451 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
453 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
454 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
456 /* Call the user callback */
457 if (priv->error_checking != NULL)
458 priv->error_checking (self, priv->error_checking_user_data);
462 ModestMailOperationTypeOperation
463 modest_mail_operation_get_type_operation (ModestMailOperation *self)
465 ModestMailOperationPrivate *priv;
467 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
468 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
470 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
472 return priv->op_type;
476 modest_mail_operation_is_mine (ModestMailOperation *self,
479 ModestMailOperationPrivate *priv;
481 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
484 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
485 if (priv->source == NULL) return FALSE;
487 return priv->source == me;
491 modest_mail_operation_get_source (ModestMailOperation *self)
493 ModestMailOperationPrivate *priv;
495 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
498 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
500 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
504 return (priv->source) ? g_object_ref (priv->source) : NULL;
507 ModestMailOperationStatus
508 modest_mail_operation_get_status (ModestMailOperation *self)
510 ModestMailOperationPrivate *priv;
512 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
513 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
514 MODEST_MAIL_OPERATION_STATUS_INVALID);
516 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
518 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
519 return MODEST_MAIL_OPERATION_STATUS_INVALID;
526 modest_mail_operation_get_error (ModestMailOperation *self)
528 ModestMailOperationPrivate *priv;
530 g_return_val_if_fail (self, NULL);
531 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
533 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
536 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
544 modest_mail_operation_cancel (ModestMailOperation *self)
546 ModestMailOperationPrivate *priv;
547 gboolean canceled = FALSE;
549 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
551 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
554 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
556 /* Cancel the mail operation */
557 g_return_val_if_fail (priv->account, FALSE);
558 tny_account_cancel (priv->account);
560 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
561 ModestTnySendQueue *queue;
562 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account),
565 /* Cancel the sending of the following next messages */
566 if (TNY_IS_SEND_QUEUE (queue))
567 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
574 modest_mail_operation_get_task_done (ModestMailOperation *self)
576 ModestMailOperationPrivate *priv;
578 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
581 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
586 modest_mail_operation_get_task_total (ModestMailOperation *self)
588 ModestMailOperationPrivate *priv;
590 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
593 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
598 modest_mail_operation_is_finished (ModestMailOperation *self)
600 ModestMailOperationPrivate *priv;
601 gboolean retval = FALSE;
603 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
606 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
608 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
609 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
610 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
611 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
621 * Creates an image of the current state of a mail operation, the
622 * caller must free it
624 static ModestMailOperationState *
625 modest_mail_operation_clone_state (ModestMailOperation *self)
627 ModestMailOperationState *state;
628 ModestMailOperationPrivate *priv;
630 g_return_val_if_fail (self, NULL);
631 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
632 g_return_val_if_fail (priv, NULL);
637 state = g_slice_new (ModestMailOperationState);
639 state->status = priv->status;
640 state->op_type = priv->op_type;
641 state->done = priv->done;
642 state->total = priv->total;
643 state->finished = modest_mail_operation_is_finished (self);
644 state->bytes_done = 0;
645 state->bytes_total = 0;
650 /* ******************************************************************* */
651 /* ************************** SEND ACTIONS ************************* */
652 /* ******************************************************************* */
656 ModestMailOperation *mail_op;
661 send_mail_on_sync_async_cb (TnyFolder *folder,
666 ModestMailOperationPrivate *priv;
667 ModestMailOperation *self;
668 SendNewMailHelper *helper;
670 helper = (SendNewMailHelper *) user_data;
671 self = helper->mail_op;
672 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
678 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
679 MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
680 "Error adding a msg to the send queue\n");
681 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
683 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
688 modest_mail_operation_notify_end (self);
690 g_object_unref (helper->mail_op);
691 g_slice_free (SendNewMailHelper, helper);
695 run_queue_start (TnySendQueue *self,
698 RunQueueHelper *helper = (RunQueueHelper *) user_data;
699 ModestMailOperation *mail_op;
701 g_debug ("%s sending queue successfully started", __FUNCTION__);
703 /* Wait for the message to be sent */
704 mail_op = modest_mail_operation_new (NULL);
705 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
707 modest_mail_operation_run_queue (mail_op, helper->queue);
708 g_object_unref (mail_op);
710 /* Free the helper and end operation */
711 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
715 run_queue_error_happened (TnySendQueue *queue,
721 RunQueueHelper *helper = (RunQueueHelper *) user_data;
722 ModestMailOperationPrivate *priv;
724 /* If we are here this means that the send queue could not
725 start to send emails. Shouldn't happen as this means that
726 we could not create the thread */
727 g_debug ("%s sending queue failed to create the thread", __FUNCTION__);
729 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
730 priv->error = g_error_copy ((const GError *) error);
732 if (error->code != TNY_SYSTEM_ERROR_UNKNOWN) {
733 /* This code is here for safety reasons. It should
734 never be called, because that would mean that we
735 are not controlling some error case */
736 g_warning ("%s Error %s should not happen",
737 __FUNCTION__, error->message);
740 /* Free helper and end operation */
741 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_FAILED);
745 send_mail_on_added_to_outbox (TnySendQueue *send_queue,
751 ModestMailOperationPrivate *priv;
752 ModestMailOperation *self;
753 SendNewMailHelper *helper;
755 helper = (SendNewMailHelper *) user_data;
756 self = helper->mail_op;
757 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
763 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
764 MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
765 "Error adding a msg to the send queue\n");
766 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
768 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
772 if (helper->notify) {
773 TnyTransportAccount *trans_account;
774 ModestTnySendQueue *queue;
776 trans_account = (TnyTransportAccount *) modest_mail_operation_get_account (self);
778 queue = modest_runtime_get_send_queue (trans_account, TRUE);
780 RunQueueHelper *helper;
782 /* Create the helper */
783 helper = g_slice_new0 (RunQueueHelper);
784 helper->queue = g_object_ref (queue);
785 helper->self = g_object_ref (self);
787 /* if sending is ongoing wait for the queue to
788 stop. Otherwise wait for the queue-start
789 signal. It could happen that the queue
790 could not start, then check also the error
792 if (modest_tny_send_queue_sending_in_progress (queue)) {
793 run_queue_start (TNY_SEND_QUEUE (queue), helper);
795 helper->start_handler = g_signal_connect (queue, "queue-start",
796 G_CALLBACK (run_queue_start),
798 helper->error_handler = g_signal_connect (queue, "error-happened",
799 G_CALLBACK (run_queue_error_happened),
803 /* Finalize this mail operation */
804 modest_mail_operation_notify_end (self);
806 g_object_unref (trans_account);
808 g_warning ("No transport account for the operation");
812 g_object_unref (helper->mail_op);
813 g_slice_free (SendNewMailHelper, helper);
817 idle_create_msg_cb (gpointer idle_data)
819 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
821 /* This is a GDK lock because we are an idle callback and
822 * info->callback can contain Gtk+ code */
824 gdk_threads_enter (); /* CHECKED */
825 info->callback (info->mail_op, info->msg, info->userdata);
827 g_object_unref (info->mail_op);
829 g_object_unref (info->msg);
830 g_slice_free (CreateMsgIdleInfo, info);
831 gdk_threads_leave (); /* CHECKED */
837 create_msg_thread (gpointer thread_data)
839 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
840 TnyMsg *new_msg = NULL;
841 ModestMailOperationPrivate *priv;
844 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
845 if (info->html_body == NULL) {
846 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
847 info->bcc, info->subject,
848 info->references, info->in_reply_to,
850 info->attachments_list, &attached,
853 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
854 info->bcc, info->subject,
855 info->references, info->in_reply_to,
857 info->plain_body, info->attachments_list,
858 info->images_list, &attached,
865 /* Set priority flags in message */
866 header = tny_msg_get_header (new_msg);
867 tny_header_set_flag (header, info->priority_flags);
869 /* Set attachment flags in message */
870 if (info->attachments_list != NULL && attached > 0)
871 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
873 g_object_unref (G_OBJECT(header));
875 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
877 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
878 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
879 "modest: failed to create a new msg\n");
887 g_free (info->plain_body);
888 g_free (info->html_body);
889 g_free (info->subject);
890 g_free (info->references);
891 g_free (info->in_reply_to);
892 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
893 g_list_free (info->attachments_list);
894 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
895 g_list_free (info->images_list);
897 if (info->callback) {
898 CreateMsgIdleInfo *idle_info;
899 idle_info = g_slice_new0 (CreateMsgIdleInfo);
900 idle_info->mail_op = g_object_ref (info->mail_op);
901 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
902 idle_info->callback = info->callback;
903 idle_info->userdata = info->userdata;
904 g_idle_add (idle_create_msg_cb, idle_info);
906 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
909 g_object_unref (info->mail_op);
910 g_slice_free (CreateMsgInfo, info);
911 if (new_msg) g_object_unref(new_msg);
917 modest_mail_operation_create_msg (ModestMailOperation *self,
918 const gchar *from, const gchar *to,
919 const gchar *cc, const gchar *bcc,
920 const gchar *subject, const gchar *plain_body,
921 const gchar *html_body,
922 const GList *attachments_list,
923 const GList *images_list,
924 TnyHeaderFlags priority_flags,
925 const gchar *references,
926 const gchar *in_reply_to,
927 ModestMailOperationCreateMsgCallback callback,
930 CreateMsgInfo *info = NULL;
932 info = g_slice_new0 (CreateMsgInfo);
933 info->mail_op = g_object_ref (self);
935 info->from = g_strdup (from);
936 info->to = g_strdup (to);
937 info->cc = g_strdup (cc);
938 info->bcc = g_strdup (bcc);
939 info->subject = g_strdup (subject);
940 info->plain_body = g_strdup (plain_body);
941 info->html_body = g_strdup (html_body);
942 info->references = g_strdup (references);
943 info->in_reply_to = g_strdup (in_reply_to);
944 info->attachments_list = g_list_copy ((GList *) attachments_list);
945 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
946 info->images_list = g_list_copy ((GList *) images_list);
947 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
948 info->priority_flags = priority_flags;
950 info->callback = callback;
951 info->userdata = userdata;
953 g_thread_create (create_msg_thread, info, FALSE, NULL);
958 TnyTransportAccount *transport_account;
963 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
967 TnySendQueue *send_queue = NULL;
968 ModestMailOperationPrivate *priv = NULL;
969 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
970 TnyFolder *draft_folder = NULL;
971 TnyFolder *outbox_folder = NULL;
972 TnyHeader *header = NULL;
974 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
977 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
978 modest_mail_operation_notify_end (self);
982 if (priv->error && priv->error->code != MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
983 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
984 modest_mail_operation_notify_end (self);
988 /* Add message to send queue */
989 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (info->transport_account, TRUE));
990 if (!TNY_IS_SEND_QUEUE(send_queue)) {
992 g_error_free (priv->error);
995 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
996 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
997 "modest: could not find send queue for account\n");
998 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
999 modest_mail_operation_notify_end (self);
1002 SendNewMailHelper *helper = g_slice_new (SendNewMailHelper);
1003 helper->mail_op = g_object_ref (self);
1004 helper->notify = (info->draft_msg == NULL);
1006 /* Add the msg to the queue. The callback will free
1008 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1010 tny_send_queue_add_async (send_queue, msg, send_mail_on_added_to_outbox,
1014 if (info->draft_msg != NULL) {
1015 TnyList *tmp_headers = NULL;
1016 TnyFolder *folder = NULL;
1017 TnyFolder *src_folder = NULL;
1018 TnyFolderType folder_type;
1019 TnyTransportAccount *transport_account = NULL;
1020 SendNewMailHelper *helper = NULL;
1022 /* To remove the old mail from its source folder, we need to get the
1023 * transport account of the original draft message (the transport account
1024 * might have been changed by the user) */
1025 header = tny_msg_get_header (info->draft_msg);
1026 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
1027 modest_runtime_get_account_store(), header);
1028 if (transport_account == NULL)
1029 transport_account = g_object_ref(info->transport_account);
1030 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
1031 TNY_FOLDER_TYPE_DRAFTS);
1032 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
1033 TNY_FOLDER_TYPE_OUTBOX);
1034 g_object_unref(transport_account);
1036 if (!draft_folder) {
1037 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
1039 modest_mail_operation_notify_end (self);
1042 if (!outbox_folder) {
1043 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
1045 modest_mail_operation_notify_end (self);
1049 folder = tny_msg_get_folder (info->draft_msg);
1050 if (folder == NULL) {
1051 modest_mail_operation_notify_end (self);
1054 folder_type = modest_tny_folder_guess_folder_type (folder);
1056 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1057 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1059 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
1060 src_folder = outbox_folder;
1062 src_folder = draft_folder;
1064 /* Note: This can fail (with a warning) if the message is not really already in a folder,
1065 * because this function requires it to have a UID. */
1066 helper = g_slice_new (SendNewMailHelper);
1067 helper->mail_op = g_object_ref (self);
1068 helper->notify = TRUE;
1070 tmp_headers = tny_simple_list_new ();
1071 tny_list_append (tmp_headers, (GObject*) header);
1072 tny_folder_remove_msgs_async (src_folder, tmp_headers, NULL, NULL, NULL);
1073 g_object_unref (tmp_headers);
1074 tny_folder_sync_async (src_folder, TRUE, send_mail_on_sync_async_cb,
1076 g_object_unref (folder);
1081 g_object_unref (header);
1082 if (info->draft_msg)
1083 g_object_unref (info->draft_msg);
1085 g_object_unref (draft_folder);
1087 g_object_unref (outbox_folder);
1088 if (info->transport_account)
1089 g_object_unref (info->transport_account);
1090 g_slice_free (SendNewMailInfo, info);
1094 modest_mail_operation_send_new_mail (ModestMailOperation *self,
1095 TnyTransportAccount *transport_account,
1097 const gchar *from, const gchar *to,
1098 const gchar *cc, const gchar *bcc,
1099 const gchar *subject, const gchar *plain_body,
1100 const gchar *html_body,
1101 const GList *attachments_list,
1102 const GList *images_list,
1103 const gchar *references,
1104 const gchar *in_reply_to,
1105 TnyHeaderFlags priority_flags)
1107 ModestMailOperationPrivate *priv = NULL;
1108 SendNewMailInfo *info;
1110 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1111 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1113 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1114 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
1115 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
1116 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1118 modest_mail_operation_notify_start (self);
1120 /* Check parametters */
1122 /* Set status failed and set an error */
1123 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1124 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1125 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
1126 _("Error trying to send a mail. You need to set at least one recipient"));
1127 modest_mail_operation_notify_end (self);
1130 info = g_slice_new0 (SendNewMailInfo);
1131 info->transport_account = transport_account;
1132 if (transport_account)
1133 g_object_ref (transport_account);
1134 info->draft_msg = draft_msg;
1136 g_object_ref (draft_msg);
1139 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1140 attachments_list, images_list, priority_flags,
1141 references, in_reply_to,
1142 modest_mail_operation_send_new_mail_cb, info);
1148 ModestMailOperation *mailop;
1150 SaveToDraftstCallback callback;
1152 } FinishSaveRemoteDraftInfo;
1155 finish_save_remote_draft (ModestAccountProtocol *protocol,
1157 const gchar *account_id,
1158 TnyMsg *new_remote_msg,
1163 FinishSaveRemoteDraftInfo *info = (FinishSaveRemoteDraftInfo *) userdata;
1164 ModestMailOperationPrivate *priv = NULL;
1166 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1168 if (!priv->error && err != NULL) {
1169 /* Priority for errors in save to local stage */
1170 priv->error = g_error_copy (err);
1171 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1175 info->callback (info->mailop, info->msg, info->userdata);
1178 g_object_unref (info->msg);
1180 modest_mail_operation_notify_end (info->mailop);
1181 g_object_unref (info->mailop);
1183 g_slice_free (FinishSaveRemoteDraftInfo, info);
1188 TnyTransportAccount *transport_account;
1190 SaveToDraftstCallback callback;
1194 ModestMailOperation *mailop;
1195 } SaveToDraftsAddMsgInfo;
1198 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1203 ModestMailOperationPrivate *priv = NULL;
1204 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1205 GError *io_error = NULL;
1206 gboolean callback_called = FALSE;
1208 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1210 if (priv->error && priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1211 io_error = priv->error;
1215 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1216 g_error_free(priv->error);
1219 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1221 if ((!priv->error) && (info->draft_msg != NULL)) {
1222 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1223 TnyFolder *src_folder = tny_header_get_folder (header);
1225 g_debug ("--- REMOVE AND SYNC");
1226 /* Remove the old draft */
1227 tny_folder_remove_msg (src_folder, header, NULL);
1229 /* Synchronize to expunge and to update the msg counts */
1230 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1231 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1232 g_debug ("--- REMOVED - SYNCED");
1234 g_object_unref (G_OBJECT(header));
1235 g_object_unref (G_OBJECT(src_folder));
1239 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1241 g_error_free (io_error);
1244 } else if (io_error) {
1245 priv->error = io_error;
1246 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
1248 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1251 if (info->transport_account) {
1252 ModestProtocolType transport_protocol_type;
1253 ModestProtocol *transport_protocol;
1255 transport_protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (info->transport_account));
1257 transport_protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
1258 transport_protocol_type);
1259 if (transport_protocol && MODEST_IS_ACCOUNT_PROTOCOL (transport_protocol)) {
1260 FinishSaveRemoteDraftInfo *srd_info = g_slice_new (FinishSaveRemoteDraftInfo);
1261 srd_info->mailop = info->mailop?g_object_ref (info->mailop):NULL;
1262 srd_info->msg = info->msg?g_object_ref (info->msg):NULL;
1263 srd_info->callback = info->callback;
1264 srd_info->userdata = info->user_data;
1265 modest_account_protocol_save_remote_draft (MODEST_ACCOUNT_PROTOCOL (transport_protocol),
1266 tny_account_get_id (TNY_ACCOUNT (info->transport_account)),
1267 info->msg, info->draft_msg,
1268 finish_save_remote_draft,
1271 callback_called = TRUE;
1275 /* Call the user callback */
1276 if (!callback_called && info->callback)
1277 info->callback (info->mailop, info->msg, info->user_data);
1279 if (info->transport_account)
1280 g_object_unref (G_OBJECT(info->transport_account));
1281 if (info->draft_msg)
1282 g_object_unref (G_OBJECT (info->draft_msg));
1284 g_object_unref (G_OBJECT(info->drafts));
1286 g_object_unref (G_OBJECT (info->msg));
1288 if (!callback_called)
1289 modest_mail_operation_notify_end (info->mailop);
1291 g_object_unref(info->mailop);
1292 g_slice_free (SaveToDraftsAddMsgInfo, info);
1297 TnyTransportAccount *transport_account;
1299 SaveToDraftstCallback callback;
1304 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1308 TnyFolder *drafts = NULL;
1309 ModestMailOperationPrivate *priv = NULL;
1310 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1312 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1315 if (!(priv->error)) {
1316 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1317 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1318 "modest: failed to create a new msg\n");
1321 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1322 TNY_FOLDER_TYPE_DRAFTS);
1323 if (!drafts && !(priv->error)) {
1324 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1325 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1326 "modest: failed to create a new msg\n");
1330 if (!priv->error || priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1332 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1333 cb_info->transport_account = g_object_ref(info->transport_account);
1334 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1335 cb_info->callback = info->callback;
1336 cb_info->user_data = info->user_data;
1337 cb_info->drafts = g_object_ref(drafts);
1338 cb_info->msg = g_object_ref(msg);
1339 cb_info->mailop = g_object_ref(self);
1340 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1344 /* Call the user callback */
1345 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1347 info->callback (self, msg, info->user_data);
1348 modest_mail_operation_notify_end (self);
1352 g_object_unref (G_OBJECT(drafts));
1353 if (info->draft_msg)
1354 g_object_unref (G_OBJECT (info->draft_msg));
1355 if (info->transport_account)
1356 g_object_unref (G_OBJECT(info->transport_account));
1357 g_slice_free (SaveToDraftsInfo, info);
1361 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1362 TnyTransportAccount *transport_account,
1364 const gchar *from, const gchar *to,
1365 const gchar *cc, const gchar *bcc,
1366 const gchar *subject, const gchar *plain_body,
1367 const gchar *html_body,
1368 const GList *attachments_list,
1369 const GList *images_list,
1370 TnyHeaderFlags priority_flags,
1371 const gchar *references,
1372 const gchar *in_reply_to,
1373 SaveToDraftstCallback callback,
1376 ModestMailOperationPrivate *priv = NULL;
1377 SaveToDraftsInfo *info = NULL;
1379 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1380 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1382 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1384 /* Get account and set it into mail_operation */
1385 priv->account = g_object_ref (transport_account);
1386 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1388 info = g_slice_new0 (SaveToDraftsInfo);
1389 info->transport_account = g_object_ref (transport_account);
1390 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1391 info->callback = callback;
1392 info->user_data = user_data;
1394 g_debug ("--- CREATE MESSAGE");
1395 modest_mail_operation_notify_start (self);
1396 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1397 attachments_list, images_list, priority_flags,
1398 references, in_reply_to,
1399 modest_mail_operation_save_to_drafts_cb, info);
1404 ModestMailOperation *mail_op;
1405 TnyMimePart *mime_part;
1407 GetMimePartSizeCallback callback;
1409 } GetMimePartSizeInfo;
1411 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1412 /* We use this folder observer to track the headers that have been
1413 * added to a folder */
1416 TnyList *new_headers;
1417 } InternalFolderObserver;
1420 GObjectClass parent;
1421 } InternalFolderObserverClass;
1423 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1425 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1426 internal_folder_observer,
1428 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1432 foreach_add_item (gpointer header, gpointer user_data)
1434 tny_list_append (TNY_LIST (user_data), G_OBJECT (header));
1437 /* This is the method that looks for new messages in a folder */
1439 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1441 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1443 TnyFolderChangeChanged changed;
1445 changed = tny_folder_change_get_changed (change);
1447 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1450 /* Get added headers */
1451 list = tny_simple_list_new ();
1452 tny_folder_change_get_added_headers (change, list);
1454 /* Add them to the folder observer */
1455 tny_list_foreach (list, foreach_add_item,
1456 derived->new_headers);
1458 g_object_unref (G_OBJECT (list));
1463 internal_folder_observer_init (InternalFolderObserver *self)
1465 self->new_headers = tny_simple_list_new ();
1468 internal_folder_observer_finalize (GObject *object)
1470 InternalFolderObserver *self;
1472 self = (InternalFolderObserver *) object;
1473 g_object_unref (self->new_headers);
1475 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1478 tny_folder_observer_init (TnyFolderObserverIface *iface)
1480 iface->update = internal_folder_observer_update;
1483 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1485 GObjectClass *object_class;
1487 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1488 object_class = (GObjectClass*) klass;
1489 object_class->finalize = internal_folder_observer_finalize;
1493 destroy_update_account_info (UpdateAccountInfo *info)
1495 g_free (info->account_name);
1496 g_object_unref (info->folders);
1497 g_object_unref (info->mail_op);
1498 g_slice_free (UpdateAccountInfo, info);
1503 update_account_send_mail (UpdateAccountInfo *info)
1505 TnyTransportAccount *transport_account = NULL;
1506 ModestTnyAccountStore *account_store;
1508 account_store = modest_runtime_get_account_store ();
1510 /* We don't try to send messages while sending mails is blocked */
1511 if (modest_tny_account_store_is_send_mail_blocked (account_store))
1514 /* Get the transport account */
1515 transport_account = (TnyTransportAccount *)
1516 modest_tny_account_store_get_server_account (account_store, info->account_name,
1517 TNY_ACCOUNT_TYPE_TRANSPORT);
1519 if (transport_account) {
1520 ModestTnySendQueue *send_queue;
1524 send_queue = modest_runtime_get_send_queue (transport_account, TRUE);
1525 g_object_unref (transport_account);
1527 if (TNY_IS_SEND_QUEUE (send_queue)) {
1528 /* Get outbox folder */
1529 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1530 if (outbox) { /* this could fail in some cases */
1531 num_messages = tny_folder_get_all_count (outbox);
1532 g_object_unref (outbox);
1534 g_warning ("%s: could not get outbox", __FUNCTION__);
1538 if (num_messages != 0) {
1539 ModestMailOperation *mail_op;
1540 /* Reenable suspended items */
1541 mail_op = modest_mail_operation_new (NULL);
1542 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1544 modest_mail_operation_queue_wakeup (mail_op, MODEST_TNY_SEND_QUEUE (send_queue));
1547 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1555 update_account_get_msg_async_cb (TnyFolder *folder,
1561 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1562 ModestMailOperationPrivate *priv;
1564 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (msg_info->mail_op);
1567 if (TNY_IS_MSG (msg)) {
1568 TnyHeader *header = tny_msg_get_header (msg);
1571 ModestMailOperationState *state;
1572 state = modest_mail_operation_clone_state (msg_info->mail_op);
1573 msg_info->sum_total_bytes += tny_header_get_message_size (header);
1574 state->bytes_done = msg_info->sum_total_bytes;
1575 state->bytes_total = msg_info->total_bytes;
1577 /* Notify the status change. Only notify about changes
1578 referred to bytes */
1579 g_signal_emit (G_OBJECT (msg_info->mail_op),
1580 signals[PROGRESS_CHANGED_SIGNAL],
1583 g_object_unref (header);
1584 g_slice_free (ModestMailOperationState, state);
1588 if (priv->done == priv->total) {
1589 TnyList *new_headers;
1590 UpdateAccountInfo *info;
1592 /* After getting all the messages send the ones in the
1594 info = (UpdateAccountInfo *) msg_info->user_data;
1595 update_account_send_mail (info);
1597 /* Check if the operation was a success */
1599 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1601 /* Call the user callback and free */
1602 new_headers = tny_iterator_get_list (msg_info->more_msgs);
1603 update_account_notify_user_and_free (info, new_headers);
1605 /* Delete the helper */
1606 g_object_unref (msg_info->more_msgs);
1607 g_object_unref (msg_info->mail_op);
1608 g_slice_free (GetMsgInfo, msg_info);
1613 update_account_notify_user_and_free (UpdateAccountInfo *info,
1614 TnyList *new_headers)
1616 /* Set the account back to not busy */
1617 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (),
1618 info->account_name, FALSE);
1622 info->callback (info->mail_op, new_headers, info->user_data);
1624 /* Mail operation end */
1625 modest_mail_operation_notify_end (info->mail_op);
1629 g_object_unref (new_headers);
1630 destroy_update_account_info (info);
1634 inbox_refreshed_cb (TnyFolder *inbox,
1639 UpdateAccountInfo *info;
1640 ModestMailOperationPrivate *priv;
1641 TnyIterator *new_headers_iter;
1642 GPtrArray *new_headers_array = NULL;
1643 gint max_size, retrieve_limit, i;
1644 ModestAccountMgr *mgr;
1645 ModestAccountRetrieveType retrieve_type;
1646 TnyList *new_headers = NULL;
1647 gboolean headers_only;
1648 time_t time_to_store;
1650 info = (UpdateAccountInfo *) user_data;
1651 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1652 mgr = modest_runtime_get_account_mgr ();
1654 if (canceled || err) {
1655 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1657 priv->error = g_error_copy (err);
1659 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1660 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1664 tny_folder_remove_observer (inbox, info->inbox_observer);
1665 g_object_unref (info->inbox_observer);
1666 info->inbox_observer = NULL;
1668 /* Notify the user about the error and then exit */
1669 update_account_notify_user_and_free (info, NULL);
1674 /* Try to send anyway */
1678 /* Set the last updated as the current time */
1679 #ifdef MODEST_USE_LIBTIME
1681 time_get_utc (&utc_tm);
1682 time_to_store = time_mktime (&utc_tm, "GMT");
1684 time_to_store = time (NULL);
1686 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
1688 /* Get the message max size */
1689 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1690 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1692 max_size = G_MAXINT;
1694 max_size = max_size * KB;
1696 /* Create the new headers array. We need it to sort the
1697 new headers by date */
1698 new_headers_array = g_ptr_array_new ();
1699 if (info->inbox_observer) {
1700 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1701 while (!tny_iterator_is_done (new_headers_iter)) {
1702 TnyHeader *header = NULL;
1704 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1705 /* Apply per-message size limits */
1706 if (tny_header_get_message_size (header) < max_size)
1707 g_ptr_array_add (new_headers_array, g_object_ref (header));
1709 g_object_unref (header);
1710 tny_iterator_next (new_headers_iter);
1712 g_object_unref (new_headers_iter);
1714 tny_folder_remove_observer (inbox, info->inbox_observer);
1715 g_object_unref (info->inbox_observer);
1716 info->inbox_observer = NULL;
1719 if (new_headers_array->len == 0) {
1720 g_ptr_array_free (new_headers_array, FALSE);
1724 /* Get per-account message amount retrieval limit */
1725 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1726 if (retrieve_limit == 0)
1727 retrieve_limit = G_MAXINT;
1729 /* Get per-account retrieval type */
1730 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1731 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1734 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1736 /* Copy the headers to a list and free the array */
1737 new_headers = tny_simple_list_new ();
1738 for (i=0; i < new_headers_array->len; i++) {
1739 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1740 /* We want the first element to be the most recent
1741 one, that's why we reverse the list */
1742 tny_list_prepend (new_headers, G_OBJECT (header));
1744 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1745 g_ptr_array_free (new_headers_array, FALSE);
1747 if (!headers_only && (tny_list_get_length (new_headers) > 0)) {
1750 GetMsgInfo *msg_info;
1753 priv->total = MIN (tny_list_get_length (new_headers), retrieve_limit);
1755 iter = tny_list_create_iterator (new_headers);
1757 /* Create the message info */
1758 msg_info = g_slice_new0 (GetMsgInfo);
1759 msg_info->mail_op = g_object_ref (info->mail_op);
1760 msg_info->total_bytes = compute_message_list_size (new_headers, priv->total);
1761 msg_info->more_msgs = g_object_ref (iter);
1762 msg_info->user_data = info;
1764 while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) {
1765 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1766 TnyFolder *folder = tny_header_get_folder (header);
1768 /* Get message in an async way */
1769 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1772 g_object_unref (folder);
1773 g_object_unref (header);
1776 tny_iterator_next (iter);
1778 g_object_unref (iter);
1779 g_object_unref (new_headers);
1781 /* The mail operation will finish when the last
1782 message is retrieved */
1786 /* If we don't have to retrieve the new messages then
1788 update_account_send_mail (info);
1790 /* Check if the operation was a success */
1792 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1794 /* Call the user callback and free */
1795 update_account_notify_user_and_free (info, new_headers);
1799 inbox_refresh_status_update (GObject *obj,
1803 UpdateAccountInfo *info = NULL;
1804 ModestMailOperation *self = NULL;
1805 ModestMailOperationPrivate *priv = NULL;
1806 ModestMailOperationState *state;
1808 g_return_if_fail (user_data != NULL);
1809 g_return_if_fail (status != NULL);
1811 /* Show only the status information we want */
1812 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
1815 info = (UpdateAccountInfo *) user_data;
1816 self = info->mail_op;
1817 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1819 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1821 priv->done = status->position;
1822 priv->total = status->of_total;
1824 state = modest_mail_operation_clone_state (self);
1826 /* This is not a GDK lock because we are a Tinymail callback and
1827 * Tinymail already acquires the Gdk lock */
1828 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1830 g_slice_free (ModestMailOperationState, state);
1834 recurse_folders_async_cb (TnyFolderStore *folder_store,
1840 UpdateAccountInfo *info;
1841 ModestMailOperationPrivate *priv;
1843 info = (UpdateAccountInfo *) user_data;
1844 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1846 if (err || canceled) {
1847 /* If the error was previosly set by another callback
1848 don't set it again */
1850 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1852 priv->error = g_error_copy (err);
1854 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1855 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1859 /* We're not getting INBOX children if we don't want to poke all */
1860 TnyIterator *iter = tny_list_create_iterator (list);
1861 while (!tny_iterator_is_done (iter)) {
1862 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1864 /* Add to the list of all folders */
1865 tny_list_append (info->folders, (GObject *) folder);
1867 if (info->poke_all) {
1868 TnyList *folders = tny_simple_list_new ();
1869 /* Add pending call */
1870 info->pending_calls++;
1872 tny_folder_store_get_folders_async (folder, folders, NULL, FALSE,
1873 recurse_folders_async_cb,
1875 g_object_unref (folders);
1878 g_object_unref (G_OBJECT (folder));
1880 tny_iterator_next (iter);
1882 g_object_unref (G_OBJECT (iter));
1885 /* Remove my own pending call */
1886 info->pending_calls--;
1888 /* This means that we have all the folders */
1889 if (info->pending_calls == 0) {
1890 TnyIterator *iter_all_folders;
1891 TnyFolder *inbox = NULL;
1893 /* If there was any error do not continue */
1895 update_account_notify_user_and_free (info, NULL);
1899 iter_all_folders = tny_list_create_iterator (info->folders);
1901 /* Do a poke status over all folders */
1902 while (!tny_iterator_is_done (iter_all_folders) &&
1903 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1904 TnyFolder *folder = NULL;
1906 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1908 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1909 /* Get a reference to the INBOX */
1910 inbox = g_object_ref (folder);
1912 /* Issue a poke status over the folder */
1914 tny_folder_poke_status (folder);
1917 /* Free and go to next */
1918 g_object_unref (folder);
1919 tny_iterator_next (iter_all_folders);
1921 g_object_unref (iter_all_folders);
1923 /* Refresh the INBOX */
1925 /* Refresh the folder. Our observer receives
1926 * the new emails during folder refreshes, so
1927 * we can use observer->new_headers
1929 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1930 tny_folder_add_observer (inbox, info->inbox_observer);
1932 /* Refresh the INBOX */
1933 tny_folder_refresh_async (inbox, inbox_refreshed_cb, inbox_refresh_status_update, info);
1934 g_object_unref (inbox);
1936 /* We could not perform the inbox refresh but
1937 we'll try to send mails anyway */
1938 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1944 modest_mail_operation_update_account (ModestMailOperation *self,
1945 const gchar *account_name,
1947 gboolean interactive,
1948 UpdateAccountCallback callback,
1951 UpdateAccountInfo *info = NULL;
1952 ModestMailOperationPrivate *priv = NULL;
1953 ModestTnyAccountStore *account_store = NULL;
1955 ModestMailOperationState *state;
1957 /* Init mail operation */
1958 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1961 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1962 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1964 /* Get the store account */
1965 account_store = modest_runtime_get_account_store ();
1967 modest_tny_account_store_get_server_account (account_store,
1969 TNY_ACCOUNT_TYPE_STORE);
1971 /* The above function could return NULL */
1972 if (!priv->account) {
1973 /* Check if the operation was a success */
1974 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1975 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1977 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1979 /* Call the user callback */
1981 callback (self, NULL, user_data);
1983 /* Notify about operation end */
1984 modest_mail_operation_notify_end (self);
1989 /* We have once seen priv->account getting finalized during this code,
1990 * therefore adding a reference (bug #82296) */
1992 g_object_ref (priv->account);
1994 /* Create the helper object */
1995 info = g_slice_new0 (UpdateAccountInfo);
1996 info->pending_calls = 1;
1997 info->folders = tny_simple_list_new ();
1998 info->mail_op = g_object_ref (self);
1999 info->poke_all = poke_all;
2000 info->interactive = interactive;
2001 info->account_name = g_strdup (account_name);
2002 info->callback = callback;
2003 info->user_data = user_data;
2005 /* Set account busy */
2006 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
2007 modest_mail_operation_notify_start (self);
2009 /* notify about the start of the operation */
2010 state = modest_mail_operation_clone_state (self);
2014 /* Start notifying progress */
2015 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2016 g_slice_free (ModestMailOperationState, state);
2018 /* Get all folders and continue in the callback */
2019 folders = tny_simple_list_new ();
2020 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
2021 folders, NULL, TRUE,
2022 recurse_folders_async_cb,
2024 g_object_unref (folders);
2026 g_object_unref (priv->account);
2031 * Used to notify the queue from the main
2032 * loop. We call it inside an idle call to achieve that
2035 idle_notify_queue (gpointer data)
2037 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
2039 gdk_threads_enter ();
2040 modest_mail_operation_notify_end (mail_op);
2041 gdk_threads_leave ();
2042 g_object_unref (mail_op);
2048 compare_headers_by_date (gconstpointer a,
2051 TnyHeader **header1, **header2;
2052 time_t sent1, sent2;
2054 header1 = (TnyHeader **) a;
2055 header2 = (TnyHeader **) b;
2057 sent1 = tny_header_get_date_sent (*header1);
2058 sent2 = tny_header_get_date_sent (*header2);
2060 /* We want the most recent ones (greater time_t) at the
2069 /* ******************************************************************* */
2070 /* ************************** STORE ACTIONS ************************* */
2071 /* ******************************************************************* */
2074 ModestMailOperation *mail_op;
2075 CreateFolderUserCallback callback;
2081 create_folder_cb (TnyFolderStore *parent_folder,
2083 TnyFolder *new_folder,
2087 ModestMailOperationPrivate *priv;
2088 CreateFolderInfo *info;
2090 info = (CreateFolderInfo *) user_data;
2091 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2093 if (canceled || err) {
2094 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2096 priv->error = g_error_copy (err);
2098 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2099 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2102 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2105 /* The user will unref the new_folder */
2107 info->callback (info->mail_op, parent_folder,
2108 new_folder, info->user_data);
2110 /* Notify about operation end */
2111 modest_mail_operation_notify_end (info->mail_op);
2114 g_object_unref (info->mail_op);
2115 g_slice_free (CreateFolderInfo, info);
2119 modest_mail_operation_create_folder (ModestMailOperation *self,
2120 TnyFolderStore *parent,
2122 CreateFolderUserCallback callback,
2125 ModestMailOperationPrivate *priv;
2127 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2128 g_return_if_fail (name);
2130 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2131 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2132 priv->account = (TNY_IS_ACCOUNT (parent)) ?
2133 g_object_ref (parent) :
2134 modest_tny_folder_get_account (TNY_FOLDER (parent));
2136 /* Check for already existing folder */
2137 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
2138 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2139 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2140 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2141 _CS("ckdg_ib_folder_already_exists"));
2145 if (TNY_IS_FOLDER (parent)) {
2146 /* Check folder rules */
2147 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2148 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2149 /* Set status failed and set an error */
2150 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2151 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2152 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2153 _("mail_in_ui_folder_create_error"));
2157 if (!priv->error && (!strcmp (name, " ") || strchr (name, '/'))) {
2158 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2159 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2160 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2161 _("mail_in_ui_folder_create_error"));
2165 CreateFolderInfo *info;
2167 info = g_slice_new0 (CreateFolderInfo);
2168 info->mail_op = g_object_ref (self);
2169 info->callback = callback;
2170 info->user_data = user_data;
2172 modest_mail_operation_notify_start (self);
2174 /* Create the folder */
2175 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
2178 /* Call the user callback anyway */
2180 callback (self, parent, NULL, user_data);
2181 /* Notify about operation end */
2182 modest_mail_operation_notify_end (self);
2187 modest_mail_operation_remove_folder (ModestMailOperation *self,
2189 gboolean remove_to_trash)
2191 ModestMailOperationPrivate *priv;
2192 ModestTnyFolderRules rules;
2194 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2195 g_return_if_fail (TNY_IS_FOLDER (folder));
2197 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2199 /* Check folder rules */
2200 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2201 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
2202 /* Set status failed and set an error */
2203 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2204 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2205 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2206 _("mail_in_ui_folder_delete_error"));
2210 /* Get the account */
2211 priv->account = modest_tny_folder_get_account (folder);
2212 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2214 /* Delete folder or move to trash */
2215 if (remove_to_trash) {
2216 TnyFolder *trash_folder = NULL;
2217 trash_folder = modest_tny_account_get_special_folder (priv->account,
2218 TNY_FOLDER_TYPE_TRASH);
2219 /* TODO: error_handling */
2221 modest_mail_operation_notify_start (self);
2222 modest_mail_operation_xfer_folder (self, folder,
2223 TNY_FOLDER_STORE (trash_folder),
2225 g_object_unref (trash_folder);
2227 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
2230 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
2232 modest_mail_operation_notify_start (self);
2233 tny_folder_store_remove_folder (parent, folder, &(priv->error));
2234 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
2237 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2239 g_object_unref (parent);
2241 g_warning ("%s: could not get parent folder", __FUNCTION__);
2245 /* Notify about operation end */
2246 modest_mail_operation_notify_end (self);
2250 transfer_folder_status_cb (GObject *obj,
2254 ModestMailOperation *self;
2255 ModestMailOperationPrivate *priv;
2256 ModestMailOperationState *state;
2257 XFerFolderAsyncHelper *helper;
2259 g_return_if_fail (status != NULL);
2261 /* Show only the status information we want */
2262 if (status->code != TNY_FOLDER_STATUS_CODE_COPY_FOLDER)
2265 helper = (XFerFolderAsyncHelper *) user_data;
2266 g_return_if_fail (helper != NULL);
2268 self = helper->mail_op;
2269 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2271 priv->done = status->position;
2272 priv->total = status->of_total;
2274 state = modest_mail_operation_clone_state (self);
2276 /* This is not a GDK lock because we are a Tinymail callback
2277 * which is already GDK locked by Tinymail */
2279 /* no gdk_threads_enter (), CHECKED */
2281 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2283 /* no gdk_threads_leave (), CHECKED */
2285 g_slice_free (ModestMailOperationState, state);
2289 transfer_folder_cb (TnyFolder *folder,
2291 TnyFolderStore *into,
2292 TnyFolder *new_folder,
2296 XFerFolderAsyncHelper *helper;
2297 ModestMailOperation *self = NULL;
2298 ModestMailOperationPrivate *priv = NULL;
2300 helper = (XFerFolderAsyncHelper *) user_data;
2301 g_return_if_fail (helper != NULL);
2303 self = helper->mail_op;
2304 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2307 priv->error = g_error_copy (err);
2309 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2310 } else if (cancelled) {
2311 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2312 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2313 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2314 _("Transference of %s was cancelled."),
2315 tny_folder_get_name (folder));
2318 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2321 /* Update state of new folder */
2323 tny_folder_refresh_async (new_folder, NULL, NULL, NULL);
2324 tny_folder_poke_status (new_folder);
2327 /* Notify about operation end */
2328 modest_mail_operation_notify_end (self);
2330 /* If user defined callback function was defined, call it */
2331 if (helper->user_callback) {
2333 /* This is not a GDK lock because we are a Tinymail callback
2334 * which is already GDK locked by Tinymail */
2336 /* no gdk_threads_enter (), CHECKED */
2337 helper->user_callback (self, new_folder, helper->user_data);
2338 /* no gdk_threads_leave () , CHECKED */
2342 g_object_unref (helper->mail_op);
2343 g_slice_free (XFerFolderAsyncHelper, helper);
2348 * This function checks if the new name is a valid name for our local
2349 * folders account. The new name could not be the same than then name
2350 * of any of the mandatory local folders
2352 * We can not rely on tinymail because tinymail does not check the
2353 * name of the virtual folders that the account could have in the case
2354 * that we're doing a rename (because it directly calls Camel which
2355 * knows nothing about our virtual folders).
2357 * In the case of an actual copy/move (i.e. move/copy a folder between
2358 * accounts) tinymail uses the tny_folder_store_create_account which
2359 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2360 * checks the new name of the folder, so this call in that case
2361 * wouldn't be needed. *But* NOTE that if tinymail changes its
2362 * implementation (if folder transfers within the same account is no
2363 * longer implemented as a rename) this call will allow Modest to work
2366 * If the new name is not valid, this function will set the status to
2367 * failed and will set also an error in the mail operation
2370 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2371 TnyFolderStore *into,
2372 const gchar *new_name)
2374 if (TNY_IS_ACCOUNT (into) &&
2375 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2376 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2378 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2379 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2380 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2381 _CS("ckdg_ib_folder_already_exists"));
2388 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2390 TnyFolderStore *parent,
2391 gboolean delete_original,
2392 XferFolderAsyncUserCallback user_callback,
2395 ModestMailOperationPrivate *priv = NULL;
2396 ModestTnyFolderRules parent_rules = 0, rules;
2397 XFerFolderAsyncHelper *helper = NULL;
2398 const gchar *folder_name = NULL;
2399 const gchar *error_msg;
2401 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2402 g_return_if_fail (TNY_IS_FOLDER (folder));
2403 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2405 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2406 folder_name = tny_folder_get_name (folder);
2408 /* Set the error msg */
2409 error_msg = _("mail_in_ui_folder_move_target_error");
2411 /* Get account and set it into mail_operation */
2412 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2413 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2414 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2416 /* Get folder rules */
2417 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2418 if (TNY_IS_FOLDER (parent))
2419 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2421 /* Apply operation constraints */
2422 if ((gpointer) parent == (gpointer) folder ||
2423 (!TNY_IS_FOLDER_STORE (parent)) ||
2424 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2427 } else if (TNY_IS_FOLDER (parent) &&
2428 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2432 } else if (TNY_IS_FOLDER (parent) &&
2433 TNY_IS_FOLDER_STORE (folder) &&
2434 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2435 TNY_FOLDER_STORE (folder))) {
2436 /* Do not move a parent into a child */
2438 } else if (TNY_IS_FOLDER_STORE (parent) &&
2439 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2440 /* Check that the new folder name is not used by any
2443 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2444 /* Check that the new folder name is not used by any
2445 special local folder */
2448 /* Create the helper */
2449 helper = g_slice_new0 (XFerFolderAsyncHelper);
2450 helper->mail_op = g_object_ref (self);
2451 helper->user_callback = user_callback;
2452 helper->user_data = user_data;
2454 /* Move/Copy folder */
2455 modest_mail_operation_notify_start (self);
2456 tny_folder_copy_async (folder,
2458 tny_folder_get_name (folder),
2461 transfer_folder_status_cb,
2467 /* Set status failed and set an error */
2468 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2469 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2470 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2473 /* Call the user callback if exists */
2475 user_callback (self, NULL, user_data);
2477 /* Notify the queue */
2478 modest_mail_operation_notify_end (self);
2482 modest_mail_operation_rename_folder (ModestMailOperation *self,
2485 XferFolderAsyncUserCallback user_callback,
2488 ModestMailOperationPrivate *priv;
2489 ModestTnyFolderRules rules;
2490 XFerFolderAsyncHelper *helper;
2492 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2493 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2494 g_return_if_fail (name);
2496 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2498 /* Get account and set it into mail_operation */
2499 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2500 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2502 /* Check folder rules */
2503 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2504 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2506 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2509 TnyFolderStore *into;
2511 into = tny_folder_get_folder_store (folder);
2513 /* Check that the new folder name is not used by any
2514 special local folder */
2515 if (new_name_valid_if_local_account (priv, into, name)) {
2516 /* Create the helper */
2517 helper = g_slice_new0 (XFerFolderAsyncHelper);
2518 helper->mail_op = g_object_ref(self);
2519 helper->user_callback = user_callback;
2520 helper->user_data = user_data;
2522 /* Rename. Camel handles folder subscription/unsubscription */
2523 modest_mail_operation_notify_start (self);
2524 tny_folder_copy_async (folder, into, name, TRUE,
2526 transfer_folder_status_cb,
2528 g_object_unref (into);
2530 g_object_unref (into);
2537 /* Set status failed and set an error */
2538 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2539 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2540 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2541 _("FIXME: unable to rename"));
2544 user_callback (self, NULL, user_data);
2546 /* Notify about operation end */
2547 modest_mail_operation_notify_end (self);
2550 /* ******************************************************************* */
2551 /* ************************** MSG ACTIONS ************************* */
2552 /* ******************************************************************* */
2555 modest_mail_operation_find_msg (ModestMailOperation *self,
2557 const gchar *msg_uid,
2558 gboolean progress_feedback,
2559 GetMsgAsyncUserCallback user_callback,
2562 GetMsgInfo *helper = NULL;
2563 ModestMailOperationPrivate *priv;
2565 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2566 g_return_if_fail (msg_uid != NULL);
2568 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2569 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2573 /* Check memory low */
2574 if (_check_memory_low (self)) {
2576 user_callback (self, NULL, FALSE, NULL, priv->error, user_data);
2577 modest_mail_operation_notify_end (self);
2581 /* Get account and set it into mail_operation */
2582 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2584 /* Check for cached messages */
2585 if (progress_feedback) {
2586 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2588 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2591 /* Create the helper */
2592 helper = g_slice_new0 (GetMsgInfo);
2593 helper->header = NULL;
2594 helper->mail_op = g_object_ref (self);
2595 helper->user_callback = user_callback;
2596 helper->user_data = user_data;
2597 helper->destroy_notify = NULL;
2598 helper->last_total_bytes = 0;
2599 helper->sum_total_bytes = 0;
2600 helper->total_bytes = 0;
2601 helper->more_msgs = NULL;
2603 modest_mail_operation_notify_start (self);
2605 /* notify about the start of the operation */
2606 ModestMailOperationState *state;
2607 state = modest_mail_operation_clone_state (self);
2610 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2612 g_slice_free (ModestMailOperationState, state);
2614 tny_folder_find_msg_async (folder, msg_uid, get_msg_async_cb, get_msg_status_cb, helper);
2618 modest_mail_operation_get_msg (ModestMailOperation *self,
2620 gboolean progress_feedback,
2621 GetMsgAsyncUserCallback user_callback,
2624 GetMsgInfo *helper = NULL;
2626 ModestMailOperationPrivate *priv;
2628 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2629 g_return_if_fail (TNY_IS_HEADER (header));
2631 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2632 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2636 /* Check memory low */
2637 if (_check_memory_low (self)) {
2639 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2640 modest_mail_operation_notify_end (self);
2644 /* Get account and set it into mail_operation */
2645 folder = tny_header_get_folder (header);
2646 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2648 /* Check for cached messages */
2649 if (progress_feedback) {
2650 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2651 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2653 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2655 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2658 /* Create the helper */
2659 helper = g_slice_new0 (GetMsgInfo);
2660 helper->header = g_object_ref (header);
2661 helper->mail_op = g_object_ref (self);
2662 helper->user_callback = user_callback;
2663 helper->user_data = user_data;
2664 helper->destroy_notify = NULL;
2665 helper->last_total_bytes = 0;
2666 helper->sum_total_bytes = 0;
2667 helper->total_bytes = tny_header_get_message_size (header);
2668 helper->more_msgs = NULL;
2670 modest_mail_operation_notify_start (self);
2672 /* notify about the start of the operation */
2673 ModestMailOperationState *state;
2674 state = modest_mail_operation_clone_state (self);
2677 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2679 g_slice_free (ModestMailOperationState, state);
2681 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2683 g_object_unref (G_OBJECT (folder));
2687 get_msg_status_cb (GObject *obj,
2691 GetMsgInfo *helper = NULL;
2693 g_return_if_fail (status != NULL);
2695 /* Show only the status information we want */
2696 if (status->code != TNY_FOLDER_STATUS_CODE_GET_MSG)
2699 helper = (GetMsgInfo *) user_data;
2700 g_return_if_fail (helper != NULL);
2702 /* Notify progress */
2703 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2704 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2708 get_msg_async_cb (TnyFolder *folder,
2714 GetMsgInfo *info = NULL;
2715 ModestMailOperationPrivate *priv = NULL;
2718 info = (GetMsgInfo *) user_data;
2720 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2723 if (info->more_msgs) {
2724 tny_iterator_next (info->more_msgs);
2725 finished = (tny_iterator_is_done (info->more_msgs));
2727 finished = (priv->done == priv->total) ? TRUE : FALSE;
2730 /* If canceled by the user, ignore the error given by Tinymail */
2734 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2736 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2737 priv->error = g_error_copy ((const GError *) err);
2739 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2741 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2742 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2743 "%s", err->message);
2745 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2746 /* Set the success status before calling the user callback */
2747 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2750 if (info->header == NULL && msg)
2751 info->header = tny_msg_get_header (msg);
2753 /* Call the user callback */
2754 if (info->user_callback)
2755 info->user_callback (info->mail_op, info->header, canceled,
2756 msg, err, info->user_data);
2758 /* Notify about operation end if this is the last callback */
2760 /* Free user data */
2761 if (info->destroy_notify)
2762 info->destroy_notify (info->user_data);
2764 /* Notify about operation end */
2765 modest_mail_operation_notify_end (info->mail_op);
2768 if (info->more_msgs)
2769 g_object_unref (info->more_msgs);
2771 g_object_unref (info->header);
2772 g_object_unref (info->mail_op);
2773 g_slice_free (GetMsgInfo, info);
2774 } else if (info->more_msgs) {
2775 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2776 TnyFolder *folder = tny_header_get_folder (header);
2778 g_object_unref (info->header);
2779 info->header = g_object_ref (header);
2781 /* Retrieve the next message */
2782 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2784 g_object_unref (header);
2785 g_object_unref (folder);
2787 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2792 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2793 TnyList *header_list,
2794 GetMsgAsyncUserCallback user_callback,
2796 GDestroyNotify notify)
2798 ModestMailOperationPrivate *priv = NULL;
2800 TnyIterator *iter = NULL;
2801 gboolean has_uncached_messages;
2803 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2805 /* Init mail operation */
2806 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2807 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2809 priv->total = tny_list_get_length(header_list);
2811 /* Check memory low */
2812 if (_check_memory_low (self)) {
2813 if (user_callback) {
2814 TnyHeader *header = NULL;
2817 if (tny_list_get_length (header_list) > 0) {
2818 iter = tny_list_create_iterator (header_list);
2819 header = (TnyHeader *) tny_iterator_get_current (iter);
2820 g_object_unref (iter);
2822 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2824 g_object_unref (header);
2828 /* Notify about operation end */
2829 modest_mail_operation_notify_end (self);
2833 /* Check uncached messages */
2834 for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
2835 !has_uncached_messages && !tny_iterator_is_done (iter);
2836 tny_iterator_next (iter)) {
2839 header = (TnyHeader *) tny_iterator_get_current (iter);
2840 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
2841 has_uncached_messages = TRUE;
2842 g_object_unref (header);
2844 g_object_unref (iter);
2845 priv->op_type = has_uncached_messages?MODEST_MAIL_OPERATION_TYPE_RECEIVE:MODEST_MAIL_OPERATION_TYPE_OPEN;
2847 /* Get account and set it into mail_operation */
2848 if (tny_list_get_length (header_list) >= 1) {
2849 TnyIterator *iterator = tny_list_create_iterator (header_list);
2850 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2852 TnyFolder *folder = tny_header_get_folder (header);
2854 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2855 g_object_unref (folder);
2857 g_object_unref (header);
2859 g_object_unref (iterator);
2862 msg_list_size = compute_message_list_size (header_list, 0);
2864 modest_mail_operation_notify_start (self);
2865 iter = tny_list_create_iterator (header_list);
2866 if (!tny_iterator_is_done (iter)) {
2867 /* notify about the start of the operation */
2868 ModestMailOperationState *state;
2869 state = modest_mail_operation_clone_state (self);
2872 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2875 GetMsgInfo *msg_info = NULL;
2876 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2877 TnyFolder *folder = tny_header_get_folder (header);
2879 /* Create the message info */
2880 msg_info = g_slice_new0 (GetMsgInfo);
2881 msg_info->mail_op = g_object_ref (self);
2882 msg_info->header = g_object_ref (header);
2883 msg_info->more_msgs = g_object_ref (iter);
2884 msg_info->user_callback = user_callback;
2885 msg_info->user_data = user_data;
2886 msg_info->destroy_notify = notify;
2887 msg_info->last_total_bytes = 0;
2888 msg_info->sum_total_bytes = 0;
2889 msg_info->total_bytes = msg_list_size;
2891 /* The callback will call it per each header */
2892 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2894 /* Free and go on */
2895 g_object_unref (header);
2896 g_object_unref (folder);
2897 g_slice_free (ModestMailOperationState, state);
2899 g_object_unref (iter);
2904 remove_msgs_async_cb (TnyFolder *folder,
2909 gboolean expunge, leave_on_server;
2910 const gchar *account_name;
2911 TnyAccount *account;
2912 ModestProtocolType account_proto = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2913 ModestMailOperation *self;
2914 ModestMailOperationPrivate *priv;
2915 ModestProtocolRegistry *protocol_registry;
2916 SyncFolderHelper *helper;
2918 self = (ModestMailOperation *) user_data;
2919 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2920 protocol_registry = modest_runtime_get_protocol_registry ();
2922 if (canceled || err) {
2923 /* If canceled by the user, ignore the error given by Tinymail */
2925 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2927 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2928 priv->error = g_error_copy ((const GError *) err);
2929 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2932 modest_mail_operation_notify_end (self);
2933 g_object_unref (self);
2937 account = modest_tny_folder_get_account (folder);
2938 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2940 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2942 account_proto = modest_tny_account_get_protocol_type (account);
2943 g_object_unref (account);
2945 if ((modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto) &&
2946 !leave_on_server) ||
2947 !modest_tny_folder_is_remote_folder (folder))
2953 helper = g_slice_new0 (SyncFolderHelper);
2954 helper->mail_op = g_object_ref (self);
2955 helper->user_callback = NULL;
2956 helper->user_data = NULL;
2959 tny_folder_sync_async(folder, expunge, sync_folder_finish_callback, NULL, helper);
2961 /* Remove the extra reference */
2962 g_object_unref (self);
2966 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2968 gboolean remove_to_trash /*ignored*/)
2970 TnyFolder *folder = NULL;
2971 ModestMailOperationPrivate *priv;
2972 TnyIterator *iter = NULL;
2973 TnyHeader *header = NULL;
2974 TnyList *remove_headers = NULL;
2975 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2976 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2978 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2979 g_return_if_fail (TNY_IS_LIST (headers));
2981 if (remove_to_trash)
2982 g_warning ("remove to trash is not implemented");
2984 if (tny_list_get_length(headers) == 0) {
2985 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2986 goto cleanup; /* nothing to do */
2989 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2991 /* Get folder from first header and sync it */
2992 iter = tny_list_create_iterator (headers);
2993 header = TNY_HEADER (tny_iterator_get_current (iter));
2994 g_object_unref (iter);
2996 folder = tny_header_get_folder (header);
2997 if (!TNY_IS_FOLDER(folder)) {
2998 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
3002 /* Use the merged folder if we're removing messages from outbox */
3003 if (modest_tny_folder_is_local_folder (folder)) {
3004 ModestTnyLocalFoldersAccount *local_account;
3006 local_account = (ModestTnyLocalFoldersAccount *)
3007 modest_tny_account_store_get_local_folders_account (accstore);
3008 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
3009 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3010 g_object_unref (folder);
3011 folder = modest_tny_local_folders_account_get_merged_outbox (local_account);
3013 g_object_unref (local_account);
3016 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3017 TnyIterator *headers_iter = tny_list_create_iterator (headers);
3019 while (!tny_iterator_is_done (headers_iter)) {
3020 TnyTransportAccount *traccount = NULL;
3021 TnyHeader *hdr = NULL;
3023 hdr = TNY_HEADER (tny_iterator_get_current (headers_iter));
3024 traccount = modest_tny_account_store_get_transport_account_from_outbox_header (accstore,
3027 ModestTnySendQueueStatus status;
3028 ModestTnySendQueue *send_queue;
3030 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
3031 if (TNY_IS_SEND_QUEUE (send_queue)) {
3034 msg_id = modest_tny_send_queue_get_msg_id (hdr);
3035 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
3036 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
3037 if (G_UNLIKELY (remove_headers == NULL))
3038 remove_headers = tny_simple_list_new ();
3039 tny_list_append(remove_headers, G_OBJECT(hdr));
3043 g_object_unref(traccount);
3045 g_object_unref(hdr);
3046 tny_iterator_next (headers_iter);
3048 g_object_unref(headers_iter);
3051 /* Get account and set it into mail_operation */
3052 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
3053 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
3054 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3056 if (!remove_headers)
3057 remove_headers = g_object_ref (headers);
3059 /* remove message from folder */
3060 modest_mail_operation_notify_start (self);
3061 tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb,
3062 NULL, g_object_ref (self));
3066 g_object_unref (remove_headers);
3068 g_object_unref (header);
3070 g_object_unref (folder);
3074 notify_progress_of_multiple_messages (ModestMailOperation *self,
3076 gint *last_total_bytes,
3077 gint *sum_total_bytes,
3079 gboolean increment_done)
3081 ModestMailOperationPrivate *priv;
3082 ModestMailOperationState *state;
3083 gboolean is_num_bytes = FALSE;
3085 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3087 /* We know that tinymail sends us information about
3088 * transferred bytes with this particular message
3090 if (status->message)
3091 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
3093 state = modest_mail_operation_clone_state (self);
3094 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
3095 /* We know that we're in a different message when the
3096 total number of bytes to transfer is different. Of
3097 course it could fail if we're transferring messages
3098 of the same size, but this is a workarround */
3099 if (status->of_total != *last_total_bytes) {
3100 /* We need to increment the done when there is
3101 no information about each individual
3102 message, we need to do this in message
3103 transfers, and we don't do it for getting
3107 *sum_total_bytes += *last_total_bytes;
3108 *last_total_bytes = status->of_total;
3110 state->bytes_done += status->position + *sum_total_bytes;
3111 state->bytes_total = total_bytes;
3113 /* Notify the status change. Only notify about changes
3114 referred to bytes */
3115 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3119 g_slice_free (ModestMailOperationState, state);
3123 transfer_msgs_status_cb (GObject *obj,
3127 XFerMsgsAsyncHelper *helper;
3129 g_return_if_fail (status != NULL);
3131 /* Show only the status information we want */
3132 if (status->code != TNY_FOLDER_STATUS_CODE_XFER_MSGS)
3135 helper = (XFerMsgsAsyncHelper *) user_data;
3136 g_return_if_fail (helper != NULL);
3138 /* Notify progress */
3139 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
3140 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
3144 transfer_msgs_sync_folder_cb (TnyFolder *self,
3149 XFerMsgsAsyncHelper *helper;
3150 /* We don't care here about the results of the
3152 helper = (XFerMsgsAsyncHelper *) user_data;
3154 /* Notify about operation end */
3155 modest_mail_operation_notify_end (helper->mail_op);
3157 /* If user defined callback function was defined, call it */
3158 if (helper->user_callback)
3159 helper->user_callback (helper->mail_op, helper->user_data);
3162 if (helper->more_msgs)
3163 g_object_unref (helper->more_msgs);
3164 if (helper->headers)
3165 g_object_unref (helper->headers);
3166 if (helper->dest_folder)
3167 g_object_unref (helper->dest_folder);
3168 if (helper->mail_op)
3169 g_object_unref (helper->mail_op);
3170 g_slice_free (XFerMsgsAsyncHelper, helper);
3174 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
3176 XFerMsgsAsyncHelper *helper;
3177 ModestMailOperation *self;
3178 ModestMailOperationPrivate *priv;
3179 gboolean finished = TRUE;
3181 helper = (XFerMsgsAsyncHelper *) user_data;
3182 self = helper->mail_op;
3184 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3187 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3189 priv->error = g_error_copy (err);
3191 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3192 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
3193 if (helper->more_msgs) {
3194 /* We'll transfer the next message in the list */
3195 tny_iterator_next (helper->more_msgs);
3196 if (!tny_iterator_is_done (helper->more_msgs)) {
3197 GObject *next_header;
3198 g_object_unref (helper->headers);
3199 helper->headers = tny_simple_list_new ();
3200 next_header = tny_iterator_get_current (helper->more_msgs);
3201 tny_list_append (helper->headers, next_header);
3202 g_object_unref (next_header);
3208 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3213 /* Synchronize the source folder contents. This should
3214 be done by tinymail but the camel_folder_sync it's
3215 actually disabled in transfer_msgs_thread_clean
3216 because it's supposed to cause hangs */
3217 tny_folder_sync_async (folder, helper->delete,
3218 transfer_msgs_sync_folder_cb,
3221 /* Transfer more messages */
3222 tny_folder_transfer_msgs_async (folder,
3224 helper->dest_folder,
3227 transfer_msgs_status_cb,
3232 /* Computes the size of the messages the headers in the list belongs
3233 to. If num_elements is different from 0 then it only takes into
3234 account the first num_elements for the calculation */
3236 compute_message_list_size (TnyList *headers,
3240 guint size = 0, element = 0;
3242 /* If num_elements is not valid then take all into account */
3243 if ((num_elements <= 0) || (num_elements > tny_list_get_length (headers)))
3244 num_elements = tny_list_get_length (headers);
3246 iter = tny_list_create_iterator (headers);
3247 while (!tny_iterator_is_done (iter) && element < num_elements) {
3248 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
3249 size += tny_header_get_message_size (header);
3250 g_object_unref (header);
3251 tny_iterator_next (iter);
3254 g_object_unref (iter);
3260 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
3263 gboolean delete_original,
3264 XferMsgsAsyncUserCallback user_callback,
3267 ModestMailOperationPrivate *priv = NULL;
3268 TnyIterator *iter = NULL;
3269 TnyFolder *src_folder = NULL;
3270 XFerMsgsAsyncHelper *helper = NULL;
3271 TnyHeader *header = NULL;
3272 ModestTnyFolderRules rules = 0;
3273 TnyAccount *dst_account = NULL;
3274 gboolean leave_on_server;
3275 ModestMailOperationState *state;
3276 ModestProtocolRegistry *protocol_registry;
3277 ModestProtocolType account_protocol;
3279 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
3280 g_return_if_fail (headers && TNY_IS_LIST (headers));
3281 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
3283 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3284 protocol_registry = modest_runtime_get_protocol_registry ();
3286 priv->total = tny_list_get_length (headers);
3288 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3289 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3291 /* Apply folder rules */
3292 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
3293 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3294 /* Set status failed and set an error */
3295 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3296 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3297 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
3298 _CS("ckct_ib_unable_to_paste_here"));
3299 /* Notify the queue */
3300 modest_mail_operation_notify_end (self);
3304 /* Get source folder */
3305 iter = tny_list_create_iterator (headers);
3306 header = TNY_HEADER (tny_iterator_get_current (iter));
3308 src_folder = tny_header_get_folder (header);
3309 g_object_unref (header);
3311 g_object_unref (iter);
3313 if (src_folder == NULL) {
3314 /* Notify the queue */
3315 modest_mail_operation_notify_end (self);
3317 g_warning ("%s: cannot find folder from header", __FUNCTION__);
3322 /* Check folder source and destination */
3323 if (src_folder == folder) {
3324 /* Set status failed and set an error */
3325 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3326 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3327 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
3328 _("mail_in_ui_folder_copy_target_error"));
3330 /* Notify the queue */
3331 modest_mail_operation_notify_end (self);
3334 g_object_unref (src_folder);
3338 /* Create the helper */
3339 helper = g_slice_new0 (XFerMsgsAsyncHelper);
3340 helper->mail_op = g_object_ref(self);
3341 helper->dest_folder = g_object_ref(folder);
3342 helper->user_callback = user_callback;
3343 helper->user_data = user_data;
3344 helper->last_total_bytes = 0;
3345 helper->sum_total_bytes = 0;
3346 helper->total_bytes = compute_message_list_size (headers, 0);
3348 /* Get account and set it into mail_operation */
3349 priv->account = modest_tny_folder_get_account (src_folder);
3350 dst_account = modest_tny_folder_get_account (folder);
3352 if (priv->account == dst_account) {
3353 /* Transfer all messages at once using the fast
3354 * method. Note that depending on the server this
3355 * might not be that fast, and might not be
3356 * user-cancellable either */
3357 helper->headers = g_object_ref (headers);
3358 helper->more_msgs = NULL;
3360 /* Transfer messages one by one so the user can cancel
3363 helper->headers = tny_simple_list_new ();
3364 helper->more_msgs = tny_list_create_iterator (headers);
3365 hdr = tny_iterator_get_current (helper->more_msgs);
3366 tny_list_append (helper->headers, hdr);
3367 g_object_unref (hdr);
3370 /* If leave_on_server is set to TRUE then don't use
3371 delete_original, we always pass FALSE. This is because
3372 otherwise tinymail will try to sync the source folder and
3373 this could cause an error if we're offline while
3374 transferring an already downloaded message from a POP
3376 account_protocol = modest_tny_account_get_protocol_type (priv->account);
3377 if (modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_protocol)) {
3378 const gchar *account_name;
3380 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
3381 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
3384 leave_on_server = FALSE;
3387 /* Do not delete messages if leave on server is TRUE */
3388 helper->delete = (leave_on_server) ? FALSE : delete_original;
3390 modest_mail_operation_notify_start (self);
3392 /* Start notifying progress */
3393 state = modest_mail_operation_clone_state (self);
3396 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3397 g_slice_free (ModestMailOperationState, state);
3399 tny_folder_transfer_msgs_async (src_folder,
3404 transfer_msgs_status_cb,
3406 g_object_unref (src_folder);
3407 g_object_unref (dst_account);
3412 on_refresh_folder (TnyFolder *folder,
3417 RefreshAsyncHelper *helper = NULL;
3418 ModestMailOperation *self = NULL;
3419 ModestMailOperationPrivate *priv = NULL;
3421 helper = (RefreshAsyncHelper *) user_data;
3422 self = helper->mail_op;
3423 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3425 g_return_if_fail(priv!=NULL);
3428 priv->error = g_error_copy (error);
3429 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3434 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3435 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3436 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
3437 _("Error trying to refresh the contents of %s"),
3438 tny_folder_get_name (folder));
3442 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3445 /* Call user defined callback, if it exists */
3446 if (helper->user_callback) {
3448 /* This is not a GDK lock because we are a Tinymail callback and
3449 * Tinymail already acquires the Gdk lock */
3450 helper->user_callback (self, folder, helper->user_data);
3454 g_slice_free (RefreshAsyncHelper, helper);
3456 /* Notify about operation end */
3457 modest_mail_operation_notify_end (self);
3458 g_object_unref(self);
3462 on_refresh_folder_status_update (GObject *obj,
3466 RefreshAsyncHelper *helper = NULL;
3467 ModestMailOperation *self = NULL;
3468 ModestMailOperationPrivate *priv = NULL;
3469 ModestMailOperationState *state;
3471 g_return_if_fail (user_data != NULL);
3472 g_return_if_fail (status != NULL);
3474 /* Show only the status information we want */
3475 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
3478 helper = (RefreshAsyncHelper *) user_data;
3479 self = helper->mail_op;
3480 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
3482 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3484 priv->done = status->position;
3485 priv->total = status->of_total;
3487 state = modest_mail_operation_clone_state (self);
3489 /* This is not a GDK lock because we are a Tinymail callback and
3490 * Tinymail already acquires the Gdk lock */
3491 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3493 g_slice_free (ModestMailOperationState, state);
3497 modest_mail_operation_refresh_folder (ModestMailOperation *self,
3499 RefreshAsyncUserCallback user_callback,
3502 ModestMailOperationPrivate *priv = NULL;
3503 RefreshAsyncHelper *helper = NULL;
3505 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3507 /* Check memory low */
3508 if (_check_memory_low (self)) {
3510 user_callback (self, folder, user_data);
3511 /* Notify about operation end */
3512 modest_mail_operation_notify_end (self);
3516 /* Get account and set it into mail_operation */
3517 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3518 priv->account = modest_tny_folder_get_account (folder);
3519 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3521 /* Create the helper */
3522 helper = g_slice_new0 (RefreshAsyncHelper);
3523 helper->mail_op = g_object_ref(self);
3524 helper->user_callback = user_callback;
3525 helper->user_data = user_data;
3527 modest_mail_operation_notify_start (self);
3529 /* notify that the operation was started */
3530 ModestMailOperationState *state;
3531 state = modest_mail_operation_clone_state (self);
3534 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3536 g_slice_free (ModestMailOperationState, state);
3538 tny_folder_refresh_async (folder,
3540 on_refresh_folder_status_update,
3545 run_queue_notify_and_destroy (RunQueueHelper *helper,
3546 ModestMailOperationStatus status)
3548 ModestMailOperationPrivate *priv;
3551 if (helper->error_handler &&
3552 g_signal_handler_is_connected (helper->queue, helper->error_handler))
3553 g_signal_handler_disconnect (helper->queue, helper->error_handler);
3554 if (helper->start_handler &&
3555 g_signal_handler_is_connected (helper->queue, helper->start_handler))
3556 g_signal_handler_disconnect (helper->queue, helper->start_handler);
3557 if (helper->stop_handler &&
3558 g_signal_handler_is_connected (helper->queue, helper->stop_handler))
3559 g_signal_handler_disconnect (helper->queue, helper->stop_handler);
3562 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
3563 priv->status = status;
3566 modest_mail_operation_notify_end (helper->self);
3569 g_object_unref (helper->queue);
3570 g_object_unref (helper->self);
3571 g_slice_free (RunQueueHelper, helper);
3575 run_queue_stop (ModestTnySendQueue *queue,
3578 RunQueueHelper *helper;
3580 g_debug ("%s sending queue stopped", __FUNCTION__);
3582 helper = (RunQueueHelper *) user_data;
3583 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
3587 modest_mail_operation_run_queue (ModestMailOperation *self,
3588 ModestTnySendQueue *queue)
3590 ModestMailOperationPrivate *priv;
3591 RunQueueHelper *helper;
3593 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3594 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3595 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3597 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3598 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3599 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
3601 /* Create the helper */
3602 helper = g_slice_new0 (RunQueueHelper);
3603 helper->queue = g_object_ref (queue);
3604 helper->self = g_object_ref (self);
3605 helper->stop_handler = g_signal_connect (queue, "queue-stop",
3606 G_CALLBACK (run_queue_stop),
3609 /* Notify operation has started */
3610 modest_mail_operation_notify_start (self);
3611 g_debug ("%s, run queue started", __FUNCTION__);
3615 queue_wakeup_callback (ModestTnySendQueue *queue,
3620 ModestMailOperation *mail_op;
3621 ModestMailOperationPrivate *priv;
3623 mail_op = (ModestMailOperation *) userdata;
3624 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3626 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3627 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (queue));
3630 modest_mail_operation_notify_end (mail_op);
3631 g_object_unref (mail_op);
3635 modest_mail_operation_queue_wakeup (ModestMailOperation *self,
3636 ModestTnySendQueue *queue)
3638 ModestMailOperationPrivate *priv;
3640 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3641 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3642 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3644 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3645 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3646 priv->op_type = MODEST_MAIL_OPERATION_TYPE_QUEUE_WAKEUP;
3648 g_object_ref (self);
3650 modest_tny_send_queue_wakeup (queue, queue_wakeup_callback, self);
3651 modest_mail_operation_notify_start (self);
3655 shutdown_callback (ModestTnyAccountStore *account_store, gpointer userdata)
3657 ModestMailOperation *self = (ModestMailOperation *) userdata;
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 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3666 modest_mail_operation_notify_end (self);
3667 g_object_unref (self);
3671 modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore *account_store)
3673 ModestMailOperationPrivate *priv;
3675 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3676 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3677 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3679 modest_mail_operation_queue_set_running_shutdown (modest_runtime_get_mail_operation_queue ());
3681 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3682 priv->account = NULL;
3683 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SHUTDOWN;
3685 modest_mail_operation_notify_start (self);
3686 g_object_ref (self);
3687 modest_tny_account_store_shutdown (account_store, shutdown_callback, self);
3691 sync_folder_finish_callback (TnyFolder *self,
3697 ModestMailOperationPrivate *priv;
3698 SyncFolderHelper *helper;
3700 helper = (SyncFolderHelper *) user_data;
3701 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->mail_op);
3703 /* If canceled by the user, ignore the error given by Tinymail */
3705 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3707 /* If the operation was a sync then the status is
3708 failed, but if it's part of another operation then
3709 just set it as finished with errors */
3710 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
3711 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3713 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
3714 priv->error = g_error_copy ((const GError *) err);
3715 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
3717 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3721 if (helper->user_callback)
3722 helper->user_callback (helper->mail_op, self, helper->user_data);
3724 modest_mail_operation_notify_end (helper->mail_op);
3727 g_object_unref (helper->mail_op);
3728 g_slice_free (SyncFolderHelper, helper);
3732 modest_mail_operation_sync_folder (ModestMailOperation *self,
3735 SyncFolderCallback callback,
3738 ModestMailOperationPrivate *priv;
3739 SyncFolderHelper *helper;
3741 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3742 g_return_if_fail (TNY_IS_FOLDER (folder));
3743 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3745 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3746 priv->account = modest_tny_folder_get_account (folder);
3747 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3750 helper = g_slice_new0 (SyncFolderHelper);
3751 helper->mail_op = g_object_ref (self);
3752 helper->user_callback = callback;
3753 helper->user_data = user_data;
3755 modest_mail_operation_notify_start (self);
3756 tny_folder_sync_async (folder, expunge,
3757 (TnyFolderCallback) sync_folder_finish_callback,
3762 modest_mail_operation_notify_start (ModestMailOperation *self)
3764 ModestMailOperationPrivate *priv = NULL;
3766 g_return_if_fail (self);
3768 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3770 /* Ensure that all the fields are filled correctly */
3771 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3773 /* Notify the observers about the mail operation. We do not
3774 wrapp this emission because we assume that this function is
3775 always called from within the main lock */
3776 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3781 * It's used by the mail operation queue to notify the observers
3782 * attached to that signal that the operation finished. We need to use
3783 * that because tinymail does not give us the progress of a given
3784 * operation when it finishes (it directly calls the operation
3788 modest_mail_operation_notify_end (ModestMailOperation *self)
3790 ModestMailOperationPrivate *priv = NULL;
3792 g_return_if_fail (self);
3794 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3796 /* Notify the observers about the mail operation end. We do
3797 not wrapp this emission because we assume that this
3798 function is always called from within the main lock */
3799 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3801 /* Remove the error user data */
3802 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3803 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3807 modest_mail_operation_get_account (ModestMailOperation *self)
3809 ModestMailOperationPrivate *priv = NULL;
3811 g_return_val_if_fail (self, NULL);
3813 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3815 return (priv->account) ? g_object_ref (priv->account) : NULL;
3819 modest_mail_operation_noop (ModestMailOperation *self)
3821 ModestMailOperationPrivate *priv = NULL;
3823 g_return_if_fail (self);
3825 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3826 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3827 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3831 /* This mail operation does nothing actually */
3832 modest_mail_operation_notify_start (self);
3833 modest_mail_operation_notify_end (self);
3838 modest_mail_operation_to_string (ModestMailOperation *self)
3840 const gchar *type, *status, *account_id;
3841 ModestMailOperationPrivate *priv = NULL;
3843 g_return_val_if_fail (self, NULL);
3845 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3847 /* new operations don't have anything interesting */
3848 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3849 return g_strdup_printf ("%p <new operation>", self);
3851 switch (priv->op_type) {
3852 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3853 case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE: type= "SEND-AND-RECEIVE"; break;
3854 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3855 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3856 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3857 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3858 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3859 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3860 case MODEST_MAIL_OPERATION_TYPE_SHUTDOWN: type= "SHUTDOWN"; break;
3861 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3862 default: type = "UNEXPECTED"; break;
3865 switch (priv->status) {
3866 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3867 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3868 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3869 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3870 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3871 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3872 default: status= "UNEXPECTED"; break;
3875 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3877 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3878 priv->done, priv->total,
3879 priv->error && priv->error->message ? priv->error->message : "");
3883 * Once the mail operations were objects this will be no longer
3884 * needed. I don't like it, but we need it for the moment
3887 _check_memory_low (ModestMailOperation *mail_op)
3889 if (modest_platform_check_memory_low (NULL, FALSE)) {
3890 ModestMailOperationPrivate *priv;
3892 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3893 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3894 g_set_error (&(priv->error),
3895 MODEST_MAIL_OPERATION_ERROR,
3896 MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY,
3897 "Not enough memory to complete the operation");