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-simple-list.h>
41 #include <tny-send-queue.h>
42 #include <tny-status.h>
43 #include <tny-folder-observer.h>
44 #include <camel/camel-stream-mem.h>
45 #include <glib/gi18n.h>
46 #include "modest-platform.h"
47 #include <modest-tny-account.h>
48 #include <modest-tny-send-queue.h>
49 #include <modest-runtime.h>
50 #include "modest-text-utils.h"
51 #include "modest-tny-msg.h"
52 #include "modest-tny-folder.h"
53 #include "modest-tny-platform-factory.h"
54 #include "modest-marshal.h"
55 #include "modest-error.h"
56 #include "modest-mail-operation.h"
60 /* 'private'/'protected' functions */
61 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
62 static void modest_mail_operation_init (ModestMailOperation *obj);
63 static void modest_mail_operation_finalize (GObject *obj);
65 static void get_msg_cb (TnyFolder *folder,
71 static void get_msg_status_cb (GObject *obj,
75 static void modest_mail_operation_notify_end (ModestMailOperation *self);
77 static gboolean did_a_cancel = FALSE;
79 enum _ModestMailOperationSignals
81 PROGRESS_CHANGED_SIGNAL,
86 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
87 struct _ModestMailOperationPrivate {
94 ErrorCheckingUserCallback error_checking;
95 gpointer error_checking_user_data;
96 ModestMailOperationStatus status;
97 ModestMailOperationTypeOperation op_type;
100 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
101 MODEST_TYPE_MAIL_OPERATION, \
102 ModestMailOperationPrivate))
104 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
105 priv->status = new_status;\
108 typedef struct _GetMsgAsyncHelper {
109 ModestMailOperation *mail_op;
111 GetMsgAsyncUserCallback user_callback;
115 typedef struct _RefreshAsyncHelper {
116 ModestMailOperation *mail_op;
117 RefreshAsyncUserCallback user_callback;
119 } RefreshAsyncHelper;
121 typedef struct _XFerMsgAsyncHelper
123 ModestMailOperation *mail_op;
125 TnyFolder *dest_folder;
126 XferMsgsAsynUserCallback user_callback;
128 } XFerMsgAsyncHelper;
131 static GObjectClass *parent_class = NULL;
133 static guint signals[NUM_SIGNALS] = {0};
136 modest_mail_operation_get_type (void)
138 static GType my_type = 0;
140 static const GTypeInfo my_info = {
141 sizeof(ModestMailOperationClass),
142 NULL, /* base init */
143 NULL, /* base finalize */
144 (GClassInitFunc) modest_mail_operation_class_init,
145 NULL, /* class finalize */
146 NULL, /* class data */
147 sizeof(ModestMailOperation),
149 (GInstanceInitFunc) modest_mail_operation_init,
152 my_type = g_type_register_static (G_TYPE_OBJECT,
153 "ModestMailOperation",
160 modest_mail_operation_class_init (ModestMailOperationClass *klass)
162 GObjectClass *gobject_class;
163 gobject_class = (GObjectClass*) klass;
165 parent_class = g_type_class_peek_parent (klass);
166 gobject_class->finalize = modest_mail_operation_finalize;
168 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
171 * ModestMailOperation::progress-changed
172 * @self: the #MailOperation that emits the signal
173 * @user_data: user data set when the signal handler was connected
175 * Emitted when the progress of a mail operation changes
177 signals[PROGRESS_CHANGED_SIGNAL] =
178 g_signal_new ("progress-changed",
179 G_TYPE_FROM_CLASS (gobject_class),
181 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
183 g_cclosure_marshal_VOID__POINTER,
184 G_TYPE_NONE, 1, G_TYPE_POINTER);
189 modest_mail_operation_init (ModestMailOperation *obj)
191 ModestMailOperationPrivate *priv;
193 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
195 priv->account = NULL;
196 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
197 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
202 priv->error_checking = NULL;
203 priv->error_checking_user_data = NULL;
207 modest_mail_operation_finalize (GObject *obj)
209 ModestMailOperationPrivate *priv;
211 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
216 g_error_free (priv->error);
220 g_object_unref (priv->source);
224 g_object_unref (priv->account);
225 priv->account = NULL;
229 G_OBJECT_CLASS(parent_class)->finalize (obj);
233 modest_mail_operation_new (ModestMailOperationTypeOperation op_type,
236 ModestMailOperation *obj;
237 ModestMailOperationPrivate *priv;
239 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
240 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
242 priv->op_type = op_type;
244 priv->source = g_object_ref(source);
250 modest_mail_operation_new_with_error_handling (ModestMailOperationTypeOperation op_type,
252 ErrorCheckingUserCallback error_handler,
255 ModestMailOperation *obj;
256 ModestMailOperationPrivate *priv;
258 obj = modest_mail_operation_new (op_type, source);
259 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
261 g_return_val_if_fail (error_handler != NULL, obj);
262 priv->error_checking = error_handler;
268 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
270 ModestMailOperationPrivate *priv;
272 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
273 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
275 if (priv->error_checking != NULL)
276 priv->error_checking (self, priv->error_checking_user_data);
280 ModestMailOperationTypeOperation
281 modest_mail_operation_get_type_operation (ModestMailOperation *self)
283 ModestMailOperationPrivate *priv;
285 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
287 return priv->op_type;
291 modest_mail_operation_is_mine (ModestMailOperation *self,
294 ModestMailOperationPrivate *priv;
296 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
297 if (priv->source == NULL) return FALSE;
299 return priv->source == me;
303 modest_mail_operation_get_source (ModestMailOperation *self)
305 ModestMailOperationPrivate *priv;
307 g_return_val_if_fail (self, NULL);
309 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
311 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
315 return g_object_ref (priv->source);
318 ModestMailOperationStatus
319 modest_mail_operation_get_status (ModestMailOperation *self)
321 ModestMailOperationPrivate *priv;
323 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
324 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
325 MODEST_MAIL_OPERATION_STATUS_INVALID);
327 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
329 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
330 return MODEST_MAIL_OPERATION_STATUS_INVALID;
337 modest_mail_operation_get_error (ModestMailOperation *self)
339 ModestMailOperationPrivate *priv;
341 g_return_val_if_fail (self, NULL);
342 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
344 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
347 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
355 modest_mail_operation_cancel (ModestMailOperation *self)
357 ModestMailOperationPrivate *priv;
359 if (!MODEST_IS_MAIL_OPERATION (self)) {
360 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
364 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
366 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
373 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
375 /* This emits progress-changed on which the mail operation queue is
376 * listening, so the mail operation is correctly removed from the
377 * queue without further explicit calls. */
378 modest_mail_operation_notify_end (self);
384 modest_mail_operation_get_task_done (ModestMailOperation *self)
386 ModestMailOperationPrivate *priv;
388 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
390 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
395 modest_mail_operation_get_task_total (ModestMailOperation *self)
397 ModestMailOperationPrivate *priv;
399 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
401 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
406 modest_mail_operation_is_finished (ModestMailOperation *self)
408 ModestMailOperationPrivate *priv;
409 gboolean retval = FALSE;
411 if (!MODEST_IS_MAIL_OPERATION (self)) {
412 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
416 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
418 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
419 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
420 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
421 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
431 modest_mail_operation_get_id (ModestMailOperation *self)
433 ModestMailOperationPrivate *priv;
435 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
437 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
442 modest_mail_operation_set_id (ModestMailOperation *self,
445 ModestMailOperationPrivate *priv;
447 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
449 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
454 * Creates an image of the current state of a mail operation, the
455 * caller must free it
457 static ModestMailOperationState *
458 modest_mail_operation_clone_state (ModestMailOperation *self)
460 ModestMailOperationState *state;
461 ModestMailOperationPrivate *priv;
463 /* FIXME: this should be fixed properly
465 * in some cases, priv was NULL, so checking here to
468 g_return_val_if_fail (self, NULL);
469 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
470 g_return_val_if_fail (priv, NULL);
475 state = g_slice_new (ModestMailOperationState);
477 state->status = priv->status;
478 state->op_type = priv->op_type;
479 state->done = priv->done;
480 state->total = priv->total;
481 state->finished = modest_mail_operation_is_finished (self);
482 state->bytes_done = 0;
483 state->bytes_total = 0;
488 /* ******************************************************************* */
489 /* ************************** SEND ACTIONS ************************* */
490 /* ******************************************************************* */
493 modest_mail_operation_send_mail (ModestMailOperation *self,
494 TnyTransportAccount *transport_account,
497 TnySendQueue *send_queue = NULL;
498 ModestMailOperationPrivate *priv;
500 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
501 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
502 g_return_if_fail (TNY_IS_MSG (msg));
504 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
506 /* Get account and set it into mail_operation */
507 priv->account = g_object_ref (transport_account);
511 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
512 if (!TNY_IS_SEND_QUEUE(send_queue)) {
513 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
514 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
515 "modest: could not find send queue for account\n");
517 /* TODO: connect to the msg-sent in order to know when
518 the mail operation is finished */
519 tny_send_queue_add (send_queue, msg, &(priv->error));
520 /* TODO: we're setting always success, do the check in
522 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
525 /* TODO: do this in the handler of the "msg-sent"
526 signal.Notify about operation end */
527 modest_mail_operation_notify_end (self);
531 modest_mail_operation_send_new_mail (ModestMailOperation *self,
532 TnyTransportAccount *transport_account,
534 const gchar *from, const gchar *to,
535 const gchar *cc, const gchar *bcc,
536 const gchar *subject, const gchar *plain_body,
537 const gchar *html_body,
538 const GList *attachments_list,
539 TnyHeaderFlags priority_flags)
541 TnyMsg *new_msg = NULL;
542 TnyFolder *folder = NULL;
543 TnyHeader *header = NULL;
544 ModestMailOperationPrivate *priv = NULL;
546 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
547 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
549 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
551 /* Check parametters */
553 /* Set status failed and set an error */
554 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
555 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
556 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
557 _("Error trying to send a mail. You need to set at least one recipient"));
561 if (html_body == NULL) {
562 new_msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
564 new_msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
567 g_printerr ("modest: failed to create a new msg\n");
571 /* Set priority flags in message */
572 header = tny_msg_get_header (new_msg);
573 if (priority_flags != 0)
574 tny_header_set_flags (header, priority_flags);
575 g_object_unref (G_OBJECT(header));
577 /* Call mail operation */
578 modest_mail_operation_send_mail (self, transport_account, new_msg);
580 folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
582 if (draft_msg != NULL) {
583 header = tny_msg_get_header (draft_msg);
584 /* Note: This can fail (with a warning) if the message is not really already in a folder,
585 * because this function requires it to have a UID. */
586 tny_folder_remove_msg (folder, header, NULL);
587 tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED);
588 g_object_unref (header);
593 g_object_unref (G_OBJECT (new_msg));
597 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
598 TnyTransportAccount *transport_account,
600 const gchar *from, const gchar *to,
601 const gchar *cc, const gchar *bcc,
602 const gchar *subject, const gchar *plain_body,
603 const gchar *html_body,
604 const GList *attachments_list,
605 TnyHeaderFlags priority_flags)
608 TnyFolder *folder = NULL;
609 TnyHeader *header = NULL;
610 ModestMailOperationPrivate *priv = NULL;
612 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
613 g_return_val_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account), NULL);
615 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
617 /* Get account and set it into mail_operation */
618 priv->account = g_object_ref (transport_account);
620 if (html_body == NULL) {
621 msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
623 msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
626 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
627 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
628 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
629 "modest: failed to create a new msg\n");
633 /* add priority flags */
634 header = tny_msg_get_header (msg);
635 tny_header_set_flags (header, priority_flags);
636 g_object_unref (G_OBJECT(header));
638 folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
640 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
641 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
642 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
643 "modest: failed to create a new msg\n");
647 if (draft_msg != NULL) {
648 header = tny_msg_get_header (draft_msg);
649 /* Remove the old draft expunging it */
650 tny_folder_remove_msg (folder, header, NULL);
651 tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED);
652 tny_folder_sync (folder, FALSE, &(priv->error)); /* FALSE --> don't expunge */
653 g_object_unref (header);
657 tny_folder_add_msg (folder, msg, &(priv->error));
660 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
662 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
666 g_object_unref (G_OBJECT(folder));
668 modest_mail_operation_notify_end (self);
674 ModestMailOperation *mail_op;
675 TnyStoreAccount *account;
676 TnyTransportAccount *transport_account;
679 gchar *retrieve_type;
681 UpdateAccountCallback callback;
686 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
687 /* We use this folder observer to track the headers that have been
688 * added to a folder */
691 TnyList *new_headers;
692 } InternalFolderObserver;
696 } InternalFolderObserverClass;
698 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
700 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
701 internal_folder_observer,
703 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
707 foreach_add_item (gpointer header, gpointer user_data)
709 /* printf("DEBUG: %s: header subject=%s\n",
710 * __FUNCTION__, tny_header_get_subject(TNY_HEADER(header)));
712 tny_list_prepend (TNY_LIST (user_data),
713 g_object_ref (G_OBJECT (header)));
716 /* This is the method that looks for new messages in a folder */
718 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
720 InternalFolderObserver *derived = (InternalFolderObserver *)self;
722 TnyFolderChangeChanged changed;
724 changed = tny_folder_change_get_changed (change);
726 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
729 /* Get added headers */
730 list = tny_simple_list_new ();
731 tny_folder_change_get_added_headers (change, list);
733 /* printf ("DEBUG: %s: Calling foreach with a list of size=%d\n",
734 * __FUNCTION__, tny_list_get_length(list));
737 /* Add them to the folder observer */
738 tny_list_foreach (list, foreach_add_item,
739 derived->new_headers);
741 g_object_unref (G_OBJECT (list));
746 internal_folder_observer_init (InternalFolderObserver *self)
748 self->new_headers = tny_simple_list_new ();
751 internal_folder_observer_finalize (GObject *object)
753 InternalFolderObserver *self;
755 self = (InternalFolderObserver *) object;
756 g_object_unref (self->new_headers);
758 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
761 tny_folder_observer_init (TnyFolderObserverIface *iface)
763 iface->update_func = internal_folder_observer_update;
766 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
768 GObjectClass *object_class;
770 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
771 object_class = (GObjectClass*) klass;
772 object_class->finalize = internal_folder_observer_finalize;
778 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
781 TnyList *folders = tny_simple_list_new ();
783 tny_folder_store_get_folders (store, folders, query, NULL);
784 iter = tny_list_create_iterator (folders);
786 while (!tny_iterator_is_done (iter)) {
788 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
790 tny_list_prepend (all_folders, G_OBJECT (folder));
791 recurse_folders (folder, query, all_folders);
792 g_object_unref (G_OBJECT (folder));
794 tny_iterator_next (iter);
796 g_object_unref (G_OBJECT (iter));
797 g_object_unref (G_OBJECT (folders));
801 * Issues the "progress-changed" signal. The timer won't be removed,
802 * so you must call g_source_remove to stop the signal emission
805 idle_notify_progress (gpointer data)
807 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
808 ModestMailOperationState *state;
810 state = modest_mail_operation_clone_state (mail_op);
811 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
812 g_slice_free (ModestMailOperationState, state);
818 * Issues the "progress-changed" signal and removes the timer. It uses
819 * a lock to ensure that the progress information of the mail
820 * operation is not modified while there are notifications pending
823 idle_notify_progress_once (gpointer data)
827 pair = (ModestPair *) data;
829 g_signal_emit (G_OBJECT (pair->first), signals[PROGRESS_CHANGED_SIGNAL], 0, pair->second, NULL);
831 /* Free the state and the reference to the mail operation */
832 g_slice_free (ModestMailOperationState, (ModestMailOperationState*)pair->second);
833 g_object_unref (pair->first);
839 * Used by update_account_thread to notify the queue from the main
840 * loop. We call it inside an idle call to achieve that
843 idle_notify_update_account_queue (gpointer data)
845 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
846 ModestMailOperationPrivate *priv = NULL;
848 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_op);
850 /* Do not need to block, the notify end will do it for us */
851 modest_mail_operation_notify_end (mail_op);
852 g_object_unref (mail_op);
858 compare_headers_by_date (gconstpointer a,
861 TnyHeader **header1, **header2;
864 header1 = (TnyHeader **) a;
865 header2 = (TnyHeader **) b;
867 sent1 = tny_header_get_date_sent (*header1);
868 sent2 = tny_header_get_date_sent (*header2);
870 /* We want the most recent ones (greater time_t) at the
879 set_last_updated_idle (gpointer data)
881 gdk_threads_enter ();
883 /* It does not matter if the time is not exactly the same than
884 the time when this idle was called, it's just an
885 approximation and it won't be very different */
886 modest_account_mgr_set_int (modest_runtime_get_account_mgr (),
888 MODEST_ACCOUNT_LAST_UPDATED,
892 gdk_threads_leave ();
898 idle_update_account_cb (gpointer data)
900 UpdateAccountInfo *idle_info;
902 idle_info = (UpdateAccountInfo *) data;
904 gdk_threads_enter ();
905 idle_info->callback (idle_info->mail_op,
906 idle_info->new_headers,
907 idle_info->user_data);
908 gdk_threads_leave ();
911 g_object_unref (idle_info->mail_op);
919 update_account_thread (gpointer thr_user_data)
921 static gboolean first_time = TRUE;
922 UpdateAccountInfo *info;
923 TnyList *all_folders = NULL;
924 GPtrArray *new_headers = NULL;
925 TnyIterator *iter = NULL;
926 TnyFolderStoreQuery *query = NULL;
927 ModestMailOperationPrivate *priv = NULL;
928 ModestTnySendQueue *send_queue = NULL;
930 info = (UpdateAccountInfo *) thr_user_data;
931 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
933 /* Get account and set it into mail_operation */
934 priv->account = g_object_ref (info->account);
937 * for POP3, we do a logout-login upon send/receive -- many POP-servers (like Gmail) do not
938 * show any updates unless we do that
940 if (!first_time && TNY_IS_CAMEL_POP_STORE_ACCOUNT(priv->account))
941 tny_camel_pop_store_account_reconnect (TNY_CAMEL_POP_STORE_ACCOUNT(priv->account));
943 /* Get all the folders. We can do it synchronously because
944 we're already running in a different thread than the UI */
945 all_folders = tny_simple_list_new ();
946 query = tny_folder_store_query_new ();
947 tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
948 tny_folder_store_get_folders (TNY_FOLDER_STORE (info->account),
953 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
957 iter = tny_list_create_iterator (all_folders);
958 while (!tny_iterator_is_done (iter)) {
959 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
961 recurse_folders (folder, query, all_folders);
962 tny_iterator_next (iter);
964 g_object_unref (G_OBJECT (iter));
966 /* Update status and notify. We need to call the notification
967 with a source function in order to call it from the main
968 loop. We need that in order not to get into trouble with
969 Gtk+. We use a timeout in order to provide more status
970 information, because the sync tinymail call does not
971 provide it for the moment */
972 gint timeout = g_timeout_add (100, idle_notify_progress, info->mail_op);
974 /* Refresh folders */
975 new_headers = g_ptr_array_new ();
976 iter = tny_list_create_iterator (all_folders);
978 while (!tny_iterator_is_done (iter) && !priv->error && !did_a_cancel) {
980 InternalFolderObserver *observer;
981 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
983 /* Refresh the folder */
984 /* Our observer receives notification of new emails during folder refreshes,
985 * so we can use observer->new_headers.
987 observer = g_object_new (internal_folder_observer_get_type (), NULL);
988 tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
990 /* This gets the status information (headers) from the server.
991 * We use the blocking version, because we are already in a separate
995 if (!g_ascii_strcasecmp (info->retrieve_type, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES) ||
996 !g_ascii_strcasecmp (info->retrieve_type, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES_AND_ATTACHMENTS)) {
999 /* If the retrieve type is full messages, refresh and get the messages */
1000 tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
1002 iter = tny_list_create_iterator (observer->new_headers);
1003 while (!tny_iterator_is_done (iter)) {
1004 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1006 /* Apply per-message size limits */
1007 if (tny_header_get_message_size (header) < info->max_size)
1008 g_ptr_array_add (new_headers, g_object_ref (header));
1010 g_object_unref (header);
1011 tny_iterator_next (iter);
1013 g_object_unref (iter);
1015 /* We do not need to do it the first time
1016 because it's automatically done by the tree
1018 if (G_UNLIKELY (!first_time))
1019 tny_folder_poke_status (TNY_FOLDER (folder));
1021 tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
1022 g_object_unref (observer);
1025 g_object_unref (G_OBJECT (folder));
1028 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1032 tny_iterator_next (iter);
1035 did_a_cancel = FALSE;
1037 g_object_unref (G_OBJECT (iter));
1038 g_source_remove (timeout);
1040 if (new_headers->len > 0) {
1044 g_ptr_array_sort (new_headers, (GCompareFunc) compare_headers_by_date);
1046 /* Apply message count limit */
1047 /* If the number of messages exceeds the maximum, ask the
1048 * user to download them all,
1049 * as per the UI spec "Retrieval Limits" section in 4.4:
1051 if (new_headers->len > info->retrieve_limit) {
1052 /* TODO: Ask the user, instead of just
1054 * mail_nc_msg_count_limit_exceeded, with 'Get
1055 * all' and 'Newest only' buttons. */
1056 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1057 MODEST_MAIL_OPERATION_ERROR_RETRIEVAL_NUMBER_LIMIT,
1058 "The number of messages to retrieve exceeds the chosen limit for account %s\n",
1059 tny_account_get_name (TNY_ACCOUNT (info->transport_account)));
1060 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1065 priv->total = MIN (new_headers->len, info->retrieve_limit);
1066 while (msg_num < priv->total) {
1068 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers, msg_num));
1069 TnyFolder *folder = tny_header_get_folder (header);
1070 TnyMsg *msg = tny_folder_get_msg (folder, header, NULL);
1071 ModestMailOperationState *state;
1075 /* We can not just use the mail operation because the
1076 values of done and total could change before the
1078 state = modest_mail_operation_clone_state (info->mail_op);
1079 pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE);
1080 g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once,
1081 pair, (GDestroyNotify) modest_pair_free);
1083 g_object_unref (msg);
1084 g_object_unref (folder);
1088 g_ptr_array_foreach (new_headers, (GFunc) g_object_unref, NULL);
1089 g_ptr_array_free (new_headers, FALSE);
1093 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
1096 if (priv->account != NULL)
1097 g_object_unref (priv->account);
1098 priv->account = g_object_ref (info->transport_account);
1100 send_queue = modest_runtime_get_send_queue (info->transport_account);
1102 timeout = g_timeout_add (250, idle_notify_progress, info->mail_op);
1103 modest_tny_send_queue_try_to_send (send_queue);
1104 g_source_remove (timeout);
1106 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1107 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1108 "cannot create a send queue for %s\n",
1109 tny_account_get_name (TNY_ACCOUNT (info->transport_account)));
1110 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1113 /* Check if the operation was a success */
1115 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1117 /* Update the last updated key */
1118 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1119 set_last_updated_idle,
1120 g_strdup (tny_account_get_id (TNY_ACCOUNT (info->account))),
1121 (GDestroyNotify) g_free);
1126 if (info->callback) {
1127 UpdateAccountInfo *idle_info;
1129 /* This thread is not in the main lock */
1130 idle_info = g_malloc0 (sizeof (UpdateAccountInfo));
1131 idle_info->mail_op = g_object_ref (info->mail_op);
1132 idle_info->new_headers = (new_headers) ? new_headers->len : 0;
1133 idle_info->callback = info->callback;
1134 g_idle_add (idle_update_account_cb, idle_info);
1137 /* Notify about operation end. Note that the info could be
1138 freed before this idle happens, but the mail operation will
1140 g_idle_add (idle_notify_update_account_queue, g_object_ref (info->mail_op));
1143 g_object_unref (query);
1144 g_object_unref (all_folders);
1145 g_object_unref (info->account);
1146 g_object_unref (info->transport_account);
1147 g_free (info->retrieve_type);
1148 g_slice_free (UpdateAccountInfo, info);
1156 modest_mail_operation_update_account (ModestMailOperation *self,
1157 const gchar *account_name,
1158 UpdateAccountCallback callback,
1162 UpdateAccountInfo *info;
1163 ModestMailOperationPrivate *priv;
1164 ModestAccountMgr *mgr;
1165 TnyStoreAccount *modest_account;
1166 TnyTransportAccount *transport_account;
1168 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
1169 g_return_val_if_fail (account_name, FALSE);
1171 /* Init mail operation. Set total and done to 0, and do not
1172 update them, this way the progress objects will know that
1173 we have no clue about the number of the objects */
1174 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1177 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1179 /* Make sure that we have a connection, and request one
1181 * TODO: Is there some way to trigger this for every attempt to
1182 * use the network? */
1183 if (!modest_platform_connect_and_wait (NULL))
1186 /* Get the Modest account */
1187 modest_account = (TnyStoreAccount *)
1188 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1190 TNY_ACCOUNT_TYPE_STORE);
1192 if (!modest_account) {
1193 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1194 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1195 "cannot get tny store account for %s\n", account_name);
1200 /* Get the transport account, we can not do it in the thread
1201 due to some problems with dbus */
1202 transport_account = (TnyTransportAccount *)
1203 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1205 if (!transport_account) {
1206 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1207 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1208 "cannot get tny transport account for %s\n", account_name);
1212 /* Create the helper object */
1213 info = g_slice_new (UpdateAccountInfo);
1214 info->mail_op = self;
1215 info->account = modest_account;
1216 info->transport_account = transport_account;
1217 info->callback = callback;
1218 info->user_data = user_data;
1220 /* Get the message size limit */
1221 info->max_size = modest_conf_get_int (modest_runtime_get_conf (),
1222 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1223 if (info->max_size == 0)
1224 info->max_size = G_MAXINT;
1226 info->max_size = info->max_size * KB;
1228 /* Get per-account retrieval type */
1229 mgr = modest_runtime_get_account_mgr ();
1230 info->retrieve_type = modest_account_mgr_get_string (mgr, account_name,
1231 MODEST_ACCOUNT_RETRIEVE, FALSE);
1233 /* Get per-account message amount retrieval limit */
1234 info->retrieve_limit = modest_account_mgr_get_int (mgr, account_name,
1235 MODEST_ACCOUNT_LIMIT_RETRIEVE, FALSE);
1236 if (info->retrieve_limit == 0)
1237 info->retrieve_limit = G_MAXINT;
1239 /* printf ("DEBUG: %s: info->retrieve_limit = %d\n", __FUNCTION__, info->retrieve_limit); */
1241 /* Set account busy */
1242 modest_account_mgr_set_account_busy(mgr, account_name, TRUE);
1243 priv->account_name = g_strdup(account_name);
1245 thread = g_thread_create (update_account_thread, info, FALSE, NULL);
1250 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1252 callback (self, 0, user_data);
1253 modest_mail_operation_notify_end (self);
1257 /* ******************************************************************* */
1258 /* ************************** STORE ACTIONS ************************* */
1259 /* ******************************************************************* */
1263 modest_mail_operation_create_folder (ModestMailOperation *self,
1264 TnyFolderStore *parent,
1267 ModestMailOperationPrivate *priv;
1268 TnyFolder *new_folder = NULL;
1270 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
1271 g_return_val_if_fail (name, NULL);
1273 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1276 if (TNY_IS_FOLDER (parent)) {
1277 /* Check folder rules */
1278 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1279 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1280 /* Set status failed and set an error */
1281 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1282 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1283 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1284 _("mail_in_ui_folder_create_error"));
1288 if (!strcmp (name, " ") || strchr (name, '/')) {
1289 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1290 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1291 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1292 _("mail_in_ui_folder_create_error"));
1296 /* Create the folder */
1297 new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
1298 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1300 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1303 /* Notify about operation end */
1304 modest_mail_operation_notify_end (self);
1310 modest_mail_operation_remove_folder (ModestMailOperation *self,
1312 gboolean remove_to_trash)
1314 TnyAccount *account;
1315 ModestMailOperationPrivate *priv;
1316 ModestTnyFolderRules rules;
1318 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1319 g_return_if_fail (TNY_IS_FOLDER (folder));
1321 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1323 /* Check folder rules */
1324 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1325 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1326 /* Set status failed and set an error */
1327 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1328 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1329 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1330 _("mail_in_ui_folder_delete_error"));
1334 /* Get the account */
1335 account = modest_tny_folder_get_account (folder);
1336 priv->account = g_object_ref(account);
1338 /* Delete folder or move to trash */
1339 if (remove_to_trash) {
1340 TnyFolder *trash_folder = NULL;
1341 trash_folder = modest_tny_account_get_special_folder (account,
1342 TNY_FOLDER_TYPE_TRASH);
1343 /* TODO: error_handling */
1344 modest_mail_operation_xfer_folder (self, folder,
1345 TNY_FOLDER_STORE (trash_folder),
1348 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1350 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1351 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1354 g_object_unref (G_OBJECT (parent));
1356 g_object_unref (G_OBJECT (account));
1359 /* Notify about operation end */
1360 modest_mail_operation_notify_end (self);
1364 transfer_folder_status_cb (GObject *obj,
1368 ModestMailOperation *self;
1369 ModestMailOperationPrivate *priv;
1370 ModestMailOperationState *state;
1371 XFerMsgAsyncHelper *helper;
1373 g_return_if_fail (status != NULL);
1374 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1376 helper = (XFerMsgAsyncHelper *) user_data;
1377 g_return_if_fail (helper != NULL);
1379 self = helper->mail_op;
1380 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1382 priv->done = status->position;
1383 priv->total = status->of_total;
1385 state = modest_mail_operation_clone_state (self);
1386 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1387 g_slice_free (ModestMailOperationState, state);
1392 transfer_folder_cb (TnyFolder *folder,
1393 TnyFolderStore *into,
1395 TnyFolder *new_folder,
1399 XFerMsgAsyncHelper *helper;
1400 ModestMailOperation *self = NULL;
1401 ModestMailOperationPrivate *priv = NULL;
1403 helper = (XFerMsgAsyncHelper *) user_data;
1404 g_return_if_fail (helper != NULL);
1406 self = helper->mail_op;
1407 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1410 priv->error = g_error_copy (*err);
1412 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1413 } else if (cancelled) {
1414 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1415 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1416 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1417 _("Transference of %s was cancelled."),
1418 tny_folder_get_name (folder));
1421 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1424 /* Notify about operation end */
1425 modest_mail_operation_notify_end (self);
1427 /* If user defined callback function was defined, call it */
1428 if (helper->user_callback) {
1429 gdk_threads_enter ();
1430 helper->user_callback (priv->source, helper->user_data);
1431 gdk_threads_leave ();
1435 g_object_unref (helper->mail_op);
1436 g_slice_free (XFerMsgAsyncHelper, helper);
1437 g_object_unref (folder);
1438 g_object_unref (into);
1442 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1444 TnyFolderStore *parent,
1445 gboolean delete_original,
1446 XferMsgsAsynUserCallback user_callback,
1449 ModestMailOperationPrivate *priv = NULL;
1450 ModestTnyFolderRules parent_rules = 0, rules;
1451 XFerMsgAsyncHelper *helper = NULL;
1453 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1454 g_return_if_fail (TNY_IS_FOLDER (folder));
1456 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1458 /* Get account and set it into mail_operation */
1459 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1460 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1462 /* Get folder rules */
1463 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1464 if (TNY_IS_FOLDER (parent))
1465 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1467 /* The moveable restriction is applied also to copy operation */
1468 if ((!TNY_IS_FOLDER_STORE (parent)) || (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1469 printf("DEBUG: %s: Not allowing the move.\n", __FUNCTION__);
1470 /* Set status failed and set an error */
1471 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1472 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1473 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1474 _("mail_in_ui_folder_move_target_error"));
1476 /* Notify the queue */
1477 modest_mail_operation_notify_end (self);
1478 } else if (TNY_IS_FOLDER (parent) &&
1479 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1480 /* Set status failed and set an error */
1481 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1482 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1483 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1484 _("FIXME: parent folder does not accept new folders"));
1486 /* Notify the queue */
1487 modest_mail_operation_notify_end (self);
1489 /* Pick references for async calls */
1490 g_object_ref (folder);
1491 g_object_ref (parent);
1493 /* Create the helper */
1494 helper = g_slice_new0 (XFerMsgAsyncHelper);
1495 helper->mail_op = g_object_ref(self);
1496 helper->dest_folder = NULL;
1497 helper->headers = NULL;
1498 helper->user_callback = user_callback;
1499 helper->user_data = user_data;
1501 /* Move/Copy folder */
1502 tny_folder_copy_async (folder,
1504 tny_folder_get_name (folder),
1507 transfer_folder_status_cb,
1514 modest_mail_operation_rename_folder (ModestMailOperation *self,
1518 ModestMailOperationPrivate *priv;
1519 ModestTnyFolderRules rules;
1520 XFerMsgAsyncHelper *helper;
1522 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1523 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
1524 g_return_if_fail (name);
1526 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1528 /* Get account and set it into mail_operation */
1529 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1531 /* Check folder rules */
1532 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1533 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
1534 /* Set status failed and set an error */
1535 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1536 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1537 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1538 _("FIXME: unable to rename"));
1540 /* Notify about operation end */
1541 modest_mail_operation_notify_end (self);
1542 } else if (!strcmp (name, " ") || strchr (name, '/')) {
1543 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1544 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1545 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1546 _("FIXME: unable to rename"));
1547 /* Notify about operation end */
1548 modest_mail_operation_notify_end (self);
1550 TnyFolderStore *into;
1552 /* Create the helper */
1553 helper = g_slice_new0 (XFerMsgAsyncHelper);
1554 helper->mail_op = g_object_ref(self);
1555 helper->dest_folder = NULL;
1556 helper->headers = NULL;
1557 helper->user_callback = NULL;
1558 helper->user_data = NULL;
1560 /* Rename. Camel handles folder subscription/unsubscription */
1561 into = tny_folder_get_folder_store (folder);
1562 tny_folder_copy_async (folder, into, name, TRUE,
1564 transfer_folder_status_cb,
1568 g_object_unref (into);
1572 /* ******************************************************************* */
1573 /* ************************** MSG ACTIONS ************************* */
1574 /* ******************************************************************* */
1576 void modest_mail_operation_get_msg (ModestMailOperation *self,
1578 GetMsgAsyncUserCallback user_callback,
1581 GetMsgAsyncHelper *helper = NULL;
1583 ModestMailOperationPrivate *priv;
1585 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1586 g_return_if_fail (TNY_IS_HEADER (header));
1588 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1589 folder = tny_header_get_folder (header);
1591 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1593 /* Get message from folder */
1595 /* Get account and set it into mail_operation */
1596 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1598 helper = g_slice_new0 (GetMsgAsyncHelper);
1599 helper->mail_op = self;
1600 helper->user_callback = user_callback;
1601 helper->user_data = user_data;
1602 helper->header = g_object_ref (header);
1604 // The callback's reference so that the mail op is not
1605 // finalized until the async operation is completed even if
1606 // the user canceled the request meanwhile.
1607 g_object_ref (G_OBJECT (helper->mail_op));
1609 tny_folder_get_msg_async (folder, header, get_msg_cb, get_msg_status_cb, helper);
1611 g_object_unref (G_OBJECT (folder));
1613 /* Set status failed and set an error */
1614 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1615 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1616 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1617 _("Error trying to get a message. No folder found for header"));
1619 /* Notify the queue */
1620 modest_mail_operation_notify_end (self);
1625 get_msg_cb (TnyFolder *folder,
1631 GetMsgAsyncHelper *helper = NULL;
1632 ModestMailOperation *self = NULL;
1633 ModestMailOperationPrivate *priv = NULL;
1635 helper = (GetMsgAsyncHelper *) user_data;
1636 g_return_if_fail (helper != NULL);
1637 self = helper->mail_op;
1638 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1639 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1641 /* Check errors and cancel */
1643 priv->error = g_error_copy (*error);
1644 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1645 } else if (cancelled) {
1646 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1647 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1648 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1649 _("Error trying to refresh the contents of %s"),
1650 tny_folder_get_name (folder));
1652 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1655 /* If user defined callback function was defined, call it even
1656 if the operation failed*/
1657 if (helper->user_callback) {
1658 /* This callback is called into an iddle by tinymail,
1659 and idles are not in the main lock */
1660 gdk_threads_enter ();
1661 helper->user_callback (self, helper->header, msg, helper->user_data);
1662 gdk_threads_leave ();
1666 g_object_unref (helper->mail_op);
1667 g_object_unref (helper->header);
1668 g_slice_free (GetMsgAsyncHelper, helper);
1670 /* Notify about operation end */
1671 modest_mail_operation_notify_end (self);
1675 get_msg_status_cb (GObject *obj,
1679 GetMsgAsyncHelper *helper = NULL;
1680 ModestMailOperation *self;
1681 ModestMailOperationPrivate *priv;
1682 ModestMailOperationState *state;
1684 g_return_if_fail (status != NULL);
1685 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
1687 helper = (GetMsgAsyncHelper *) user_data;
1688 g_return_if_fail (helper != NULL);
1690 self = helper->mail_op;
1691 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1693 if(priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
1699 state = modest_mail_operation_clone_state (self);
1700 state->bytes_done = status->position;
1701 state->bytes_total = status->of_total;
1702 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1703 g_slice_free (ModestMailOperationState, state);
1706 /****************************************************/
1708 ModestMailOperation *mail_op;
1710 GetMsgAsyncUserCallback user_callback;
1712 GDestroyNotify notify;
1716 GetMsgAsyncUserCallback user_callback;
1720 ModestMailOperation *mail_op;
1721 } NotifyGetMsgsInfo;
1725 * Used by get_msgs_full_thread to call the user_callback for each
1726 * message that has been read
1729 notify_get_msgs_full (gpointer data)
1731 NotifyGetMsgsInfo *info;
1733 info = (NotifyGetMsgsInfo *) data;
1735 /* Call the user callback. Idles are not in the main lock, so
1737 gdk_threads_enter ();
1738 info->user_callback (info->mail_op, info->header, info->msg, info->user_data);
1739 gdk_threads_leave ();
1741 g_slice_free (NotifyGetMsgsInfo, info);
1747 * Used by get_msgs_full_thread to free al the thread resources and to
1748 * call the destroy function for the passed user_data
1751 get_msgs_full_destroyer (gpointer data)
1753 GetFullMsgsInfo *info;
1755 info = (GetFullMsgsInfo *) data;
1758 gdk_threads_enter ();
1759 info->notify (info->user_data);
1760 gdk_threads_leave ();
1764 g_object_unref (info->headers);
1765 g_slice_free (GetFullMsgsInfo, info);
1771 get_msgs_full_thread (gpointer thr_user_data)
1773 GetFullMsgsInfo *info;
1774 ModestMailOperationPrivate *priv = NULL;
1775 TnyIterator *iter = NULL;
1777 info = (GetFullMsgsInfo *) thr_user_data;
1778 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1780 iter = tny_list_create_iterator (info->headers);
1781 while (!tny_iterator_is_done (iter)) {
1785 header = TNY_HEADER (tny_iterator_get_current (iter));
1786 folder = tny_header_get_folder (header);
1788 /* Get message from folder */
1791 /* The callback will call it per each header */
1792 msg = tny_folder_get_msg (folder, header, &(priv->error));
1795 ModestMailOperationState *state;
1800 /* notify progress */
1801 state = modest_mail_operation_clone_state (info->mail_op);
1802 pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE);
1803 g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once,
1804 pair, (GDestroyNotify) modest_pair_free);
1806 /* The callback is the responsible for
1807 freeing the message */
1808 if (info->user_callback) {
1809 NotifyGetMsgsInfo *info_notify;
1810 info_notify = g_slice_new0 (NotifyGetMsgsInfo);
1811 info_notify->user_callback = info->user_callback;
1812 info_notify->mail_op = info->mail_op;
1813 info_notify->header = g_object_ref (header);
1814 info_notify->msg = g_object_ref (msg);
1815 info_notify->user_data = info->user_data;
1816 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1817 notify_get_msgs_full,
1820 g_object_unref (msg);
1823 /* Set status failed and set an error */
1824 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1825 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1826 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1827 "Error trying to get a message. No folder found for header");
1829 g_object_unref (header);
1830 tny_iterator_next (iter);
1833 /* Set operation status */
1834 if (priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
1835 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1837 /* Notify about operation end */
1838 g_idle_add (idle_notify_update_account_queue, g_object_ref (info->mail_op));
1840 /* Free thread resources. Will be called after all previous idles */
1841 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1, get_msgs_full_destroyer, info, NULL);
1847 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
1848 TnyList *header_list,
1849 GetMsgAsyncUserCallback user_callback,
1851 GDestroyNotify notify)
1853 TnyHeader *header = NULL;
1854 TnyFolder *folder = NULL;
1856 ModestMailOperationPrivate *priv = NULL;
1857 GetFullMsgsInfo *info = NULL;
1858 gboolean size_ok = TRUE;
1860 TnyIterator *iter = NULL;
1862 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1864 /* Init mail operation */
1865 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1866 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1868 priv->total = tny_list_get_length(header_list);
1870 /* Get account and set it into mail_operation */
1871 if (tny_list_get_length (header_list) >= 1) {
1872 iter = tny_list_create_iterator (header_list);
1873 header = TNY_HEADER (tny_iterator_get_current (iter));
1874 folder = tny_header_get_folder (header);
1875 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1876 g_object_unref (header);
1877 g_object_unref (folder);
1879 if (tny_list_get_length (header_list) == 1) {
1880 g_object_unref (iter);
1885 /* Get msg size limit */
1886 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1887 MODEST_CONF_MSG_SIZE_LIMIT,
1890 g_clear_error (&(priv->error));
1891 max_size = G_MAXINT;
1893 max_size = max_size * KB;
1896 /* Check message size limits. If there is only one message
1897 always retrieve it */
1899 while (!tny_iterator_is_done (iter) && size_ok) {
1900 header = TNY_HEADER (tny_iterator_get_current (iter));
1901 if (tny_header_get_message_size (header) >= max_size)
1903 g_object_unref (header);
1904 tny_iterator_next (iter);
1906 g_object_unref (iter);
1910 /* Create the info */
1911 info = g_slice_new0 (GetFullMsgsInfo);
1912 info->mail_op = self;
1913 info->user_callback = user_callback;
1914 info->user_data = user_data;
1915 info->headers = g_object_ref (header_list);
1916 info->notify = notify;
1918 thread = g_thread_create (get_msgs_full_thread, info, FALSE, NULL);
1920 /* Set status failed and set an error */
1921 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1922 /* FIXME: the error msg is different for pop */
1923 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1924 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
1925 _("emev_ni_ui_imap_msg_size_exceed_error"));
1926 /* Remove from queue and free resources */
1927 modest_mail_operation_notify_end (self);
1935 modest_mail_operation_remove_msg (ModestMailOperation *self, TnyHeader *header,
1936 gboolean remove_to_trash /*ignored*/)
1939 ModestMailOperationPrivate *priv;
1941 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1942 g_return_if_fail (TNY_IS_HEADER (header));
1944 if (remove_to_trash)
1945 g_warning ("remove to trash is not implemented");
1947 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1948 folder = tny_header_get_folder (header);
1950 /* Get account and set it into mail_operation */
1951 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1953 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1956 tny_folder_remove_msg (folder, header, &(priv->error));
1958 tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED);
1960 if (TNY_IS_CAMEL_IMAP_FOLDER (folder))
1961 tny_folder_sync(folder, FALSE, &(priv->error)); /* FALSE --> don't expunge */
1962 else if (TNY_IS_CAMEL_POP_FOLDER (folder))
1963 tny_folder_sync(folder, TRUE, &(priv->error)); /* TRUE --> expunge */
1966 tny_folder_sync(folder, TRUE, &(priv->error)); /* TRUE --> expunge */
1972 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1974 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1977 g_object_unref (G_OBJECT (folder));
1979 /* Notify about operation end */
1980 modest_mail_operation_notify_end (self);
1984 transfer_msgs_status_cb (GObject *obj,
1988 XFerMsgAsyncHelper *helper = NULL;
1989 ModestMailOperation *self;
1990 ModestMailOperationPrivate *priv;
1991 ModestMailOperationState *state;
1994 g_return_if_fail (status != NULL);
1995 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
1997 helper = (XFerMsgAsyncHelper *) user_data;
1998 g_return_if_fail (helper != NULL);
2000 self = helper->mail_op;
2001 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2003 priv->done = status->position;
2004 priv->total = status->of_total;
2006 state = modest_mail_operation_clone_state (self);
2007 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2008 g_slice_free (ModestMailOperationState, state);
2013 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer user_data)
2015 XFerMsgAsyncHelper *helper;
2016 ModestMailOperation *self;
2017 ModestMailOperationPrivate *priv;
2019 helper = (XFerMsgAsyncHelper *) user_data;
2020 self = helper->mail_op;
2022 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2025 priv->error = g_error_copy (*err);
2027 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2028 } else if (cancelled) {
2029 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2030 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2031 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2032 _("Error trying to refresh the contents of %s"),
2033 tny_folder_get_name (folder));
2036 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2039 /* Notify about operation end */
2040 modest_mail_operation_notify_end (self);
2042 /* If user defined callback function was defined, call it */
2043 if (helper->user_callback) {
2044 gdk_threads_enter ();
2045 helper->user_callback (priv->source, helper->user_data);
2046 gdk_threads_leave ();
2050 g_object_unref (helper->headers);
2051 g_object_unref (helper->dest_folder);
2052 g_object_unref (helper->mail_op);
2053 g_slice_free (XFerMsgAsyncHelper, helper);
2054 g_object_unref (folder);
2059 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2062 gboolean delete_original,
2063 XferMsgsAsynUserCallback user_callback,
2066 ModestMailOperationPrivate *priv;
2068 TnyFolder *src_folder;
2069 XFerMsgAsyncHelper *helper;
2071 ModestTnyFolderRules rules;
2072 const gchar *id1 = NULL;
2073 const gchar *id2 = NULL;
2074 gboolean same_folder = FALSE;
2076 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2077 g_return_if_fail (TNY_IS_LIST (headers));
2078 g_return_if_fail (TNY_IS_FOLDER (folder));
2080 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2083 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2085 /* Apply folder rules */
2086 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2087 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2088 /* Set status failed and set an error */
2089 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2090 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2091 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2092 _("ckct_ib_unable_to_paste_here"));
2093 /* Notify the queue */
2094 modest_mail_operation_notify_end (self);
2098 /* Get source folder */
2099 iter = tny_list_create_iterator (headers);
2100 header = TNY_HEADER (tny_iterator_get_current (iter));
2101 src_folder = tny_header_get_folder (header);
2102 g_object_unref (header);
2103 g_object_unref (iter);
2105 /* Check folder source and destination */
2106 id1 = tny_folder_get_id (src_folder);
2107 id2 = tny_folder_get_id (TNY_FOLDER(folder));
2108 same_folder = !g_ascii_strcasecmp (id1, id2);
2110 /* Set status failed and set an error */
2111 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2112 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2113 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2114 _("mcen_ib_unable_to_copy_samefolder"));
2116 /* Notify the queue */
2117 modest_mail_operation_notify_end (self);
2120 g_object_unref (src_folder);
2124 /* Create the helper */
2125 helper = g_slice_new0 (XFerMsgAsyncHelper);
2126 helper->mail_op = g_object_ref(self);
2127 helper->dest_folder = g_object_ref(folder);
2128 helper->headers = g_object_ref(headers);
2129 helper->user_callback = user_callback;
2130 helper->user_data = user_data;
2132 /* Get account and set it into mail_operation */
2133 priv->account = modest_tny_folder_get_account (src_folder);
2135 /* Transfer messages */
2136 tny_folder_transfer_msgs_async (src_folder,
2141 transfer_msgs_status_cb,
2147 on_refresh_folder (TnyFolder *folder,
2152 RefreshAsyncHelper *helper = NULL;
2153 ModestMailOperation *self = NULL;
2154 ModestMailOperationPrivate *priv = NULL;
2156 helper = (RefreshAsyncHelper *) user_data;
2157 self = helper->mail_op;
2158 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2161 priv->error = g_error_copy (*error);
2162 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2167 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2168 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2169 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2170 _("Error trying to refresh the contents of %s"),
2171 tny_folder_get_name (folder));
2175 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2178 /* Call user defined callback, if it exists */
2179 if (helper->user_callback) {
2180 gdk_threads_enter ();
2181 helper->user_callback (self, folder, helper->user_data);
2182 gdk_threads_leave ();
2186 g_object_unref (helper->mail_op);
2187 g_slice_free (RefreshAsyncHelper, helper);
2188 g_object_unref (folder);
2190 /* Notify about operation end */
2191 modest_mail_operation_notify_end (self);
2195 on_refresh_folder_status_update (GObject *obj,
2199 RefreshAsyncHelper *helper = NULL;
2200 ModestMailOperation *self = NULL;
2201 ModestMailOperationPrivate *priv = NULL;
2202 ModestMailOperationState *state;
2204 g_return_if_fail (user_data != NULL);
2205 g_return_if_fail (status != NULL);
2206 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2208 helper = (RefreshAsyncHelper *) user_data;
2209 self = helper->mail_op;
2210 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2212 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2214 priv->done = status->position;
2215 priv->total = status->of_total;
2217 state = modest_mail_operation_clone_state (self);
2218 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2219 g_slice_free (ModestMailOperationState, state);
2223 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2225 RefreshAsyncUserCallback user_callback,
2228 ModestMailOperationPrivate *priv = NULL;
2229 RefreshAsyncHelper *helper = NULL;
2231 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2233 /* Pick a reference */
2234 g_object_ref (folder);
2236 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2238 /* Get account and set it into mail_operation */
2239 priv->account = modest_tny_folder_get_account (folder);
2241 /* Create the helper */
2242 helper = g_slice_new0 (RefreshAsyncHelper);
2243 helper->mail_op = g_object_ref(self);
2244 helper->user_callback = user_callback;
2245 helper->user_data = user_data;
2247 /* Refresh the folder. TODO: tinymail could issue a status
2248 updates before the callback call then this could happen. We
2249 must review the design */
2250 tny_folder_refresh_async (folder,
2252 on_refresh_folder_status_update,
2258 * It's used by the mail operation queue to notify the observers
2259 * attached to that signal that the operation finished. We need to use
2260 * that because tinymail does not give us the progress of a given
2261 * operation when it finishes (it directly calls the operation
2265 modest_mail_operation_notify_end (ModestMailOperation *self)
2267 ModestMailOperationState *state;
2268 ModestMailOperationPrivate *priv = NULL;
2270 g_return_if_fail (self);
2272 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2275 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
2279 /* Set the account back to not busy */
2280 if (priv->account_name) {
2281 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr(),
2282 priv->account_name, FALSE);
2283 g_free(priv->account_name);
2284 priv->account_name = NULL;
2287 /* Notify the observers about the mail opertation end */
2288 state = modest_mail_operation_clone_state (self);
2289 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2290 g_slice_free (ModestMailOperationState, state);