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-folder-observer.h>
45 #include <camel/camel-stream-mem.h>
46 #include <glib/gi18n.h>
47 #include "modest-platform.h"
48 #include "modest-account-mgr-helpers.h"
49 #include <modest-tny-account.h>
50 #include <modest-tny-send-queue.h>
51 #include <modest-runtime.h>
52 #include "modest-text-utils.h"
53 #include "modest-tny-msg.h"
54 #include "modest-tny-folder.h"
55 #include "modest-tny-account-store.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-marshal.h"
58 #include "modest-error.h"
59 #include "modest-mail-operation.h"
64 * Remove all these #ifdef stuff when the tinymail's idle calls become
67 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
69 /* 'private'/'protected' functions */
70 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
71 static void modest_mail_operation_init (ModestMailOperation *obj);
72 static void modest_mail_operation_finalize (GObject *obj);
74 static void get_msg_async_cb (TnyFolder *folder,
80 static void get_msg_status_cb (GObject *obj,
84 static void modest_mail_operation_notify_start (ModestMailOperation *self);
85 static void modest_mail_operation_notify_end (ModestMailOperation *self);
87 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
89 gint *last_total_bytes,
90 gint *sum_total_bytes,
92 gboolean increment_done);
94 static guint compute_message_list_size (TnyList *headers);
96 enum _ModestMailOperationSignals
98 PROGRESS_CHANGED_SIGNAL,
99 OPERATION_STARTED_SIGNAL,
100 OPERATION_FINISHED_SIGNAL,
104 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
105 struct _ModestMailOperationPrivate {
111 ErrorCheckingUserCallback error_checking;
112 gpointer error_checking_user_data;
113 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
114 ModestMailOperationStatus status;
115 ModestMailOperationTypeOperation op_type;
118 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
119 MODEST_TYPE_MAIL_OPERATION, \
120 ModestMailOperationPrivate))
122 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
123 priv->status = new_status;\
128 GetMsgAsyncUserCallback user_callback;
131 ModestMailOperation *mail_op;
132 GDestroyNotify destroy_notify;
133 gint last_total_bytes;
134 gint sum_total_bytes;
139 ModestMailOperation *mail_op;
141 gulong msg_sent_handler;
142 gulong error_happened_handler;
145 static void send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
146 guint nth, guint total, gpointer userdata);
147 static void send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
148 GError *error, gpointer userdata);
149 static void common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
152 typedef struct _RefreshAsyncHelper {
153 ModestMailOperation *mail_op;
154 RefreshAsyncUserCallback user_callback;
156 } RefreshAsyncHelper;
158 typedef struct _XFerMsgAsyncHelper
160 ModestMailOperation *mail_op;
162 TnyFolder *dest_folder;
163 XferAsyncUserCallback user_callback;
166 gint last_total_bytes;
167 gint sum_total_bytes;
169 } XFerMsgAsyncHelper;
171 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
175 static void modest_mail_operation_create_msg (ModestMailOperation *self,
176 const gchar *from, const gchar *to,
177 const gchar *cc, const gchar *bcc,
178 const gchar *subject, const gchar *plain_body,
179 const gchar *html_body, const GList *attachments_list,
180 const GList *images_list,
181 TnyHeaderFlags priority_flags,
182 ModestMailOperationCreateMsgCallback callback,
185 static gboolean idle_notify_queue (gpointer data);
188 ModestMailOperation *mail_op;
196 GList *attachments_list;
198 TnyHeaderFlags priority_flags;
199 ModestMailOperationCreateMsgCallback callback;
205 ModestMailOperation *mail_op;
207 ModestMailOperationCreateMsgCallback callback;
212 static GObjectClass *parent_class = NULL;
214 static guint signals[NUM_SIGNALS] = {0};
217 modest_mail_operation_get_type (void)
219 static GType my_type = 0;
221 static const GTypeInfo my_info = {
222 sizeof(ModestMailOperationClass),
223 NULL, /* base init */
224 NULL, /* base finalize */
225 (GClassInitFunc) modest_mail_operation_class_init,
226 NULL, /* class finalize */
227 NULL, /* class data */
228 sizeof(ModestMailOperation),
230 (GInstanceInitFunc) modest_mail_operation_init,
233 my_type = g_type_register_static (G_TYPE_OBJECT,
234 "ModestMailOperation",
241 modest_mail_operation_class_init (ModestMailOperationClass *klass)
243 GObjectClass *gobject_class;
244 gobject_class = (GObjectClass*) klass;
246 parent_class = g_type_class_peek_parent (klass);
247 gobject_class->finalize = modest_mail_operation_finalize;
249 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
252 * ModestMailOperation::progress-changed
253 * @self: the #MailOperation that emits the signal
254 * @user_data: user data set when the signal handler was connected
256 * Emitted when the progress of a mail operation changes
258 signals[PROGRESS_CHANGED_SIGNAL] =
259 g_signal_new ("progress-changed",
260 G_TYPE_FROM_CLASS (gobject_class),
262 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
264 g_cclosure_marshal_VOID__POINTER,
265 G_TYPE_NONE, 1, G_TYPE_POINTER);
269 * This signal is issued whenever a mail operation starts, and
270 * starts mean when the tinymail operation is issued. This
271 * means that it could happen that something wrong happens and
272 * the tinymail function is never called. In this situation a
273 * operation-finished will be issued without any
276 signals[OPERATION_STARTED_SIGNAL] =
277 g_signal_new ("operation-started",
278 G_TYPE_FROM_CLASS (gobject_class),
280 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
282 g_cclosure_marshal_VOID__VOID,
287 * This signal is issued whenever a mail operation
288 * finishes. Note that this signal could be issued without any
289 * previous "operation-started" signal, because this last one
290 * is only issued when the tinymail operation is successfully
293 signals[OPERATION_FINISHED_SIGNAL] =
294 g_signal_new ("operation-finished",
295 G_TYPE_FROM_CLASS (gobject_class),
297 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
299 g_cclosure_marshal_VOID__VOID,
304 modest_mail_operation_init (ModestMailOperation *obj)
306 ModestMailOperationPrivate *priv;
308 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
310 priv->account = NULL;
311 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
312 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
317 priv->error_checking = NULL;
318 priv->error_checking_user_data = NULL;
322 modest_mail_operation_finalize (GObject *obj)
324 ModestMailOperationPrivate *priv;
326 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
331 g_error_free (priv->error);
335 g_object_unref (priv->source);
339 g_object_unref (priv->account);
340 priv->account = NULL;
344 G_OBJECT_CLASS(parent_class)->finalize (obj);
348 modest_mail_operation_new (GObject *source)
350 ModestMailOperation *obj;
351 ModestMailOperationPrivate *priv;
353 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
354 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
357 priv->source = g_object_ref(source);
363 modest_mail_operation_new_with_error_handling (GObject *source,
364 ErrorCheckingUserCallback error_handler,
366 ErrorCheckingUserDataDestroyer error_handler_destroyer)
368 ModestMailOperation *obj;
369 ModestMailOperationPrivate *priv;
371 obj = modest_mail_operation_new (source);
372 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
374 g_return_val_if_fail (error_handler != NULL, obj);
375 priv->error_checking = error_handler;
376 priv->error_checking_user_data = user_data;
377 priv->error_checking_user_data_destroyer = error_handler_destroyer;
383 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
385 ModestMailOperationPrivate *priv;
387 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
388 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
390 /* Call the user callback */
391 if (priv->error_checking != NULL)
392 priv->error_checking (self, priv->error_checking_user_data);
396 ModestMailOperationTypeOperation
397 modest_mail_operation_get_type_operation (ModestMailOperation *self)
399 ModestMailOperationPrivate *priv;
401 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
403 return priv->op_type;
407 modest_mail_operation_is_mine (ModestMailOperation *self,
410 ModestMailOperationPrivate *priv;
412 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
413 if (priv->source == NULL) return FALSE;
415 return priv->source == me;
419 modest_mail_operation_get_source (ModestMailOperation *self)
421 ModestMailOperationPrivate *priv;
423 g_return_val_if_fail (self, NULL);
425 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
427 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
431 return (priv->source) ? g_object_ref (priv->source) : NULL;
434 ModestMailOperationStatus
435 modest_mail_operation_get_status (ModestMailOperation *self)
437 ModestMailOperationPrivate *priv;
439 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
440 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
441 MODEST_MAIL_OPERATION_STATUS_INVALID);
443 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
445 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
446 return MODEST_MAIL_OPERATION_STATUS_INVALID;
453 modest_mail_operation_get_error (ModestMailOperation *self)
455 ModestMailOperationPrivate *priv;
457 g_return_val_if_fail (self, NULL);
458 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
460 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
463 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
471 modest_mail_operation_cancel (ModestMailOperation *self)
473 ModestMailOperationPrivate *priv;
474 gboolean canceled = FALSE;
476 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
478 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
480 /* Note that if we call cancel with an already canceled mail
481 operation the progress changed signal won't be emitted */
482 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
486 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
488 /* Cancel the mail operation. We need to wrap it between this
489 start/stop operations to allow following calls to the
491 g_return_val_if_fail (priv->account, FALSE);
493 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
494 ModestTnySendQueue *queue;
495 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
496 /* Cancel sending without removing the item */
497 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), FALSE, NULL);
499 /* Cancel operation */
500 tny_account_cancel (priv->account);
507 modest_mail_operation_get_task_done (ModestMailOperation *self)
509 ModestMailOperationPrivate *priv;
511 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
513 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
518 modest_mail_operation_get_task_total (ModestMailOperation *self)
520 ModestMailOperationPrivate *priv;
522 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
524 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
529 modest_mail_operation_is_finished (ModestMailOperation *self)
531 ModestMailOperationPrivate *priv;
532 gboolean retval = FALSE;
534 if (!MODEST_IS_MAIL_OPERATION (self)) {
535 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
539 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
541 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
542 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
543 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
544 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
554 * Creates an image of the current state of a mail operation, the
555 * caller must free it
557 static ModestMailOperationState *
558 modest_mail_operation_clone_state (ModestMailOperation *self)
560 ModestMailOperationState *state;
561 ModestMailOperationPrivate *priv;
563 /* FIXME: this should be fixed properly
565 * in some cases, priv was NULL, so checking here to
568 g_return_val_if_fail (self, NULL);
569 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
570 g_return_val_if_fail (priv, NULL);
575 state = g_slice_new (ModestMailOperationState);
577 state->status = priv->status;
578 state->op_type = priv->op_type;
579 state->done = priv->done;
580 state->total = priv->total;
581 state->finished = modest_mail_operation_is_finished (self);
582 state->bytes_done = 0;
583 state->bytes_total = 0;
588 /* ******************************************************************* */
589 /* ************************** SEND ACTIONS ************************* */
590 /* ******************************************************************* */
593 modest_mail_operation_send_mail (ModestMailOperation *self,
594 TnyTransportAccount *transport_account,
597 TnySendQueue *send_queue = NULL;
598 ModestMailOperationPrivate *priv;
601 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
602 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
603 g_return_if_fail (TNY_IS_MSG (msg));
605 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
607 /* Get account and set it into mail_operation */
608 priv->account = g_object_ref (transport_account);
609 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
613 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
614 if (!TNY_IS_SEND_QUEUE(send_queue)) {
615 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
616 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
617 "modest: could not find send queue for account\n");
618 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
619 modest_mail_operation_notify_end (self);
622 /* Add the msg to the queue */
623 modest_mail_operation_notify_start (self);
624 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
628 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
630 info = g_slice_new0 (SendMsgInfo);
632 info->mail_op = g_object_ref (self);
633 info->msg = g_object_ref (msg);
634 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
635 G_CALLBACK (send_mail_msg_sent_handler), info);
636 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
637 G_CALLBACK (send_mail_error_happened_handler), info);
643 common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
646 if (msg == info->msg) {
647 g_signal_handler_disconnect (queue, info->msg_sent_handler);
648 info->msg_sent_handler = 0;
649 g_signal_handler_disconnect (queue, info->error_happened_handler);
650 info->error_happened_handler = 0;
651 g_object_unref (info->msg);
652 modest_mail_operation_notify_end (info->mail_op);
653 g_object_unref (info->mail_op);
654 g_slice_free (SendMsgInfo, info);
659 send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
660 guint nth, guint total, gpointer userdata)
662 SendMsgInfo *info = (SendMsgInfo *) info;
664 if (msg == info->msg) {
665 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
666 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
669 common_send_mail_operation_end (queue, msg, info);
673 send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
674 GError *error, gpointer userdata)
676 SendMsgInfo *info = (SendMsgInfo *) info;
678 if (msg == info->msg) {
679 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
680 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
681 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
682 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
683 "modest: send mail failed\n");
686 common_send_mail_operation_end (queue, msg, info);
691 idle_create_msg_cb (gpointer idle_data)
693 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
695 /* This is a GDK lock because we are an idle callback and
696 * info->callback can contain Gtk+ code */
698 gdk_threads_enter (); /* CHECKED */
699 info->callback (info->mail_op, info->msg, info->userdata);
701 g_object_unref (info->mail_op);
703 g_object_unref (info->msg);
704 g_slice_free (CreateMsgIdleInfo, info);
705 gdk_threads_leave (); /* CHECKED */
711 create_msg_thread (gpointer thread_data)
713 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
714 TnyMsg *new_msg = NULL;
715 ModestMailOperationPrivate *priv;
717 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
718 if (info->html_body == NULL) {
719 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
720 info->bcc, info->subject, info->plain_body,
721 info->attachments_list);
723 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
724 info->bcc, info->subject, info->html_body,
725 info->plain_body, info->attachments_list,
732 /* Set priority flags in message */
733 header = tny_msg_get_header (new_msg);
734 tny_header_set_flag (header, info->priority_flags);
736 /* Set attachment flags in message */
737 if (info->attachments_list != NULL)
738 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
740 g_object_unref (G_OBJECT(header));
742 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
743 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
744 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
745 "modest: failed to create a new msg\n");
753 g_free (info->plain_body);
754 g_free (info->html_body);
755 g_free (info->subject);
756 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
757 g_list_free (info->attachments_list);
758 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
759 g_list_free (info->images_list);
761 if (info->callback) {
762 CreateMsgIdleInfo *idle_info;
763 idle_info = g_slice_new0 (CreateMsgIdleInfo);
764 idle_info->mail_op = g_object_ref (info->mail_op);
765 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
766 idle_info->callback = info->callback;
767 idle_info->userdata = info->userdata;
768 g_idle_add (idle_create_msg_cb, idle_info);
770 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
773 g_object_unref (info->mail_op);
774 g_slice_free (CreateMsgInfo, info);
779 modest_mail_operation_create_msg (ModestMailOperation *self,
780 const gchar *from, const gchar *to,
781 const gchar *cc, const gchar *bcc,
782 const gchar *subject, const gchar *plain_body,
783 const gchar *html_body,
784 const GList *attachments_list,
785 const GList *images_list,
786 TnyHeaderFlags priority_flags,
787 ModestMailOperationCreateMsgCallback callback,
790 CreateMsgInfo *info = NULL;
792 info = g_slice_new0 (CreateMsgInfo);
793 info->mail_op = g_object_ref (self);
795 info->from = g_strdup (from);
796 info->to = g_strdup (to);
797 info->cc = g_strdup (cc);
798 info->bcc = g_strdup (bcc);
799 info->subject = g_strdup (subject);
800 info->plain_body = g_strdup (plain_body);
801 info->html_body = g_strdup (html_body);
802 info->attachments_list = g_list_copy ((GList *) attachments_list);
803 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
804 info->images_list = g_list_copy ((GList *) images_list);
805 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
806 info->priority_flags = priority_flags;
808 info->callback = callback;
809 info->userdata = userdata;
811 g_thread_create (create_msg_thread, info, FALSE, NULL);
816 TnyTransportAccount *transport_account;
821 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
825 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
826 TnyFolder *draft_folder = NULL;
827 TnyFolder *outbox_folder = NULL;
835 /* Call mail operation */
836 modest_mail_operation_send_mail (self, info->transport_account, msg);
838 /* Remove old mail from its source folder */
839 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
840 TNY_FOLDER_TYPE_DRAFTS);
841 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
842 TNY_FOLDER_TYPE_OUTBOX);
843 if (info->draft_msg != NULL) {
844 TnyFolder *folder = NULL;
845 TnyFolder *src_folder = NULL;
846 TnyFolderType folder_type;
847 folder = tny_msg_get_folder (info->draft_msg);
848 if (folder == NULL) goto end;
849 folder_type = modest_tny_folder_guess_folder_type (folder);
851 if (folder_type == TNY_FOLDER_TYPE_INVALID)
852 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
854 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
855 src_folder = outbox_folder;
857 src_folder = draft_folder;
859 /* Note: This can fail (with a warning) if the message is not really already in a folder,
860 * because this function requires it to have a UID. */
861 header = tny_msg_get_header (info->draft_msg);
862 tny_folder_remove_msg (src_folder, header, NULL);
864 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
865 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
867 g_object_unref (header);
868 g_object_unref (folder);
875 g_object_unref (info->draft_msg);
877 g_object_unref (draft_folder);
879 g_object_unref (outbox_folder);
880 if (info->transport_account)
881 g_object_unref (info->transport_account);
882 g_slice_free (SendNewMailInfo, info);
886 modest_mail_operation_send_new_mail (ModestMailOperation *self,
887 TnyTransportAccount *transport_account,
889 const gchar *from, const gchar *to,
890 const gchar *cc, const gchar *bcc,
891 const gchar *subject, const gchar *plain_body,
892 const gchar *html_body,
893 const GList *attachments_list,
894 const GList *images_list,
895 TnyHeaderFlags priority_flags)
897 ModestMailOperationPrivate *priv = NULL;
898 SendNewMailInfo *info;
900 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
901 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
903 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
904 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
905 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
907 /* Check parametters */
909 /* Set status failed and set an error */
910 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
911 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
912 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
913 _("Error trying to send a mail. You need to set at least one recipient"));
916 info = g_slice_new0 (SendNewMailInfo);
917 info->transport_account = transport_account;
918 if (transport_account)
919 g_object_ref (transport_account);
920 info->draft_msg = draft_msg;
922 g_object_ref (draft_msg);
925 modest_mail_operation_notify_start (self);
926 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
927 attachments_list, images_list, priority_flags,
928 modest_mail_operation_send_new_mail_cb, info);
934 TnyTransportAccount *transport_account;
936 SaveToDraftstCallback callback;
940 ModestMailOperation *mailop;
941 } SaveToDraftsAddMsgInfo;
944 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
949 ModestMailOperationPrivate *priv = NULL;
950 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
952 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
955 g_warning ("%s: priv->error != NULL", __FUNCTION__);
956 g_error_free(priv->error);
959 priv->error = (err == NULL) ? NULL : g_error_copy(err);
961 if ((!priv->error) && (info->draft_msg != NULL)) {
962 TnyHeader *header = tny_msg_get_header (info->draft_msg);
963 TnyFolder *src_folder = tny_header_get_folder (header);
965 /* Remove the old draft */
966 tny_folder_remove_msg (src_folder, header, NULL);
968 /* Synchronize to expunge and to update the msg counts */
969 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
970 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
972 g_object_unref (G_OBJECT(header));
973 g_object_unref (G_OBJECT(src_folder));
977 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
979 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
981 /* Call the user callback */
983 info->callback (info->mailop, info->msg, info->user_data);
985 if (info->transport_account)
986 g_object_unref (G_OBJECT(info->transport_account));
988 g_object_unref (G_OBJECT (info->draft_msg));
990 g_object_unref (G_OBJECT(info->drafts));
992 g_object_unref (G_OBJECT (info->msg));
993 g_slice_free (SaveToDraftsAddMsgInfo, info);
995 modest_mail_operation_notify_end (info->mailop);
996 g_object_unref(info->mailop);
1001 TnyTransportAccount *transport_account;
1003 SaveToDraftstCallback callback;
1008 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1012 TnyFolder *drafts = NULL;
1013 ModestMailOperationPrivate *priv = NULL;
1014 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1016 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1019 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1020 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1021 "modest: failed to create a new msg\n");
1023 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1024 TNY_FOLDER_TYPE_DRAFTS);
1026 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1027 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1028 "modest: failed to create a new msg\n");
1033 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1034 cb_info->transport_account = g_object_ref(info->transport_account);
1035 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1036 cb_info->callback = info->callback;
1037 cb_info->user_data = info->user_data;
1038 cb_info->drafts = g_object_ref(drafts);
1039 cb_info->msg = g_object_ref(msg);
1040 cb_info->mailop = g_object_ref(self);
1041 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1044 /* Call the user callback */
1045 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1047 info->callback (self, msg, info->user_data);
1048 modest_mail_operation_notify_end (self);
1052 g_object_unref (G_OBJECT(drafts));
1053 if (info->draft_msg)
1054 g_object_unref (G_OBJECT (info->draft_msg));
1055 if (info->transport_account)
1056 g_object_unref (G_OBJECT(info->transport_account));
1057 g_slice_free (SaveToDraftsInfo, info);
1061 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1062 TnyTransportAccount *transport_account,
1064 const gchar *from, const gchar *to,
1065 const gchar *cc, const gchar *bcc,
1066 const gchar *subject, const gchar *plain_body,
1067 const gchar *html_body,
1068 const GList *attachments_list,
1069 const GList *images_list,
1070 TnyHeaderFlags priority_flags,
1071 SaveToDraftstCallback callback,
1074 ModestMailOperationPrivate *priv = NULL;
1075 SaveToDraftsInfo *info = NULL;
1077 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1078 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1080 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1082 /* Get account and set it into mail_operation */
1083 priv->account = g_object_ref (transport_account);
1084 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1086 info = g_slice_new0 (SaveToDraftsInfo);
1087 info->transport_account = g_object_ref (transport_account);
1088 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1089 info->callback = callback;
1090 info->user_data = user_data;
1092 modest_mail_operation_notify_start (self);
1093 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1094 attachments_list, images_list, priority_flags,
1095 modest_mail_operation_save_to_drafts_cb, info);
1100 ModestMailOperation *mail_op;
1101 TnyStoreAccount *account;
1102 TnyTransportAccount *transport_account;
1104 gint retrieve_limit;
1105 gchar *retrieve_type;
1106 gchar *account_name;
1107 UpdateAccountCallback callback;
1109 TnyList *new_headers;
1110 } UpdateAccountInfo;
1114 ModestMailOperation *mail_op;
1115 TnyMimePart *mime_part;
1117 GetMimePartSizeCallback callback;
1119 } GetMimePartSizeInfo;
1121 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1122 /* We use this folder observer to track the headers that have been
1123 * added to a folder */
1126 TnyList *new_headers;
1127 } InternalFolderObserver;
1130 GObjectClass parent;
1131 } InternalFolderObserverClass;
1133 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1135 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1136 internal_folder_observer,
1138 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1142 foreach_add_item (gpointer header, gpointer user_data)
1144 tny_list_prepend (TNY_LIST (user_data),
1145 g_object_ref (G_OBJECT (header)));
1148 /* This is the method that looks for new messages in a folder */
1150 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1152 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1154 TnyFolderChangeChanged changed;
1156 changed = tny_folder_change_get_changed (change);
1158 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1161 /* Get added headers */
1162 list = tny_simple_list_new ();
1163 tny_folder_change_get_added_headers (change, list);
1165 /* Add them to the folder observer */
1166 tny_list_foreach (list, foreach_add_item,
1167 derived->new_headers);
1169 g_object_unref (G_OBJECT (list));
1174 internal_folder_observer_init (InternalFolderObserver *self)
1176 self->new_headers = tny_simple_list_new ();
1179 internal_folder_observer_finalize (GObject *object)
1181 InternalFolderObserver *self;
1183 self = (InternalFolderObserver *) object;
1184 g_object_unref (self->new_headers);
1186 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1189 tny_folder_observer_init (TnyFolderObserverIface *iface)
1191 iface->update_func = internal_folder_observer_update;
1194 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1196 GObjectClass *object_class;
1198 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1199 object_class = (GObjectClass*) klass;
1200 object_class->finalize = internal_folder_observer_finalize;
1206 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
1209 TnyList *folders = tny_simple_list_new ();
1211 tny_folder_store_get_folders (store, folders, query, NULL);
1212 iter = tny_list_create_iterator (folders);
1214 while (!tny_iterator_is_done (iter)) {
1216 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1218 tny_list_prepend (all_folders, G_OBJECT (folder));
1219 recurse_folders (folder, query, all_folders);
1220 g_object_unref (G_OBJECT (folder));
1223 tny_iterator_next (iter);
1225 g_object_unref (G_OBJECT (iter));
1226 g_object_unref (G_OBJECT (folders));
1230 * Issues the "progress-changed" signal. The timer won't be removed,
1231 * so you must call g_source_remove to stop the signal emission
1234 idle_notify_progress (gpointer data)
1236 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1237 ModestMailOperationState *state;
1239 state = modest_mail_operation_clone_state (mail_op);
1241 /* This is a GDK lock because we are an idle callback and
1242 * the handlers of this signal can contain Gtk+ code */
1244 gdk_threads_enter (); /* CHECKED */
1245 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1246 gdk_threads_leave (); /* CHECKED */
1248 g_slice_free (ModestMailOperationState, state);
1254 * Issues the "progress-changed" signal and removes the timer. It uses
1255 * a lock to ensure that the progress information of the mail
1256 * operation is not modified while there are notifications pending
1259 idle_notify_progress_once (gpointer data)
1263 pair = (ModestPair *) data;
1265 /* This is a GDK lock because we are an idle callback and
1266 * the handlers of this signal can contain Gtk+ code */
1268 gdk_threads_enter (); /* CHECKED */
1269 g_signal_emit (G_OBJECT (pair->first), signals[PROGRESS_CHANGED_SIGNAL], 0, pair->second, NULL);
1270 gdk_threads_leave (); /* CHECKED */
1272 /* Free the state and the reference to the mail operation */
1273 g_slice_free (ModestMailOperationState, (ModestMailOperationState*)pair->second);
1274 g_object_unref (pair->first);
1280 * Used to notify the queue from the main
1281 * loop. We call it inside an idle call to achieve that
1284 idle_notify_queue (gpointer data)
1286 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1288 gdk_threads_enter ();
1289 modest_mail_operation_notify_end (mail_op);
1290 gdk_threads_leave ();
1291 g_object_unref (mail_op);
1297 compare_headers_by_date (gconstpointer a,
1300 TnyHeader **header1, **header2;
1301 time_t sent1, sent2;
1303 header1 = (TnyHeader **) a;
1304 header2 = (TnyHeader **) b;
1306 sent1 = tny_header_get_date_sent (*header1);
1307 sent2 = tny_header_get_date_sent (*header2);
1309 /* We want the most recent ones (greater time_t) at the
1318 set_last_updated_idle (gpointer data)
1321 /* This is a GDK lock because we are an idle callback and
1322 * modest_account_mgr_set_last_updated can issue Gtk+ code */
1324 gdk_threads_enter (); /* CHECKED - please recheck */
1326 /* It does not matter if the time is not exactly the same than
1327 the time when this idle was called, it's just an
1328 approximation and it won't be very different */
1330 modest_account_mgr_set_last_updated (modest_runtime_get_account_mgr (),
1334 gdk_threads_leave (); /* CHECKED - please recheck */
1340 idle_update_account_cb (gpointer data)
1342 UpdateAccountInfo *idle_info;
1344 idle_info = (UpdateAccountInfo *) data;
1346 /* This is a GDK lock because we are an idle callback and
1347 * idle_info->callback can contain Gtk+ code */
1349 gdk_threads_enter (); /* CHECKED */
1350 idle_info->callback (idle_info->mail_op,
1351 idle_info->new_headers,
1352 idle_info->user_data);
1353 gdk_threads_leave (); /* CHECKED */
1356 g_object_unref (idle_info->mail_op);
1357 if (idle_info->new_headers)
1358 g_object_unref (idle_info->new_headers);
1365 get_all_folders_from_account (TnyStoreAccount *account,
1368 TnyList *all_folders = NULL;
1369 TnyIterator *iter = NULL;
1370 TnyFolderStoreQuery *query = NULL;
1372 all_folders = tny_simple_list_new ();
1373 query = tny_folder_store_query_new ();
1374 tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
1375 tny_folder_store_get_folders (TNY_FOLDER_STORE (account),
1382 g_object_unref (all_folders);
1386 iter = tny_list_create_iterator (all_folders);
1387 while (!tny_iterator_is_done (iter)) {
1388 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
1390 recurse_folders (folder, query, all_folders);
1391 g_object_unref (folder);
1393 tny_iterator_next (iter);
1395 g_object_unref (G_OBJECT (iter));
1402 update_account_thread (gpointer thr_user_data)
1404 static gboolean first_time = TRUE;
1405 UpdateAccountInfo *info = NULL;
1406 TnyList *all_folders = NULL, *new_headers = NULL;
1407 GPtrArray *new_headers_array = NULL;
1408 TnyIterator *iter = NULL;
1409 ModestMailOperationPrivate *priv = NULL;
1410 ModestTnySendQueue *send_queue = NULL;
1411 gint i = 0, timeout = 0;
1413 info = (UpdateAccountInfo *) thr_user_data;
1414 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
1416 /* Get account and set it into mail_operation */
1417 priv->account = g_object_ref (info->account);
1419 /* Get all the folders. We can do it synchronously because
1420 we're already running in a different thread than the UI */
1421 all_folders = get_all_folders_from_account (info->account, &(priv->error));
1423 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1427 /* Update status and notify. We need to call the notification
1428 with a source function in order to call it from the main
1429 loop. We need that in order not to get into trouble with
1430 Gtk+. We use a timeout in order to provide more status
1431 information, because the sync tinymail call does not
1432 provide it for the moment */
1433 timeout = g_timeout_add (100, idle_notify_progress, info->mail_op);
1435 new_headers_array = g_ptr_array_new ();
1436 iter = tny_list_create_iterator (all_folders);
1438 while (!tny_iterator_is_done (iter) && !priv->error &&
1439 priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1441 TnyFolderType folder_type;
1442 TnyFolder *folder = NULL;
1444 folder = TNY_FOLDER (tny_iterator_get_current (iter));
1445 folder_type = tny_folder_get_folder_type (folder);
1447 /* Refresh it only if it's the INBOX */
1448 if (folder_type == TNY_FOLDER_TYPE_INBOX) {
1449 InternalFolderObserver *observer = NULL;
1450 TnyIterator *new_headers_iter = NULL;
1452 /* Refresh the folder. Our observer receives
1453 * the new emails during folder refreshes, so
1454 * we can use observer->new_headers
1456 observer = g_object_new (internal_folder_observer_get_type (), NULL);
1457 tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
1459 tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
1461 new_headers_iter = tny_list_create_iterator (observer->new_headers);
1462 while (!tny_iterator_is_done (new_headers_iter)) {
1463 TnyHeader *header = NULL;
1465 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1466 /* Apply per-message size limits */
1467 if (tny_header_get_message_size (header) < info->max_size)
1468 g_ptr_array_add (new_headers_array, g_object_ref (header));
1470 g_object_unref (header);
1471 tny_iterator_next (new_headers_iter);
1473 g_object_unref (new_headers_iter);
1475 tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
1476 g_object_unref (observer);
1478 /* We no not need to do it the first time,
1479 because it's automatically done by the tree
1481 if (G_LIKELY (!first_time))
1482 tny_folder_poke_status (folder);
1484 g_object_unref (folder);
1486 tny_iterator_next (iter);
1488 g_object_unref (G_OBJECT (iter));
1489 g_source_remove (timeout);
1491 if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED &&
1492 priv->status != MODEST_MAIL_OPERATION_STATUS_FAILED &&
1493 new_headers_array->len > 0) {
1497 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1499 /* TODO: Ask the user, instead of just failing,
1500 * showing mail_nc_msg_count_limit_exceeded, with 'Get
1501 * all' and 'Newest only' buttons. */
1502 if (new_headers_array->len > info->retrieve_limit) {
1506 /* Should be get only the headers or the message as well? */
1507 if (g_ascii_strcasecmp (info->retrieve_type,
1508 MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY) != 0) {
1510 priv->total = MIN (new_headers_array->len, info->retrieve_limit);
1511 while (msg_num < priv->total) {
1513 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1514 TnyFolder *folder = tny_header_get_folder (header);
1515 TnyMsg *msg = tny_folder_get_msg (folder, header, NULL);
1516 ModestMailOperationState *state;
1520 /* We can not just use the mail operation because the
1521 values of done and total could change before the
1523 state = modest_mail_operation_clone_state (info->mail_op);
1524 pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE);
1525 g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once,
1526 pair, (GDestroyNotify) modest_pair_free);
1528 g_object_unref (msg);
1529 g_object_unref (folder);
1536 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
1539 /* Copy the headers to a list and free the array */
1540 new_headers = tny_simple_list_new ();
1541 for (i=0; i < new_headers_array->len; i++) {
1542 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1543 tny_list_append (new_headers, G_OBJECT (header));
1545 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1546 g_ptr_array_free (new_headers_array, FALSE);
1549 /* Perform send (if operation was not cancelled) */
1552 if (priv->account != NULL)
1553 g_object_unref (priv->account);
1555 if (info->transport_account) {
1556 priv->account = g_object_ref (info->transport_account);
1558 send_queue = modest_runtime_get_send_queue (info->transport_account);
1560 modest_tny_send_queue_try_to_send (send_queue);
1562 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1563 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1564 "cannot create a send queue for %s\n",
1565 tny_account_get_name (TNY_ACCOUNT (info->transport_account)));
1566 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1570 /* Check if the operation was a success */
1572 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1574 /* Update the last updated key */
1575 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1576 set_last_updated_idle,
1577 g_strdup (tny_account_get_id (TNY_ACCOUNT (info->account))),
1578 (GDestroyNotify) g_free);
1582 /* Set the account back to not busy */
1583 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr(),
1584 info->account_name, FALSE);
1586 if (info->callback) {
1587 UpdateAccountInfo *idle_info;
1589 /* This thread is not in the main lock */
1590 idle_info = g_malloc0 (sizeof (UpdateAccountInfo));
1591 idle_info->mail_op = g_object_ref (info->mail_op);
1592 idle_info->new_headers = (new_headers) ? g_object_ref (new_headers) : NULL;
1593 idle_info->callback = info->callback;
1594 idle_info->user_data = info->user_data;
1595 g_idle_add (idle_update_account_cb, idle_info);
1598 /* Notify about operation end. Note that the info could be
1599 freed before this idle happens, but the mail operation will
1601 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
1605 g_object_unref (new_headers);
1607 g_object_unref (all_folders);
1608 g_object_unref (info->account);
1609 if (info->transport_account)
1610 g_object_unref (info->transport_account);
1611 g_free (info->account_name);
1612 g_free (info->retrieve_type);
1613 g_slice_free (UpdateAccountInfo, info);
1621 modest_mail_operation_update_account (ModestMailOperation *self,
1622 const gchar *account_name,
1623 UpdateAccountCallback callback,
1626 GThread *thread = NULL;
1627 UpdateAccountInfo *info = NULL;
1628 ModestMailOperationPrivate *priv = NULL;
1629 ModestAccountMgr *mgr = NULL;
1630 TnyStoreAccount *store_account = NULL;
1631 TnyTransportAccount *transport_account = NULL;
1633 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
1634 g_return_val_if_fail (account_name, FALSE);
1636 /* Init mail operation. Set total and done to 0, and do not
1637 update them, this way the progress objects will know that
1638 we have no clue about the number of the objects */
1639 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1642 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1643 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1645 /* Get the store account */
1646 store_account = (TnyStoreAccount *)
1647 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1649 TNY_ACCOUNT_TYPE_STORE);
1651 if (!store_account) {
1652 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1653 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1654 "cannot get tny store account for %s\n", account_name);
1658 priv->account = g_object_ref (store_account);
1660 /* Get the transport account, we can not do it in the thread
1661 due to some problems with dbus */
1662 transport_account = (TnyTransportAccount *)
1663 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1665 if (!transport_account) {
1666 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1667 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1668 "cannot get tny transport account for %s\n", account_name);
1672 /* Create the helper object */
1673 info = g_slice_new (UpdateAccountInfo);
1674 info->mail_op = self;
1675 info->account = store_account;
1676 info->transport_account = transport_account;
1677 info->callback = callback;
1678 info->account_name = g_strdup (account_name);
1679 info->user_data = user_data;
1681 /* Get the message size limit */
1682 info->max_size = modest_conf_get_int (modest_runtime_get_conf (),
1683 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1684 if (info->max_size == 0)
1685 info->max_size = G_MAXINT;
1687 info->max_size = info->max_size * KB;
1689 /* Get per-account retrieval type */
1690 mgr = modest_runtime_get_account_mgr ();
1691 info->retrieve_type = modest_account_mgr_get_retrieve_type (mgr, account_name);
1693 /* Get per-account message amount retrieval limit */
1694 info->retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, account_name);
1695 if (info->retrieve_limit == 0)
1696 info->retrieve_limit = G_MAXINT;
1698 /* printf ("DEBUG: %s: info->retrieve_limit = %d\n", __FUNCTION__, info->retrieve_limit); */
1700 /* Set account busy */
1701 modest_account_mgr_set_account_busy(mgr, account_name, TRUE);
1703 modest_mail_operation_notify_start (self);
1704 thread = g_thread_create (update_account_thread, info, FALSE, NULL);
1710 g_object_unref (store_account);
1711 if (transport_account)
1712 g_object_unref (transport_account);
1713 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1715 callback (self, NULL, user_data);
1717 modest_mail_operation_notify_end (self);
1721 /* ******************************************************************* */
1722 /* ************************** STORE ACTIONS ************************* */
1723 /* ******************************************************************* */
1727 modest_mail_operation_create_folder (ModestMailOperation *self,
1728 TnyFolderStore *parent,
1731 ModestMailOperationPrivate *priv;
1732 TnyFolder *new_folder = NULL;
1734 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
1735 g_return_val_if_fail (name, NULL);
1737 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1738 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1739 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1740 g_object_ref (parent) :
1741 modest_tny_folder_get_account (TNY_FOLDER (parent));
1743 /* Check for already existing folder */
1744 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1745 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1746 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1747 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1748 _CS("ckdg_ib_folder_already_exists"));
1752 if (TNY_IS_FOLDER (parent)) {
1753 /* Check folder rules */
1754 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1755 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1756 /* Set status failed and set an error */
1757 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1758 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1759 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1760 _("mail_in_ui_folder_create_error"));
1764 if (!strcmp (name, " ") || strchr (name, '/')) {
1765 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1766 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1767 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1768 _("mail_in_ui_folder_create_error"));
1772 /* Create the folder */
1773 modest_mail_operation_notify_start (self);
1774 new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
1775 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1777 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1780 /* Notify about operation end */
1781 modest_mail_operation_notify_end (self);
1787 modest_mail_operation_remove_folder (ModestMailOperation *self,
1789 gboolean remove_to_trash)
1791 TnyAccount *account;
1792 ModestMailOperationPrivate *priv;
1793 ModestTnyFolderRules rules;
1795 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1796 g_return_if_fail (TNY_IS_FOLDER (folder));
1798 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1800 /* Check folder rules */
1801 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1802 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1803 /* Set status failed and set an error */
1804 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1805 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1806 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1807 _("mail_in_ui_folder_delete_error"));
1811 /* Get the account */
1812 account = modest_tny_folder_get_account (folder);
1813 priv->account = g_object_ref(account);
1814 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1816 /* Delete folder or move to trash */
1817 if (remove_to_trash) {
1818 TnyFolder *trash_folder = NULL;
1819 trash_folder = modest_tny_account_get_special_folder (account,
1820 TNY_FOLDER_TYPE_TRASH);
1821 /* TODO: error_handling */
1823 modest_mail_operation_notify_start (self);
1824 modest_mail_operation_xfer_folder (self, folder,
1825 TNY_FOLDER_STORE (trash_folder),
1827 g_object_unref (trash_folder);
1830 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1832 modest_mail_operation_notify_start (self);
1833 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1834 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1837 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1839 g_object_unref (parent);
1841 g_warning ("%s: could not get parent folder", __FUNCTION__);
1843 g_object_unref (G_OBJECT (account));
1846 /* Notify about operation end */
1847 modest_mail_operation_notify_end (self);
1851 transfer_folder_status_cb (GObject *obj,
1855 ModestMailOperation *self;
1856 ModestMailOperationPrivate *priv;
1857 ModestMailOperationState *state;
1858 XFerMsgAsyncHelper *helper;
1860 g_return_if_fail (status != NULL);
1861 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1863 helper = (XFerMsgAsyncHelper *) user_data;
1864 g_return_if_fail (helper != NULL);
1866 self = helper->mail_op;
1867 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1869 priv->done = status->position;
1870 priv->total = status->of_total;
1872 state = modest_mail_operation_clone_state (self);
1874 /* This is not a GDK lock because we are a Tinymail callback
1875 * which is already GDK locked by Tinymail */
1877 /* no gdk_threads_enter (), CHECKED */
1879 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1881 /* no gdk_threads_leave (), CHECKED */
1883 g_slice_free (ModestMailOperationState, state);
1888 transfer_folder_cb (TnyFolder *folder,
1890 TnyFolderStore *into,
1891 TnyFolder *new_folder,
1895 XFerMsgAsyncHelper *helper;
1896 ModestMailOperation *self = NULL;
1897 ModestMailOperationPrivate *priv = NULL;
1899 helper = (XFerMsgAsyncHelper *) user_data;
1900 g_return_if_fail (helper != NULL);
1902 self = helper->mail_op;
1903 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1906 priv->error = g_error_copy (err);
1908 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1909 } else if (cancelled) {
1910 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1911 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1912 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1913 _("Transference of %s was cancelled."),
1914 tny_folder_get_name (folder));
1917 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1920 /* Notify about operation end */
1921 modest_mail_operation_notify_end (self);
1923 /* If user defined callback function was defined, call it */
1924 if (helper->user_callback) {
1926 /* This is not a GDK lock because we are a Tinymail callback
1927 * which is already GDK locked by Tinymail */
1929 /* no gdk_threads_enter (), CHECKED */
1930 helper->user_callback (self, helper->user_data);
1931 /* no gdk_threads_leave () , CHECKED */
1935 g_object_unref (helper->mail_op);
1936 g_slice_free (XFerMsgAsyncHelper, helper);
1941 * This function checks if the new name is a valid name for our local
1942 * folders account. The new name could not be the same than then name
1943 * of any of the mandatory local folders
1945 * We can not rely on tinymail because tinymail does not check the
1946 * name of the virtual folders that the account could have in the case
1947 * that we're doing a rename (because it directly calls Camel which
1948 * knows nothing about our virtual folders).
1950 * In the case of an actual copy/move (i.e. move/copy a folder between
1951 * accounts) tinymail uses the tny_folder_store_create_account which
1952 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1953 * checks the new name of the folder, so this call in that case
1954 * wouldn't be needed. *But* NOTE that if tinymail changes its
1955 * implementation (if folder transfers within the same account is no
1956 * longer implemented as a rename) this call will allow Modest to work
1959 * If the new name is not valid, this function will set the status to
1960 * failed and will set also an error in the mail operation
1963 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1964 TnyFolderStore *into,
1965 const gchar *new_name)
1967 if (TNY_IS_ACCOUNT (into) &&
1968 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1969 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1971 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1972 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1973 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1974 _CS("ckdg_ib_folder_already_exists"));
1981 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1983 TnyFolderStore *parent,
1984 gboolean delete_original,
1985 XferAsyncUserCallback user_callback,
1988 ModestMailOperationPrivate *priv = NULL;
1989 ModestTnyFolderRules parent_rules = 0, rules;
1990 XFerMsgAsyncHelper *helper = NULL;
1991 const gchar *folder_name = NULL;
1992 const gchar *error_msg;
1994 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1995 g_return_if_fail (TNY_IS_FOLDER (folder));
1996 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1998 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1999 folder_name = tny_folder_get_name (folder);
2001 /* Set the error msg */
2002 error_msg = _("mail_in_ui_folder_move_target_error");
2004 /* Get account and set it into mail_operation */
2005 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2006 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2007 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2009 /* Get folder rules */
2010 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2011 if (TNY_IS_FOLDER (parent))
2012 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2014 /* Apply operation constraints */
2015 if ((gpointer) parent == (gpointer) folder ||
2016 (!TNY_IS_FOLDER_STORE (parent)) ||
2017 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2020 } else if (TNY_IS_FOLDER (parent) &&
2021 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2025 } else if (TNY_IS_FOLDER (parent) &&
2026 TNY_IS_FOLDER_STORE (folder) &&
2027 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2028 TNY_FOLDER_STORE (folder))) {
2029 /* Do not move a parent into a child */
2031 } else if (TNY_IS_FOLDER_STORE (parent) &&
2032 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2033 /* Check that the new folder name is not used by any
2036 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2037 /* Check that the new folder name is not used by any
2038 special local folder */
2041 /* Create the helper */
2042 helper = g_slice_new0 (XFerMsgAsyncHelper);
2043 helper->mail_op = g_object_ref (self);
2044 helper->dest_folder = NULL;
2045 helper->headers = NULL;
2046 helper->user_callback = user_callback;
2047 helper->user_data = user_data;
2049 /* Move/Copy folder */
2050 modest_mail_operation_notify_start (self);
2051 tny_folder_copy_async (folder,
2053 tny_folder_get_name (folder),
2056 transfer_folder_status_cb,
2062 /* Set status failed and set an error */
2063 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2064 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2065 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2068 /* Call the user callback if exists */
2070 user_callback (self, user_data);
2072 /* Notify the queue */
2073 modest_mail_operation_notify_end (self);
2077 modest_mail_operation_rename_folder (ModestMailOperation *self,
2081 ModestMailOperationPrivate *priv;
2082 ModestTnyFolderRules rules;
2083 XFerMsgAsyncHelper *helper;
2085 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2086 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2087 g_return_if_fail (name);
2089 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2091 /* Get account and set it into mail_operation */
2092 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2093 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2095 /* Check folder rules */
2096 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2097 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2098 /* Set status failed and set an error */
2099 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2100 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2101 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2102 _("FIXME: unable to rename"));
2104 /* Notify about operation end */
2105 modest_mail_operation_notify_end (self);
2106 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2107 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2108 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2109 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2110 _("FIXME: unable to rename"));
2111 /* Notify about operation end */
2112 modest_mail_operation_notify_end (self);
2114 TnyFolderStore *into;
2116 into = tny_folder_get_folder_store (folder);
2118 /* Check that the new folder name is not used by any
2119 special local folder */
2120 if (new_name_valid_if_local_account (priv, into, name)) {
2121 /* Create the helper */
2122 helper = g_slice_new0 (XFerMsgAsyncHelper);
2123 helper->mail_op = g_object_ref(self);
2124 helper->dest_folder = NULL;
2125 helper->headers = NULL;
2126 helper->user_callback = NULL;
2127 helper->user_data = NULL;
2129 /* Rename. Camel handles folder subscription/unsubscription */
2130 modest_mail_operation_notify_start (self);
2131 tny_folder_copy_async (folder, into, name, TRUE,
2133 transfer_folder_status_cb,
2136 modest_mail_operation_notify_end (self);
2138 g_object_unref (into);
2142 /* ******************************************************************* */
2143 /* ************************** MSG ACTIONS ************************* */
2144 /* ******************************************************************* */
2147 modest_mail_operation_get_msg (ModestMailOperation *self,
2149 GetMsgAsyncUserCallback user_callback,
2152 GetMsgInfo *helper = NULL;
2154 ModestMailOperationPrivate *priv;
2156 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2157 g_return_if_fail (TNY_IS_HEADER (header));
2159 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2160 folder = tny_header_get_folder (header);
2162 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2163 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2167 /* Get account and set it into mail_operation */
2168 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2170 /* Check for cached messages */
2171 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2172 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2174 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2176 /* Create the helper */
2177 helper = g_slice_new0 (GetMsgInfo);
2178 helper->header = g_object_ref (header);
2179 helper->mail_op = g_object_ref (self);
2180 helper->user_callback = user_callback;
2181 helper->user_data = user_data;
2182 helper->destroy_notify = NULL;
2183 helper->last_total_bytes = 0;
2184 helper->sum_total_bytes = 0;
2185 helper->total_bytes = tny_header_get_message_size (header);
2187 modest_mail_operation_notify_start (self);
2188 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2190 g_object_unref (G_OBJECT (folder));
2194 get_msg_status_cb (GObject *obj,
2198 GetMsgInfo *helper = NULL;
2200 g_return_if_fail (status != NULL);
2201 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2203 helper = (GetMsgInfo *) user_data;
2204 g_return_if_fail (helper != NULL);
2206 /* Notify progress */
2207 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2208 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2212 get_msg_async_cb (TnyFolder *folder,
2218 GetMsgInfo *info = NULL;
2219 ModestMailOperationPrivate *priv = NULL;
2222 info = (GetMsgInfo *) user_data;
2224 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2226 finished = (priv->done == priv->total) ? TRUE : FALSE;
2229 if (canceled || err) {
2230 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2232 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2233 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2236 /* Set the success status before calling the user callback */
2237 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2238 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2242 /* Call the user callback */
2243 if (info->user_callback)
2244 info->user_callback (info->mail_op, info->header, canceled,
2245 msg, err, info->user_data);
2247 /* Notify about operation end if this is the last callback */
2249 /* Free user data */
2250 if (info->destroy_notify)
2251 info->destroy_notify (info->user_data);
2253 /* Notify about operation end */
2254 modest_mail_operation_notify_end (info->mail_op);
2258 g_object_unref (info->header);
2259 g_object_unref (info->mail_op);
2260 g_slice_free (GetMsgInfo, info);
2264 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2265 TnyList *header_list,
2266 GetMsgAsyncUserCallback user_callback,
2268 GDestroyNotify notify)
2270 ModestMailOperationPrivate *priv = NULL;
2271 gboolean size_ok = TRUE;
2273 TnyIterator *iter = NULL;
2275 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2277 /* Init mail operation */
2278 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2279 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2280 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2282 priv->total = tny_list_get_length(header_list);
2284 /* Get account and set it into mail_operation */
2285 if (tny_list_get_length (header_list) >= 1) {
2286 iter = tny_list_create_iterator (header_list);
2287 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2289 TnyFolder *folder = tny_header_get_folder (header);
2291 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2292 g_object_unref (folder);
2294 g_object_unref (header);
2297 if (tny_list_get_length (header_list) == 1) {
2298 g_object_unref (iter);
2303 /* Get msg size limit */
2304 max_size = modest_conf_get_int (modest_runtime_get_conf (),
2305 MODEST_CONF_MSG_SIZE_LIMIT,
2308 g_clear_error (&(priv->error));
2309 max_size = G_MAXINT;
2311 max_size = max_size * KB;
2314 /* Check message size limits. If there is only one message
2315 always retrieve it */
2317 while (!tny_iterator_is_done (iter) && size_ok) {
2318 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2320 if (tny_header_get_message_size (header) >= max_size)
2322 g_object_unref (header);
2325 tny_iterator_next (iter);
2327 g_object_unref (iter);
2331 modest_mail_operation_notify_start (self);
2333 iter = tny_list_create_iterator (header_list);
2334 while (!tny_iterator_is_done (iter)) {
2335 GetMsgInfo *msg_info = NULL;
2336 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2337 TnyFolder *folder = tny_header_get_folder (header);
2339 /* Create the message info */
2340 msg_info = g_slice_new0 (GetMsgInfo);
2341 msg_info->mail_op = g_object_ref (self);
2342 msg_info->header = g_object_ref (header);
2343 msg_info->user_callback = user_callback;
2344 msg_info->user_data = user_data;
2345 msg_info->destroy_notify = notify;
2346 msg_info->last_total_bytes = 0;
2347 msg_info->sum_total_bytes = 0;
2348 msg_info->total_bytes = compute_message_list_size (header_list);
2350 /* The callback will call it per each header */
2351 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2353 /* Free and go on */
2354 g_object_unref (header);
2355 g_object_unref (folder);
2356 tny_iterator_next (iter);
2358 g_object_unref (iter);
2360 /* Set status failed and set an error */
2361 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2362 /* FIXME: the error msg is different for pop */
2363 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2364 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
2365 _("emev_ni_ui_imap_msg_size_exceed_error"));
2366 /* Remove from queue and free resources */
2367 modest_mail_operation_notify_end (self);
2375 modest_mail_operation_remove_msg (ModestMailOperation *self,
2377 gboolean remove_to_trash /*ignored*/)
2380 ModestMailOperationPrivate *priv;
2382 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2383 g_return_if_fail (TNY_IS_HEADER (header));
2385 if (remove_to_trash)
2386 g_warning ("remove to trash is not implemented");
2388 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2389 folder = tny_header_get_folder (header);
2391 /* Get account and set it into mail_operation */
2392 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2393 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2394 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2396 /* remove message from folder */
2397 tny_folder_remove_msg (folder, header, &(priv->error));
2399 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2400 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2402 modest_mail_operation_notify_start (self);
2404 if (TNY_IS_CAMEL_IMAP_FOLDER (folder) ||
2405 TNY_IS_CAMEL_POP_FOLDER (folder))
2406 tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /* FALSE --> dont expunge */
2408 tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /* TRUE --> expunge */
2414 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2416 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2419 g_object_unref (G_OBJECT (folder));
2421 /* Notify about operation end */
2422 modest_mail_operation_notify_end (self);
2426 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2428 gboolean remove_to_trash /*ignored*/)
2431 ModestMailOperationPrivate *priv;
2432 TnyIterator *iter = NULL;
2433 TnyHeader *header = NULL;
2434 TnyList *remove_headers = NULL;
2435 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2437 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2438 g_return_if_fail (TNY_IS_LIST (headers));
2440 if (remove_to_trash)
2441 g_warning ("remove to trash is not implemented");
2443 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2445 remove_headers = g_object_ref(headers);
2447 /* Get folder from first header and sync it */
2448 iter = tny_list_create_iterator (headers);
2449 header = TNY_HEADER (tny_iterator_get_current (iter));
2450 folder = tny_header_get_folder (header);
2452 /* Don't remove messages that are being sent */
2453 if (modest_tny_folder_is_local_folder (folder)) {
2454 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2456 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2457 TnyTransportAccount *traccount = NULL;
2458 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2459 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2461 ModestTnySendQueueStatus status;
2462 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2463 TnyIterator *iter = tny_list_create_iterator(headers);
2464 g_object_unref(remove_headers);
2465 remove_headers = TNY_LIST(tny_simple_list_new());
2466 while (!tny_iterator_is_done(iter)) {
2468 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2469 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2470 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2471 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2472 tny_list_append(remove_headers, G_OBJECT(hdr));
2474 g_object_unref(hdr);
2476 tny_iterator_next(iter);
2478 g_object_unref(iter);
2479 g_object_unref(traccount);
2483 /* Get account and set it into mail_operation */
2484 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2485 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2486 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2488 /* remove message from folder */
2489 modest_mail_operation_notify_start (self);
2491 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2493 if (TNY_IS_CAMEL_IMAP_FOLDER (folder) ||
2494 TNY_IS_CAMEL_POP_FOLDER (folder))
2495 tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /* FALSE --> don't expunge */
2498 tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /* TRUE --> expunge */
2504 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2506 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2509 g_object_unref (remove_headers);
2510 g_object_unref (header);
2511 g_object_unref (iter);
2512 g_object_unref (G_OBJECT (folder));
2514 /* Notify about operation end */
2515 modest_mail_operation_notify_end (self);
2519 notify_progress_of_multiple_messages (ModestMailOperation *self,
2521 gint *last_total_bytes,
2522 gint *sum_total_bytes,
2524 gboolean increment_done)
2526 ModestMailOperationPrivate *priv;
2527 ModestMailOperationState *state;
2528 gboolean is_num_bytes;
2530 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2532 /* We know that tinymail sends us information about
2533 transferred bytes with this particular message */
2534 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2536 state = modest_mail_operation_clone_state (self);
2537 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2538 /* We know that we're in a different message when the
2539 total number of bytes to transfer is different. Of
2540 course it could fail if we're transferring messages
2541 of the same size, but this is a workarround */
2542 if (status->of_total != *last_total_bytes) {
2543 /* We need to increment the done when there is
2544 no information about each individual
2545 message, we need to do this in message
2546 transfers, and we don't do it for getting
2550 *sum_total_bytes += *last_total_bytes;
2551 *last_total_bytes = status->of_total;
2553 state->bytes_done += status->position + *sum_total_bytes;
2554 state->bytes_total = total_bytes;
2556 /* Notify the status change. Only notify about changes
2557 referred to bytes */
2558 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2562 g_slice_free (ModestMailOperationState, state);
2566 transfer_msgs_status_cb (GObject *obj,
2570 XFerMsgAsyncHelper *helper;
2572 g_return_if_fail (status != NULL);
2573 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2575 helper = (XFerMsgAsyncHelper *) user_data;
2576 g_return_if_fail (helper != NULL);
2578 /* Notify progress */
2579 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2580 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2585 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2587 XFerMsgAsyncHelper *helper;
2588 ModestMailOperation *self;
2589 ModestMailOperationPrivate *priv;
2590 TnyIterator *iter = NULL;
2591 TnyHeader *header = NULL;
2593 helper = (XFerMsgAsyncHelper *) user_data;
2594 self = helper->mail_op;
2596 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2599 priv->error = g_error_copy (err);
2601 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2602 } else if (cancelled) {
2603 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2604 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2605 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2606 _("Error trying to refresh the contents of %s"),
2607 tny_folder_get_name (folder));
2610 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2612 /* Update folder counts */
2613 tny_folder_poke_status (folder);
2614 tny_folder_poke_status (helper->dest_folder);
2618 /* Mark headers as deleted and seen */
2619 if ((helper->delete) &&
2620 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2621 iter = tny_list_create_iterator (helper->headers);
2622 while (!tny_iterator_is_done (iter)) {
2623 header = TNY_HEADER (tny_iterator_get_current (iter));
2624 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2625 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2626 g_object_unref (header);
2628 tny_iterator_next (iter);
2634 /* Notify about operation end */
2635 modest_mail_operation_notify_end (self);
2637 /* If user defined callback function was defined, call it */
2638 if (helper->user_callback) {
2639 /* This is not a GDK lock because we are a Tinymail callback and
2640 * Tinymail already acquires the Gdk lock */
2642 /* no gdk_threads_enter (), CHECKED */
2643 helper->user_callback (self, helper->user_data);
2644 /* no gdk_threads_leave (), CHECKED */
2648 if (helper->headers)
2649 g_object_unref (helper->headers);
2650 if (helper->dest_folder)
2651 g_object_unref (helper->dest_folder);
2652 if (helper->mail_op)
2653 g_object_unref (helper->mail_op);
2655 g_object_unref (folder);
2657 g_object_unref (iter);
2658 g_slice_free (XFerMsgAsyncHelper, helper);
2662 compute_message_list_size (TnyList *headers)
2667 iter = tny_list_create_iterator (headers);
2668 while (!tny_iterator_is_done (iter)) {
2669 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2670 size += tny_header_get_message_size (header);
2671 g_object_unref (header);
2672 tny_iterator_next (iter);
2674 g_object_unref (iter);
2680 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2683 gboolean delete_original,
2684 XferAsyncUserCallback user_callback,
2687 ModestMailOperationPrivate *priv = NULL;
2688 TnyIterator *iter = NULL;
2689 TnyFolder *src_folder = NULL;
2690 XFerMsgAsyncHelper *helper = NULL;
2691 TnyHeader *header = NULL;
2692 ModestTnyFolderRules rules = 0;
2694 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2695 g_return_if_fail (headers && TNY_IS_LIST (headers));
2696 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2698 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2699 priv->total = tny_list_get_length (headers);
2701 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2702 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2704 /* Apply folder rules */
2705 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2706 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2707 /* Set status failed and set an error */
2708 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2709 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2710 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2711 _CS("ckct_ib_unable_to_paste_here"));
2712 /* Notify the queue */
2713 modest_mail_operation_notify_end (self);
2717 /* Get source folder */
2718 iter = tny_list_create_iterator (headers);
2719 header = TNY_HEADER (tny_iterator_get_current (iter));
2721 src_folder = tny_header_get_folder (header);
2722 g_object_unref (header);
2724 g_object_unref (iter);
2726 if (src_folder == NULL) {
2727 /* Notify the queue */
2728 modest_mail_operation_notify_end (self);
2730 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2735 /* Check folder source and destination */
2736 if (src_folder == folder) {
2737 /* Set status failed and set an error */
2738 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2739 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2740 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2741 _("mcen_ib_unable_to_copy_samefolder"));
2743 /* Notify the queue */
2744 modest_mail_operation_notify_end (self);
2747 g_object_unref (src_folder);
2751 /* Create the helper */
2752 helper = g_slice_new0 (XFerMsgAsyncHelper);
2753 helper->mail_op = g_object_ref(self);
2754 helper->dest_folder = g_object_ref(folder);
2755 helper->headers = g_object_ref(headers);
2756 helper->user_callback = user_callback;
2757 helper->user_data = user_data;
2758 helper->delete = delete_original;
2759 helper->last_total_bytes = 0;
2760 helper->sum_total_bytes = 0;
2761 helper->total_bytes = compute_message_list_size (headers);
2763 /* Get account and set it into mail_operation */
2764 priv->account = modest_tny_folder_get_account (src_folder);
2766 /* Transfer messages */
2767 modest_mail_operation_notify_start (self);
2768 tny_folder_transfer_msgs_async (src_folder,
2773 transfer_msgs_status_cb,
2779 on_refresh_folder (TnyFolder *folder,
2784 RefreshAsyncHelper *helper = NULL;
2785 ModestMailOperation *self = NULL;
2786 ModestMailOperationPrivate *priv = NULL;
2788 helper = (RefreshAsyncHelper *) user_data;
2789 self = helper->mail_op;
2790 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2792 g_return_if_fail(priv!=NULL);
2795 priv->error = g_error_copy (error);
2796 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2801 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2802 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2803 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2804 _("Error trying to refresh the contents of %s"),
2805 tny_folder_get_name (folder));
2809 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2812 /* Call user defined callback, if it exists */
2813 if (helper->user_callback) {
2815 /* This is not a GDK lock because we are a Tinymail callback and
2816 * Tinymail already acquires the Gdk lock */
2817 helper->user_callback (self, folder, helper->user_data);
2821 g_slice_free (RefreshAsyncHelper, helper);
2823 /* Notify about operation end */
2824 modest_mail_operation_notify_end (self);
2825 g_object_unref(self);
2829 on_refresh_folder_status_update (GObject *obj,
2833 RefreshAsyncHelper *helper = NULL;
2834 ModestMailOperation *self = NULL;
2835 ModestMailOperationPrivate *priv = NULL;
2836 ModestMailOperationState *state;
2838 g_return_if_fail (user_data != NULL);
2839 g_return_if_fail (status != NULL);
2840 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2842 helper = (RefreshAsyncHelper *) user_data;
2843 self = helper->mail_op;
2844 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2846 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2848 priv->done = status->position;
2849 priv->total = status->of_total;
2851 state = modest_mail_operation_clone_state (self);
2853 /* This is not a GDK lock because we are a Tinymail callback and
2854 * Tinymail already acquires the Gdk lock */
2855 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2857 g_slice_free (ModestMailOperationState, state);
2861 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2863 RefreshAsyncUserCallback user_callback,
2866 ModestMailOperationPrivate *priv = NULL;
2867 RefreshAsyncHelper *helper = NULL;
2869 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2871 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2873 /* Get account and set it into mail_operation */
2874 priv->account = modest_tny_folder_get_account (folder);
2875 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2877 /* Create the helper */
2878 helper = g_slice_new0 (RefreshAsyncHelper);
2879 helper->mail_op = g_object_ref(self);
2880 helper->user_callback = user_callback;
2881 helper->user_data = user_data;
2883 /* Refresh the folder. TODO: tinymail could issue a status
2884 updates before the callback call then this could happen. We
2885 must review the design */
2886 modest_mail_operation_notify_start (self);
2887 tny_folder_refresh_async (folder,
2889 on_refresh_folder_status_update,
2895 modest_mail_operation_notify_start (ModestMailOperation *self)
2897 ModestMailOperationPrivate *priv = NULL;
2899 g_return_if_fail (self);
2901 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2903 /* Ensure that all the fields are filled correctly */
2904 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2906 /* Notify the observers about the mail operation. We do not
2907 wrapp this emission because we assume that this function is
2908 always called from within the main lock */
2909 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2914 * It's used by the mail operation queue to notify the observers
2915 * attached to that signal that the operation finished. We need to use
2916 * that because tinymail does not give us the progress of a given
2917 * operation when it finishes (it directly calls the operation
2921 modest_mail_operation_notify_end (ModestMailOperation *self)
2923 ModestMailOperationPrivate *priv = NULL;
2925 g_return_if_fail (self);
2927 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2929 /* Notify the observers about the mail operation end. We do
2930 not wrapp this emission because we assume that this
2931 function is always called from within the main lock */
2932 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2934 /* Remove the error user data */
2935 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2936 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2940 modest_mail_operation_get_account (ModestMailOperation *self)
2942 ModestMailOperationPrivate *priv = NULL;
2944 g_return_val_if_fail (self, NULL);
2946 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2948 return (priv->account) ? g_object_ref (priv->account) : NULL;
2952 modest_mail_operation_noop (ModestMailOperation *self)
2954 ModestMailOperationPrivate *priv = NULL;
2956 g_return_if_fail (self);
2958 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2959 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2960 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2964 /* This mail operation does nothing actually */
2965 modest_mail_operation_notify_start (self);
2966 modest_mail_operation_notify_end (self);