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;
599 SendMsgInfo *info = g_slice_new0 (SendMsgInfo);
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;
621 /* Add the msg to the queue */
622 modest_mail_operation_notify_start (self);
623 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
627 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
630 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)
631 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
633 info->mail_op = g_object_ref (self);
634 info->msg = g_object_ref (msg);
635 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
636 G_CALLBACK (send_mail_msg_sent_handler), info);
637 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
638 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);
883 modest_mail_operation_notify_end (self);
887 modest_mail_operation_send_new_mail (ModestMailOperation *self,
888 TnyTransportAccount *transport_account,
890 const gchar *from, const gchar *to,
891 const gchar *cc, const gchar *bcc,
892 const gchar *subject, const gchar *plain_body,
893 const gchar *html_body,
894 const GList *attachments_list,
895 const GList *images_list,
896 TnyHeaderFlags priority_flags)
898 ModestMailOperationPrivate *priv = NULL;
899 SendNewMailInfo *info;
901 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
902 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
904 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
905 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
906 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
908 /* Check parametters */
910 /* Set status failed and set an error */
911 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
912 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
913 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
914 _("Error trying to send a mail. You need to set at least one recipient"));
917 info = g_slice_new0 (SendNewMailInfo);
918 info->transport_account = transport_account;
919 if (transport_account)
920 g_object_ref (transport_account);
921 info->draft_msg = draft_msg;
923 g_object_ref (draft_msg);
926 modest_mail_operation_notify_start (self);
927 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
928 attachments_list, images_list, priority_flags,
929 modest_mail_operation_send_new_mail_cb, info);
935 TnyTransportAccount *transport_account;
937 SaveToDraftstCallback callback;
941 ModestMailOperation *mailop;
942 } SaveToDraftsAddMsgInfo;
945 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
950 ModestMailOperationPrivate *priv = NULL;
951 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
953 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
956 g_warning ("%s: priv->error != NULL", __FUNCTION__);
957 g_error_free(priv->error);
960 priv->error = (err == NULL) ? NULL : g_error_copy(err);
962 if ((!priv->error) && (info->draft_msg != NULL)) {
963 TnyHeader *header = tny_msg_get_header (info->draft_msg);
964 TnyFolder *src_folder = tny_header_get_folder (header);
966 /* Remove the old draft */
967 tny_folder_remove_msg (src_folder, header, NULL);
969 /* Synchronize to expunge and to update the msg counts */
970 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
971 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
973 g_object_unref (G_OBJECT(header));
974 g_object_unref (G_OBJECT(src_folder));
978 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
980 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
982 /* Call the user callback */
984 info->callback (info->mailop, info->msg, info->user_data);
986 if (info->transport_account)
987 g_object_unref (G_OBJECT(info->transport_account));
989 g_object_unref (G_OBJECT (info->draft_msg));
991 g_object_unref (G_OBJECT(info->drafts));
993 g_object_unref (G_OBJECT (info->msg));
994 g_slice_free (SaveToDraftsAddMsgInfo, info);
996 modest_mail_operation_notify_end (info->mailop);
997 g_object_unref(info->mailop);
1002 TnyTransportAccount *transport_account;
1004 SaveToDraftstCallback callback;
1009 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1013 TnyFolder *drafts = NULL;
1014 ModestMailOperationPrivate *priv = NULL;
1015 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1017 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1020 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1021 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1022 "modest: failed to create a new msg\n");
1024 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1025 TNY_FOLDER_TYPE_DRAFTS);
1027 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1028 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1029 "modest: failed to create a new msg\n");
1034 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1035 cb_info->transport_account = g_object_ref(info->transport_account);
1036 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1037 cb_info->callback = info->callback;
1038 cb_info->user_data = info->user_data;
1039 cb_info->drafts = g_object_ref(drafts);
1040 cb_info->msg = g_object_ref(msg);
1041 cb_info->mailop = g_object_ref(self);
1042 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1045 /* Call the user callback */
1046 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1048 info->callback (self, msg, info->user_data);
1049 modest_mail_operation_notify_end (self);
1053 g_object_unref (G_OBJECT(drafts));
1054 if (info->draft_msg)
1055 g_object_unref (G_OBJECT (info->draft_msg));
1056 if (info->transport_account)
1057 g_object_unref (G_OBJECT(info->transport_account));
1058 g_slice_free (SaveToDraftsInfo, info);
1062 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1063 TnyTransportAccount *transport_account,
1065 const gchar *from, const gchar *to,
1066 const gchar *cc, const gchar *bcc,
1067 const gchar *subject, const gchar *plain_body,
1068 const gchar *html_body,
1069 const GList *attachments_list,
1070 const GList *images_list,
1071 TnyHeaderFlags priority_flags,
1072 SaveToDraftstCallback callback,
1075 ModestMailOperationPrivate *priv = NULL;
1076 SaveToDraftsInfo *info = NULL;
1078 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1079 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1081 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1083 /* Get account and set it into mail_operation */
1084 priv->account = g_object_ref (transport_account);
1085 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1087 info = g_slice_new0 (SaveToDraftsInfo);
1088 info->transport_account = g_object_ref (transport_account);
1089 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1090 info->callback = callback;
1091 info->user_data = user_data;
1093 modest_mail_operation_notify_start (self);
1094 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1095 attachments_list, images_list, priority_flags,
1096 modest_mail_operation_save_to_drafts_cb, info);
1101 ModestMailOperation *mail_op;
1102 TnyStoreAccount *account;
1103 TnyTransportAccount *transport_account;
1105 gint retrieve_limit;
1106 gchar *retrieve_type;
1107 gchar *account_name;
1108 UpdateAccountCallback callback;
1110 TnyList *new_headers;
1111 } UpdateAccountInfo;
1115 ModestMailOperation *mail_op;
1116 TnyMimePart *mime_part;
1118 GetMimePartSizeCallback callback;
1120 } GetMimePartSizeInfo;
1122 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1123 /* We use this folder observer to track the headers that have been
1124 * added to a folder */
1127 TnyList *new_headers;
1128 } InternalFolderObserver;
1131 GObjectClass parent;
1132 } InternalFolderObserverClass;
1134 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1136 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1137 internal_folder_observer,
1139 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1143 foreach_add_item (gpointer header, gpointer user_data)
1145 tny_list_prepend (TNY_LIST (user_data),
1146 g_object_ref (G_OBJECT (header)));
1149 /* This is the method that looks for new messages in a folder */
1151 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1153 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1155 TnyFolderChangeChanged changed;
1157 changed = tny_folder_change_get_changed (change);
1159 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1162 /* Get added headers */
1163 list = tny_simple_list_new ();
1164 tny_folder_change_get_added_headers (change, list);
1166 /* Add them to the folder observer */
1167 tny_list_foreach (list, foreach_add_item,
1168 derived->new_headers);
1170 g_object_unref (G_OBJECT (list));
1175 internal_folder_observer_init (InternalFolderObserver *self)
1177 self->new_headers = tny_simple_list_new ();
1180 internal_folder_observer_finalize (GObject *object)
1182 InternalFolderObserver *self;
1184 self = (InternalFolderObserver *) object;
1185 g_object_unref (self->new_headers);
1187 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1190 tny_folder_observer_init (TnyFolderObserverIface *iface)
1192 iface->update_func = internal_folder_observer_update;
1195 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1197 GObjectClass *object_class;
1199 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1200 object_class = (GObjectClass*) klass;
1201 object_class->finalize = internal_folder_observer_finalize;
1207 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
1210 TnyList *folders = tny_simple_list_new ();
1212 tny_folder_store_get_folders (store, folders, query, NULL);
1213 iter = tny_list_create_iterator (folders);
1215 while (!tny_iterator_is_done (iter)) {
1217 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1219 tny_list_prepend (all_folders, G_OBJECT (folder));
1220 recurse_folders (folder, query, all_folders);
1221 g_object_unref (G_OBJECT (folder));
1224 tny_iterator_next (iter);
1226 g_object_unref (G_OBJECT (iter));
1227 g_object_unref (G_OBJECT (folders));
1231 * Issues the "progress-changed" signal. The timer won't be removed,
1232 * so you must call g_source_remove to stop the signal emission
1235 idle_notify_progress (gpointer data)
1237 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1238 ModestMailOperationState *state;
1240 state = modest_mail_operation_clone_state (mail_op);
1242 /* This is a GDK lock because we are an idle callback and
1243 * the handlers of this signal can contain Gtk+ code */
1245 gdk_threads_enter (); /* CHECKED */
1246 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1247 gdk_threads_leave (); /* CHECKED */
1249 g_slice_free (ModestMailOperationState, state);
1255 * Issues the "progress-changed" signal and removes the timer. It uses
1256 * a lock to ensure that the progress information of the mail
1257 * operation is not modified while there are notifications pending
1260 idle_notify_progress_once (gpointer data)
1264 pair = (ModestPair *) data;
1266 /* This is a GDK lock because we are an idle callback and
1267 * the handlers of this signal can contain Gtk+ code */
1269 gdk_threads_enter (); /* CHECKED */
1270 g_signal_emit (G_OBJECT (pair->first), signals[PROGRESS_CHANGED_SIGNAL], 0, pair->second, NULL);
1271 gdk_threads_leave (); /* CHECKED */
1273 /* Free the state and the reference to the mail operation */
1274 g_slice_free (ModestMailOperationState, (ModestMailOperationState*)pair->second);
1275 g_object_unref (pair->first);
1281 * Used to notify the queue from the main
1282 * loop. We call it inside an idle call to achieve that
1285 idle_notify_queue (gpointer data)
1287 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1289 gdk_threads_enter ();
1290 modest_mail_operation_notify_end (mail_op);
1291 gdk_threads_leave ();
1292 g_object_unref (mail_op);
1298 compare_headers_by_date (gconstpointer a,
1301 TnyHeader **header1, **header2;
1302 time_t sent1, sent2;
1304 header1 = (TnyHeader **) a;
1305 header2 = (TnyHeader **) b;
1307 sent1 = tny_header_get_date_sent (*header1);
1308 sent2 = tny_header_get_date_sent (*header2);
1310 /* We want the most recent ones (greater time_t) at the
1319 set_last_updated_idle (gpointer data)
1322 /* This is a GDK lock because we are an idle callback and
1323 * modest_account_mgr_set_last_updated can issue Gtk+ code */
1325 gdk_threads_enter (); /* CHECKED - please recheck */
1327 /* It does not matter if the time is not exactly the same than
1328 the time when this idle was called, it's just an
1329 approximation and it won't be very different */
1331 modest_account_mgr_set_last_updated (modest_runtime_get_account_mgr (),
1335 gdk_threads_leave (); /* CHECKED - please recheck */
1341 idle_update_account_cb (gpointer data)
1343 UpdateAccountInfo *idle_info;
1345 idle_info = (UpdateAccountInfo *) data;
1347 /* This is a GDK lock because we are an idle callback and
1348 * idle_info->callback can contain Gtk+ code */
1350 gdk_threads_enter (); /* CHECKED */
1351 idle_info->callback (idle_info->mail_op,
1352 idle_info->new_headers,
1353 idle_info->user_data);
1354 gdk_threads_leave (); /* CHECKED */
1357 g_object_unref (idle_info->mail_op);
1358 if (idle_info->new_headers)
1359 g_object_unref (idle_info->new_headers);
1366 get_all_folders_from_account (TnyStoreAccount *account,
1369 TnyList *all_folders = NULL;
1370 TnyIterator *iter = NULL;
1371 TnyFolderStoreQuery *query = NULL;
1373 all_folders = tny_simple_list_new ();
1374 query = tny_folder_store_query_new ();
1375 tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
1376 tny_folder_store_get_folders (TNY_FOLDER_STORE (account),
1383 g_object_unref (all_folders);
1387 iter = tny_list_create_iterator (all_folders);
1388 while (!tny_iterator_is_done (iter)) {
1389 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
1391 recurse_folders (folder, query, all_folders);
1392 g_object_unref (folder);
1394 tny_iterator_next (iter);
1396 g_object_unref (G_OBJECT (iter));
1403 update_account_thread (gpointer thr_user_data)
1405 static gboolean first_time = TRUE;
1406 UpdateAccountInfo *info = NULL;
1407 TnyList *all_folders = NULL, *new_headers = NULL;
1408 GPtrArray *new_headers_array = NULL;
1409 TnyIterator *iter = NULL;
1410 ModestMailOperationPrivate *priv = NULL;
1411 ModestTnySendQueue *send_queue = NULL;
1412 gint i = 0, timeout = 0;
1414 info = (UpdateAccountInfo *) thr_user_data;
1415 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
1417 /* Get account and set it into mail_operation */
1418 priv->account = g_object_ref (info->account);
1420 /* Get all the folders. We can do it synchronously because
1421 we're already running in a different thread than the UI */
1422 all_folders = get_all_folders_from_account (info->account, &(priv->error));
1424 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1428 /* Update status and notify. We need to call the notification
1429 with a source function in order to call it from the main
1430 loop. We need that in order not to get into trouble with
1431 Gtk+. We use a timeout in order to provide more status
1432 information, because the sync tinymail call does not
1433 provide it for the moment */
1434 timeout = g_timeout_add (100, idle_notify_progress, info->mail_op);
1436 new_headers_array = g_ptr_array_new ();
1437 iter = tny_list_create_iterator (all_folders);
1439 while (!tny_iterator_is_done (iter) && !priv->error &&
1440 priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1442 TnyFolderType folder_type;
1443 TnyFolder *folder = NULL;
1445 folder = TNY_FOLDER (tny_iterator_get_current (iter));
1446 folder_type = tny_folder_get_folder_type (folder);
1448 /* Refresh it only if it's the INBOX */
1449 if (folder_type == TNY_FOLDER_TYPE_INBOX) {
1450 InternalFolderObserver *observer = NULL;
1451 TnyIterator *new_headers_iter = NULL;
1453 /* Refresh the folder. Our observer receives
1454 * the new emails during folder refreshes, so
1455 * we can use observer->new_headers
1457 observer = g_object_new (internal_folder_observer_get_type (), NULL);
1458 tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
1460 tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
1462 new_headers_iter = tny_list_create_iterator (observer->new_headers);
1463 while (!tny_iterator_is_done (new_headers_iter)) {
1464 TnyHeader *header = NULL;
1466 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1467 /* Apply per-message size limits */
1468 if (tny_header_get_message_size (header) < info->max_size)
1469 g_ptr_array_add (new_headers_array, g_object_ref (header));
1471 g_object_unref (header);
1472 tny_iterator_next (new_headers_iter);
1474 g_object_unref (new_headers_iter);
1476 tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
1477 g_object_unref (observer);
1479 /* We no not need to do it the first time,
1480 because it's automatically done by the tree
1482 if (G_LIKELY (!first_time))
1483 tny_folder_poke_status (folder);
1485 g_object_unref (folder);
1487 tny_iterator_next (iter);
1489 g_object_unref (G_OBJECT (iter));
1490 g_source_remove (timeout);
1492 if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED &&
1493 priv->status != MODEST_MAIL_OPERATION_STATUS_FAILED &&
1494 new_headers_array->len > 0) {
1498 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1500 /* TODO: Ask the user, instead of just failing,
1501 * showing mail_nc_msg_count_limit_exceeded, with 'Get
1502 * all' and 'Newest only' buttons. */
1503 if (new_headers_array->len > info->retrieve_limit) {
1507 /* Should be get only the headers or the message as well? */
1508 if (g_ascii_strcasecmp (info->retrieve_type,
1509 MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY) != 0) {
1511 priv->total = MIN (new_headers_array->len, info->retrieve_limit);
1512 while (msg_num < priv->total) {
1514 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1515 TnyFolder *folder = tny_header_get_folder (header);
1516 TnyMsg *msg = tny_folder_get_msg (folder, header, NULL);
1517 ModestMailOperationState *state;
1521 /* We can not just use the mail operation because the
1522 values of done and total could change before the
1524 state = modest_mail_operation_clone_state (info->mail_op);
1525 pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE);
1526 g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once,
1527 pair, (GDestroyNotify) modest_pair_free);
1529 g_object_unref (msg);
1530 g_object_unref (folder);
1537 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
1540 /* Copy the headers to a list and free the array */
1541 new_headers = tny_simple_list_new ();
1542 for (i=0; i < new_headers_array->len; i++) {
1543 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1544 tny_list_append (new_headers, G_OBJECT (header));
1546 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1547 g_ptr_array_free (new_headers_array, FALSE);
1550 /* Perform send (if operation was not cancelled) */
1553 if (priv->account != NULL)
1554 g_object_unref (priv->account);
1556 if (info->transport_account) {
1557 priv->account = g_object_ref (info->transport_account);
1559 send_queue = modest_runtime_get_send_queue (info->transport_account);
1561 modest_tny_send_queue_try_to_send (send_queue);
1563 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1564 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1565 "cannot create a send queue for %s\n",
1566 tny_account_get_name (TNY_ACCOUNT (info->transport_account)));
1567 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1571 /* Check if the operation was a success */
1573 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1575 /* Update the last updated key */
1576 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1577 set_last_updated_idle,
1578 g_strdup (tny_account_get_id (TNY_ACCOUNT (info->account))),
1579 (GDestroyNotify) g_free);
1583 /* Set the account back to not busy */
1584 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr(),
1585 info->account_name, FALSE);
1587 if (info->callback) {
1588 UpdateAccountInfo *idle_info;
1590 /* This thread is not in the main lock */
1591 idle_info = g_malloc0 (sizeof (UpdateAccountInfo));
1592 idle_info->mail_op = g_object_ref (info->mail_op);
1593 idle_info->new_headers = (new_headers) ? g_object_ref (new_headers) : NULL;
1594 idle_info->callback = info->callback;
1595 idle_info->user_data = info->user_data;
1596 g_idle_add (idle_update_account_cb, idle_info);
1599 /* Notify about operation end. Note that the info could be
1600 freed before this idle happens, but the mail operation will
1602 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
1606 g_object_unref (new_headers);
1608 g_object_unref (all_folders);
1609 g_object_unref (info->account);
1610 if (info->transport_account)
1611 g_object_unref (info->transport_account);
1612 g_free (info->account_name);
1613 g_free (info->retrieve_type);
1614 g_slice_free (UpdateAccountInfo, info);
1622 modest_mail_operation_update_account (ModestMailOperation *self,
1623 const gchar *account_name,
1624 UpdateAccountCallback callback,
1627 GThread *thread = NULL;
1628 UpdateAccountInfo *info = NULL;
1629 ModestMailOperationPrivate *priv = NULL;
1630 ModestAccountMgr *mgr = NULL;
1631 TnyStoreAccount *store_account = NULL;
1632 TnyTransportAccount *transport_account = NULL;
1634 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
1635 g_return_val_if_fail (account_name, FALSE);
1637 /* Init mail operation. Set total and done to 0, and do not
1638 update them, this way the progress objects will know that
1639 we have no clue about the number of the objects */
1640 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1643 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1644 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1646 /* Get the store account */
1647 store_account = (TnyStoreAccount *)
1648 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1650 TNY_ACCOUNT_TYPE_STORE);
1652 if (!store_account) {
1653 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1654 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1655 "cannot get tny store account for %s\n", account_name);
1659 priv->account = g_object_ref (store_account);
1661 /* Get the transport account, we can not do it in the thread
1662 due to some problems with dbus */
1663 transport_account = (TnyTransportAccount *)
1664 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1666 if (!transport_account) {
1667 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1668 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1669 "cannot get tny transport account for %s\n", account_name);
1673 /* Create the helper object */
1674 info = g_slice_new (UpdateAccountInfo);
1675 info->mail_op = self;
1676 info->account = store_account;
1677 info->transport_account = transport_account;
1678 info->callback = callback;
1679 info->account_name = g_strdup (account_name);
1680 info->user_data = user_data;
1682 /* Get the message size limit */
1683 info->max_size = modest_conf_get_int (modest_runtime_get_conf (),
1684 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1685 if (info->max_size == 0)
1686 info->max_size = G_MAXINT;
1688 info->max_size = info->max_size * KB;
1690 /* Get per-account retrieval type */
1691 mgr = modest_runtime_get_account_mgr ();
1692 info->retrieve_type = modest_account_mgr_get_retrieve_type (mgr, account_name);
1694 /* Get per-account message amount retrieval limit */
1695 info->retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, account_name);
1696 if (info->retrieve_limit == 0)
1697 info->retrieve_limit = G_MAXINT;
1699 /* printf ("DEBUG: %s: info->retrieve_limit = %d\n", __FUNCTION__, info->retrieve_limit); */
1701 /* Set account busy */
1702 modest_account_mgr_set_account_busy(mgr, account_name, TRUE);
1704 modest_mail_operation_notify_start (self);
1705 thread = g_thread_create (update_account_thread, info, FALSE, NULL);
1711 g_object_unref (store_account);
1712 if (transport_account)
1713 g_object_unref (transport_account);
1714 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1716 callback (self, NULL, user_data);
1718 modest_mail_operation_notify_end (self);
1722 /* ******************************************************************* */
1723 /* ************************** STORE ACTIONS ************************* */
1724 /* ******************************************************************* */
1728 modest_mail_operation_create_folder (ModestMailOperation *self,
1729 TnyFolderStore *parent,
1732 ModestMailOperationPrivate *priv;
1733 TnyFolder *new_folder = NULL;
1735 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
1736 g_return_val_if_fail (name, NULL);
1738 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1739 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1740 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1741 g_object_ref (parent) :
1742 modest_tny_folder_get_account (TNY_FOLDER (parent));
1744 /* Check for already existing folder */
1745 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1746 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1747 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1748 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1749 _CS("ckdg_ib_folder_already_exists"));
1753 if (TNY_IS_FOLDER (parent)) {
1754 /* Check folder rules */
1755 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1756 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1757 /* Set status failed and set an error */
1758 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1759 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1760 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1761 _("mail_in_ui_folder_create_error"));
1765 if (!strcmp (name, " ") || strchr (name, '/')) {
1766 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1767 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1768 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1769 _("mail_in_ui_folder_create_error"));
1773 /* Create the folder */
1774 modest_mail_operation_notify_start (self);
1775 new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
1776 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1778 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1781 /* Notify about operation end */
1782 modest_mail_operation_notify_end (self);
1788 modest_mail_operation_remove_folder (ModestMailOperation *self,
1790 gboolean remove_to_trash)
1792 TnyAccount *account;
1793 ModestMailOperationPrivate *priv;
1794 ModestTnyFolderRules rules;
1796 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1797 g_return_if_fail (TNY_IS_FOLDER (folder));
1799 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1801 /* Check folder rules */
1802 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1803 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1804 /* Set status failed and set an error */
1805 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1806 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1807 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1808 _("mail_in_ui_folder_delete_error"));
1812 /* Get the account */
1813 account = modest_tny_folder_get_account (folder);
1814 priv->account = g_object_ref(account);
1815 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1817 /* Delete folder or move to trash */
1818 if (remove_to_trash) {
1819 TnyFolder *trash_folder = NULL;
1820 trash_folder = modest_tny_account_get_special_folder (account,
1821 TNY_FOLDER_TYPE_TRASH);
1822 /* TODO: error_handling */
1824 modest_mail_operation_notify_start (self);
1825 modest_mail_operation_xfer_folder (self, folder,
1826 TNY_FOLDER_STORE (trash_folder),
1828 g_object_unref (trash_folder);
1831 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1833 modest_mail_operation_notify_start (self);
1834 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1835 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1838 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1840 g_object_unref (parent);
1842 g_warning ("%s: could not get parent folder", __FUNCTION__);
1844 g_object_unref (G_OBJECT (account));
1847 /* Notify about operation end */
1848 modest_mail_operation_notify_end (self);
1852 transfer_folder_status_cb (GObject *obj,
1856 ModestMailOperation *self;
1857 ModestMailOperationPrivate *priv;
1858 ModestMailOperationState *state;
1859 XFerMsgAsyncHelper *helper;
1861 g_return_if_fail (status != NULL);
1862 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1864 helper = (XFerMsgAsyncHelper *) user_data;
1865 g_return_if_fail (helper != NULL);
1867 self = helper->mail_op;
1868 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1870 priv->done = status->position;
1871 priv->total = status->of_total;
1873 state = modest_mail_operation_clone_state (self);
1875 /* This is not a GDK lock because we are a Tinymail callback
1876 * which is already GDK locked by Tinymail */
1878 /* no gdk_threads_enter (), CHECKED */
1880 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1882 /* no gdk_threads_leave (), CHECKED */
1884 g_slice_free (ModestMailOperationState, state);
1889 transfer_folder_cb (TnyFolder *folder,
1891 TnyFolderStore *into,
1892 TnyFolder *new_folder,
1896 XFerMsgAsyncHelper *helper;
1897 ModestMailOperation *self = NULL;
1898 ModestMailOperationPrivate *priv = NULL;
1900 helper = (XFerMsgAsyncHelper *) user_data;
1901 g_return_if_fail (helper != NULL);
1903 self = helper->mail_op;
1904 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1907 priv->error = g_error_copy (err);
1909 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1910 } else if (cancelled) {
1911 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1912 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1913 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1914 _("Transference of %s was cancelled."),
1915 tny_folder_get_name (folder));
1918 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1921 /* Notify about operation end */
1922 modest_mail_operation_notify_end (self);
1924 /* If user defined callback function was defined, call it */
1925 if (helper->user_callback) {
1927 /* This is not a GDK lock because we are a Tinymail callback
1928 * which is already GDK locked by Tinymail */
1930 /* no gdk_threads_enter (), CHECKED */
1931 helper->user_callback (self, helper->user_data);
1932 /* no gdk_threads_leave () , CHECKED */
1936 g_object_unref (helper->mail_op);
1937 g_slice_free (XFerMsgAsyncHelper, helper);
1942 * This function checks if the new name is a valid name for our local
1943 * folders account. The new name could not be the same than then name
1944 * of any of the mandatory local folders
1946 * We can not rely on tinymail because tinymail does not check the
1947 * name of the virtual folders that the account could have in the case
1948 * that we're doing a rename (because it directly calls Camel which
1949 * knows nothing about our virtual folders).
1951 * In the case of an actual copy/move (i.e. move/copy a folder between
1952 * accounts) tinymail uses the tny_folder_store_create_account which
1953 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1954 * checks the new name of the folder, so this call in that case
1955 * wouldn't be needed. *But* NOTE that if tinymail changes its
1956 * implementation (if folder transfers within the same account is no
1957 * longer implemented as a rename) this call will allow Modest to work
1960 * If the new name is not valid, this function will set the status to
1961 * failed and will set also an error in the mail operation
1964 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1965 TnyFolderStore *into,
1966 const gchar *new_name)
1968 if (TNY_IS_ACCOUNT (into) &&
1969 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1970 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1972 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1973 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1974 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1975 _CS("ckdg_ib_folder_already_exists"));
1982 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1984 TnyFolderStore *parent,
1985 gboolean delete_original,
1986 XferAsyncUserCallback user_callback,
1989 ModestMailOperationPrivate *priv = NULL;
1990 ModestTnyFolderRules parent_rules = 0, rules;
1991 XFerMsgAsyncHelper *helper = NULL;
1992 const gchar *folder_name = NULL;
1993 const gchar *error_msg;
1995 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1996 g_return_if_fail (TNY_IS_FOLDER (folder));
1997 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1999 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2000 folder_name = tny_folder_get_name (folder);
2002 /* Set the error msg */
2003 error_msg = _("mail_in_ui_folder_move_target_error");
2005 /* Get account and set it into mail_operation */
2006 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2007 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2008 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2010 /* Get folder rules */
2011 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2012 if (TNY_IS_FOLDER (parent))
2013 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2015 /* Apply operation constraints */
2016 if ((gpointer) parent == (gpointer) folder ||
2017 (!TNY_IS_FOLDER_STORE (parent)) ||
2018 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2021 } else if (TNY_IS_FOLDER (parent) &&
2022 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2026 } else if (TNY_IS_FOLDER (parent) &&
2027 TNY_IS_FOLDER_STORE (folder) &&
2028 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2029 TNY_FOLDER_STORE (folder))) {
2030 /* Do not move a parent into a child */
2032 } else if (TNY_IS_FOLDER_STORE (parent) &&
2033 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2034 /* Check that the new folder name is not used by any
2037 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2038 /* Check that the new folder name is not used by any
2039 special local folder */
2042 /* Create the helper */
2043 helper = g_slice_new0 (XFerMsgAsyncHelper);
2044 helper->mail_op = g_object_ref (self);
2045 helper->dest_folder = NULL;
2046 helper->headers = NULL;
2047 helper->user_callback = user_callback;
2048 helper->user_data = user_data;
2050 /* Move/Copy folder */
2051 modest_mail_operation_notify_start (self);
2052 tny_folder_copy_async (folder,
2054 tny_folder_get_name (folder),
2057 transfer_folder_status_cb,
2063 /* Set status failed and set an error */
2064 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2065 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2066 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2069 /* Call the user callback if exists */
2071 user_callback (self, user_data);
2073 /* Notify the queue */
2074 modest_mail_operation_notify_end (self);
2078 modest_mail_operation_rename_folder (ModestMailOperation *self,
2082 ModestMailOperationPrivate *priv;
2083 ModestTnyFolderRules rules;
2084 XFerMsgAsyncHelper *helper;
2086 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2087 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2088 g_return_if_fail (name);
2090 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2092 /* Get account and set it into mail_operation */
2093 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2094 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2096 /* Check folder rules */
2097 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2098 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2099 /* Set status failed and set an error */
2100 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2101 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2102 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2103 _("FIXME: unable to rename"));
2105 /* Notify about operation end */
2106 modest_mail_operation_notify_end (self);
2107 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2108 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2109 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2110 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2111 _("FIXME: unable to rename"));
2112 /* Notify about operation end */
2113 modest_mail_operation_notify_end (self);
2115 TnyFolderStore *into;
2117 into = tny_folder_get_folder_store (folder);
2119 /* Check that the new folder name is not used by any
2120 special local folder */
2121 if (new_name_valid_if_local_account (priv, into, name)) {
2122 /* Create the helper */
2123 helper = g_slice_new0 (XFerMsgAsyncHelper);
2124 helper->mail_op = g_object_ref(self);
2125 helper->dest_folder = NULL;
2126 helper->headers = NULL;
2127 helper->user_callback = NULL;
2128 helper->user_data = NULL;
2130 /* Rename. Camel handles folder subscription/unsubscription */
2131 modest_mail_operation_notify_start (self);
2132 tny_folder_copy_async (folder, into, name, TRUE,
2134 transfer_folder_status_cb,
2137 modest_mail_operation_notify_end (self);
2139 g_object_unref (into);
2143 /* ******************************************************************* */
2144 /* ************************** MSG ACTIONS ************************* */
2145 /* ******************************************************************* */
2148 modest_mail_operation_get_msg (ModestMailOperation *self,
2150 GetMsgAsyncUserCallback user_callback,
2153 GetMsgInfo *helper = NULL;
2155 ModestMailOperationPrivate *priv;
2157 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2158 g_return_if_fail (TNY_IS_HEADER (header));
2160 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2161 folder = tny_header_get_folder (header);
2163 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2164 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2168 /* Get account and set it into mail_operation */
2169 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2171 /* Check for cached messages */
2172 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2173 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2175 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2177 /* Create the helper */
2178 helper = g_slice_new0 (GetMsgInfo);
2179 helper->header = g_object_ref (header);
2180 helper->mail_op = g_object_ref (self);
2181 helper->user_callback = user_callback;
2182 helper->user_data = user_data;
2183 helper->destroy_notify = NULL;
2184 helper->last_total_bytes = 0;
2185 helper->sum_total_bytes = 0;
2186 helper->total_bytes = tny_header_get_message_size (header);
2188 modest_mail_operation_notify_start (self);
2189 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2191 g_object_unref (G_OBJECT (folder));
2195 get_msg_status_cb (GObject *obj,
2199 GetMsgInfo *helper = NULL;
2201 g_return_if_fail (status != NULL);
2202 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2204 helper = (GetMsgInfo *) user_data;
2205 g_return_if_fail (helper != NULL);
2207 /* Notify progress */
2208 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2209 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2213 get_msg_async_cb (TnyFolder *folder,
2219 GetMsgInfo *info = NULL;
2220 ModestMailOperationPrivate *priv = NULL;
2223 info = (GetMsgInfo *) user_data;
2225 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2227 finished = (priv->done == priv->total) ? TRUE : FALSE;
2230 if (canceled || err) {
2231 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2233 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2234 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2237 /* Set the success status before calling the user callback */
2238 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2239 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2243 /* Call the user callback */
2244 if (info->user_callback)
2245 info->user_callback (info->mail_op, info->header, canceled,
2246 msg, err, info->user_data);
2248 /* Notify about operation end if this is the last callback */
2250 /* Free user data */
2251 if (info->destroy_notify)
2252 info->destroy_notify (info->user_data);
2254 /* Notify about operation end */
2255 modest_mail_operation_notify_end (info->mail_op);
2259 g_object_unref (info->header);
2260 g_object_unref (info->mail_op);
2261 g_slice_free (GetMsgInfo, info);
2265 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2266 TnyList *header_list,
2267 GetMsgAsyncUserCallback user_callback,
2269 GDestroyNotify notify)
2271 ModestMailOperationPrivate *priv = NULL;
2272 gboolean size_ok = TRUE;
2274 TnyIterator *iter = NULL;
2276 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2278 /* Init mail operation */
2279 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2280 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2281 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2283 priv->total = tny_list_get_length(header_list);
2285 /* Get account and set it into mail_operation */
2286 if (tny_list_get_length (header_list) >= 1) {
2287 iter = tny_list_create_iterator (header_list);
2288 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2290 TnyFolder *folder = tny_header_get_folder (header);
2292 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2293 g_object_unref (folder);
2295 g_object_unref (header);
2298 if (tny_list_get_length (header_list) == 1) {
2299 g_object_unref (iter);
2304 /* Get msg size limit */
2305 max_size = modest_conf_get_int (modest_runtime_get_conf (),
2306 MODEST_CONF_MSG_SIZE_LIMIT,
2309 g_clear_error (&(priv->error));
2310 max_size = G_MAXINT;
2312 max_size = max_size * KB;
2315 /* Check message size limits. If there is only one message
2316 always retrieve it */
2318 while (!tny_iterator_is_done (iter) && size_ok) {
2319 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2321 if (tny_header_get_message_size (header) >= max_size)
2323 g_object_unref (header);
2326 tny_iterator_next (iter);
2328 g_object_unref (iter);
2332 modest_mail_operation_notify_start (self);
2334 iter = tny_list_create_iterator (header_list);
2335 while (!tny_iterator_is_done (iter)) {
2336 GetMsgInfo *msg_info = NULL;
2337 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2338 TnyFolder *folder = tny_header_get_folder (header);
2340 /* Create the message info */
2341 msg_info = g_slice_new0 (GetMsgInfo);
2342 msg_info->mail_op = g_object_ref (self);
2343 msg_info->header = g_object_ref (header);
2344 msg_info->user_callback = user_callback;
2345 msg_info->user_data = user_data;
2346 msg_info->destroy_notify = notify;
2347 msg_info->last_total_bytes = 0;
2348 msg_info->sum_total_bytes = 0;
2349 msg_info->total_bytes = compute_message_list_size (header_list);
2351 /* The callback will call it per each header */
2352 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2354 /* Free and go on */
2355 g_object_unref (header);
2356 g_object_unref (folder);
2357 tny_iterator_next (iter);
2359 g_object_unref (iter);
2361 /* Set status failed and set an error */
2362 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2363 /* FIXME: the error msg is different for pop */
2364 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2365 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
2366 _("emev_ni_ui_imap_msg_size_exceed_error"));
2367 /* Remove from queue and free resources */
2368 modest_mail_operation_notify_end (self);
2376 modest_mail_operation_remove_msg (ModestMailOperation *self,
2378 gboolean remove_to_trash /*ignored*/)
2381 ModestMailOperationPrivate *priv;
2383 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2384 g_return_if_fail (TNY_IS_HEADER (header));
2386 if (remove_to_trash)
2387 g_warning ("remove to trash is not implemented");
2389 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2390 folder = tny_header_get_folder (header);
2392 /* Get account and set it into mail_operation */
2393 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2394 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2395 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2397 /* remove message from folder */
2398 tny_folder_remove_msg (folder, header, &(priv->error));
2400 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2401 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2403 modest_mail_operation_notify_start (self);
2405 if (TNY_IS_CAMEL_IMAP_FOLDER (folder) ||
2406 TNY_IS_CAMEL_POP_FOLDER (folder))
2407 tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /* FALSE --> dont expunge */
2409 tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /* TRUE --> expunge */
2415 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2417 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2420 g_object_unref (G_OBJECT (folder));
2422 /* Notify about operation end */
2423 modest_mail_operation_notify_end (self);
2427 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2429 gboolean remove_to_trash /*ignored*/)
2432 ModestMailOperationPrivate *priv;
2433 TnyIterator *iter = NULL;
2434 TnyHeader *header = NULL;
2435 TnyList *remove_headers = NULL;
2436 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2438 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2439 g_return_if_fail (TNY_IS_LIST (headers));
2441 if (remove_to_trash)
2442 g_warning ("remove to trash is not implemented");
2444 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2446 remove_headers = g_object_ref(headers);
2448 /* Get folder from first header and sync it */
2449 iter = tny_list_create_iterator (headers);
2450 header = TNY_HEADER (tny_iterator_get_current (iter));
2451 folder = tny_header_get_folder (header);
2453 /* Don't remove messages that are being sent */
2454 if (modest_tny_folder_is_local_folder (folder)) {
2455 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2457 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2458 TnyTransportAccount *traccount = NULL;
2459 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2460 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2462 ModestTnySendQueueStatus status;
2463 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2464 TnyIterator *iter = tny_list_create_iterator(headers);
2465 g_object_unref(remove_headers);
2466 remove_headers = TNY_LIST(tny_simple_list_new());
2467 while (!tny_iterator_is_done(iter)) {
2469 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2470 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2471 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2472 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2473 tny_list_append(remove_headers, G_OBJECT(hdr));
2475 g_object_unref(hdr);
2477 tny_iterator_next(iter);
2479 g_object_unref(iter);
2480 g_object_unref(traccount);
2484 /* Get account and set it into mail_operation */
2485 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2486 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2487 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2489 /* remove message from folder */
2490 modest_mail_operation_notify_start (self);
2492 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2494 if (TNY_IS_CAMEL_IMAP_FOLDER (folder) ||
2495 TNY_IS_CAMEL_POP_FOLDER (folder))
2496 tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /* FALSE --> don't expunge */
2499 tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /* TRUE --> expunge */
2505 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2507 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2510 g_object_unref (remove_headers);
2511 g_object_unref (header);
2512 g_object_unref (iter);
2513 g_object_unref (G_OBJECT (folder));
2515 /* Notify about operation end */
2516 modest_mail_operation_notify_end (self);
2520 notify_progress_of_multiple_messages (ModestMailOperation *self,
2522 gint *last_total_bytes,
2523 gint *sum_total_bytes,
2525 gboolean increment_done)
2527 ModestMailOperationPrivate *priv;
2528 ModestMailOperationState *state;
2529 gboolean is_num_bytes;
2531 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2533 /* We know that tinymail sends us information about
2534 transferred bytes with this particular message */
2535 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2537 state = modest_mail_operation_clone_state (self);
2538 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2539 /* We know that we're in a different message when the
2540 total number of bytes to transfer is different. Of
2541 course it could fail if we're transferring messages
2542 of the same size, but this is a workarround */
2543 if (status->of_total != *last_total_bytes) {
2544 /* We need to increment the done when there is
2545 no information about each individual
2546 message, we need to do this in message
2547 transfers, and we don't do it for getting
2551 *sum_total_bytes += *last_total_bytes;
2552 *last_total_bytes = status->of_total;
2554 state->bytes_done += status->position + *sum_total_bytes;
2555 state->bytes_total = total_bytes;
2557 /* Notify the status change. Only notify about changes
2558 referred to bytes */
2559 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2563 g_slice_free (ModestMailOperationState, state);
2567 transfer_msgs_status_cb (GObject *obj,
2571 XFerMsgAsyncHelper *helper;
2573 g_return_if_fail (status != NULL);
2574 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2576 helper = (XFerMsgAsyncHelper *) user_data;
2577 g_return_if_fail (helper != NULL);
2579 /* Notify progress */
2580 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2581 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2586 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2588 XFerMsgAsyncHelper *helper;
2589 ModestMailOperation *self;
2590 ModestMailOperationPrivate *priv;
2591 TnyIterator *iter = NULL;
2592 TnyHeader *header = NULL;
2594 helper = (XFerMsgAsyncHelper *) user_data;
2595 self = helper->mail_op;
2597 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2600 priv->error = g_error_copy (err);
2602 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2603 } else if (cancelled) {
2604 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2605 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2606 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2607 _("Error trying to refresh the contents of %s"),
2608 tny_folder_get_name (folder));
2611 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2613 /* Update folder counts */
2614 tny_folder_poke_status (folder);
2615 tny_folder_poke_status (helper->dest_folder);
2619 /* Mark headers as deleted and seen */
2620 if ((helper->delete) &&
2621 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2622 iter = tny_list_create_iterator (helper->headers);
2623 while (!tny_iterator_is_done (iter)) {
2624 header = TNY_HEADER (tny_iterator_get_current (iter));
2625 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2626 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2627 g_object_unref (header);
2629 tny_iterator_next (iter);
2635 /* Notify about operation end */
2636 modest_mail_operation_notify_end (self);
2638 /* If user defined callback function was defined, call it */
2639 if (helper->user_callback) {
2640 /* This is not a GDK lock because we are a Tinymail callback and
2641 * Tinymail already acquires the Gdk lock */
2643 /* no gdk_threads_enter (), CHECKED */
2644 helper->user_callback (self, helper->user_data);
2645 /* no gdk_threads_leave (), CHECKED */
2649 if (helper->headers)
2650 g_object_unref (helper->headers);
2651 if (helper->dest_folder)
2652 g_object_unref (helper->dest_folder);
2653 if (helper->mail_op)
2654 g_object_unref (helper->mail_op);
2656 g_object_unref (folder);
2658 g_object_unref (iter);
2659 g_slice_free (XFerMsgAsyncHelper, helper);
2663 compute_message_list_size (TnyList *headers)
2668 iter = tny_list_create_iterator (headers);
2669 while (!tny_iterator_is_done (iter)) {
2670 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2671 size += tny_header_get_message_size (header);
2672 g_object_unref (header);
2673 tny_iterator_next (iter);
2675 g_object_unref (iter);
2681 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2684 gboolean delete_original,
2685 XferAsyncUserCallback user_callback,
2688 ModestMailOperationPrivate *priv = NULL;
2689 TnyIterator *iter = NULL;
2690 TnyFolder *src_folder = NULL;
2691 XFerMsgAsyncHelper *helper = NULL;
2692 TnyHeader *header = NULL;
2693 ModestTnyFolderRules rules = 0;
2695 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2696 g_return_if_fail (headers && TNY_IS_LIST (headers));
2697 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2699 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2700 priv->total = tny_list_get_length (headers);
2702 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2703 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2705 /* Apply folder rules */
2706 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2707 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2708 /* Set status failed and set an error */
2709 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2710 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2711 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2712 _CS("ckct_ib_unable_to_paste_here"));
2713 /* Notify the queue */
2714 modest_mail_operation_notify_end (self);
2718 /* Get source folder */
2719 iter = tny_list_create_iterator (headers);
2720 header = TNY_HEADER (tny_iterator_get_current (iter));
2722 src_folder = tny_header_get_folder (header);
2723 g_object_unref (header);
2725 g_object_unref (iter);
2727 if (src_folder == NULL) {
2728 /* Notify the queue */
2729 modest_mail_operation_notify_end (self);
2731 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2736 /* Check folder source and destination */
2737 if (src_folder == folder) {
2738 /* Set status failed and set an error */
2739 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2740 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2741 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2742 _("mcen_ib_unable_to_copy_samefolder"));
2744 /* Notify the queue */
2745 modest_mail_operation_notify_end (self);
2748 g_object_unref (src_folder);
2752 /* Create the helper */
2753 helper = g_slice_new0 (XFerMsgAsyncHelper);
2754 helper->mail_op = g_object_ref(self);
2755 helper->dest_folder = g_object_ref(folder);
2756 helper->headers = g_object_ref(headers);
2757 helper->user_callback = user_callback;
2758 helper->user_data = user_data;
2759 helper->delete = delete_original;
2760 helper->last_total_bytes = 0;
2761 helper->sum_total_bytes = 0;
2762 helper->total_bytes = compute_message_list_size (headers);
2764 /* Get account and set it into mail_operation */
2765 priv->account = modest_tny_folder_get_account (src_folder);
2767 /* Transfer messages */
2768 modest_mail_operation_notify_start (self);
2769 tny_folder_transfer_msgs_async (src_folder,
2774 transfer_msgs_status_cb,
2780 on_refresh_folder (TnyFolder *folder,
2785 RefreshAsyncHelper *helper = NULL;
2786 ModestMailOperation *self = NULL;
2787 ModestMailOperationPrivate *priv = NULL;
2789 helper = (RefreshAsyncHelper *) user_data;
2790 self = helper->mail_op;
2791 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2793 g_return_if_fail(priv!=NULL);
2796 priv->error = g_error_copy (error);
2797 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2802 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2803 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2804 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2805 _("Error trying to refresh the contents of %s"),
2806 tny_folder_get_name (folder));
2810 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2813 /* Call user defined callback, if it exists */
2814 if (helper->user_callback) {
2816 /* This is not a GDK lock because we are a Tinymail callback and
2817 * Tinymail already acquires the Gdk lock */
2818 helper->user_callback (self, folder, helper->user_data);
2822 g_slice_free (RefreshAsyncHelper, helper);
2824 /* Notify about operation end */
2825 modest_mail_operation_notify_end (self);
2826 g_object_unref(self);
2830 on_refresh_folder_status_update (GObject *obj,
2834 RefreshAsyncHelper *helper = NULL;
2835 ModestMailOperation *self = NULL;
2836 ModestMailOperationPrivate *priv = NULL;
2837 ModestMailOperationState *state;
2839 g_return_if_fail (user_data != NULL);
2840 g_return_if_fail (status != NULL);
2841 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2843 helper = (RefreshAsyncHelper *) user_data;
2844 self = helper->mail_op;
2845 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2847 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2849 priv->done = status->position;
2850 priv->total = status->of_total;
2852 state = modest_mail_operation_clone_state (self);
2854 /* This is not a GDK lock because we are a Tinymail callback and
2855 * Tinymail already acquires the Gdk lock */
2856 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2858 g_slice_free (ModestMailOperationState, state);
2862 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2864 RefreshAsyncUserCallback user_callback,
2867 ModestMailOperationPrivate *priv = NULL;
2868 RefreshAsyncHelper *helper = NULL;
2870 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2872 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2874 /* Get account and set it into mail_operation */
2875 priv->account = modest_tny_folder_get_account (folder);
2876 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2878 /* Create the helper */
2879 helper = g_slice_new0 (RefreshAsyncHelper);
2880 helper->mail_op = g_object_ref(self);
2881 helper->user_callback = user_callback;
2882 helper->user_data = user_data;
2884 /* Refresh the folder. TODO: tinymail could issue a status
2885 updates before the callback call then this could happen. We
2886 must review the design */
2887 modest_mail_operation_notify_start (self);
2888 tny_folder_refresh_async (folder,
2890 on_refresh_folder_status_update,
2896 modest_mail_operation_notify_start (ModestMailOperation *self)
2898 ModestMailOperationPrivate *priv = NULL;
2900 g_return_if_fail (self);
2902 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2904 /* Ensure that all the fields are filled correctly */
2905 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2907 /* Notify the observers about the mail operation. We do not
2908 wrapp this emission because we assume that this function is
2909 always called from within the main lock */
2910 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2915 * It's used by the mail operation queue to notify the observers
2916 * attached to that signal that the operation finished. We need to use
2917 * that because tinymail does not give us the progress of a given
2918 * operation when it finishes (it directly calls the operation
2922 modest_mail_operation_notify_end (ModestMailOperation *self)
2924 ModestMailOperationPrivate *priv = NULL;
2926 g_return_if_fail (self);
2928 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2930 /* Notify the observers about the mail operation end. We do
2931 not wrapp this emission because we assume that this
2932 function is always called from within the main lock */
2933 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2935 /* Remove the error user data */
2936 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2937 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2941 modest_mail_operation_get_account (ModestMailOperation *self)
2943 ModestMailOperationPrivate *priv = NULL;
2945 g_return_val_if_fail (self, NULL);
2947 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2949 return (priv->account) ? g_object_ref (priv->account) : NULL;
2953 modest_mail_operation_noop (ModestMailOperation *self)
2955 ModestMailOperationPrivate *priv = NULL;
2957 g_return_if_fail (self);
2959 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2960 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2961 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2965 /* This mail operation does nothing actually */
2966 modest_mail_operation_notify_start (self);
2967 modest_mail_operation_notify_end (self);