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 static guint compute_message_array_size (GPtrArray *headers);
98 static int compare_headers_by_date (gconstpointer a,
101 enum _ModestMailOperationSignals
103 PROGRESS_CHANGED_SIGNAL,
104 OPERATION_STARTED_SIGNAL,
105 OPERATION_FINISHED_SIGNAL,
109 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
110 struct _ModestMailOperationPrivate {
116 ErrorCheckingUserCallback error_checking;
117 gpointer error_checking_user_data;
118 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
119 ModestMailOperationStatus status;
120 ModestMailOperationTypeOperation op_type;
123 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
124 MODEST_TYPE_MAIL_OPERATION, \
125 ModestMailOperationPrivate))
127 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
128 priv->status = new_status;\
133 GetMsgAsyncUserCallback user_callback;
136 ModestMailOperation *mail_op;
137 GDestroyNotify destroy_notify;
138 gint last_total_bytes;
139 gint sum_total_bytes;
144 ModestMailOperation *mail_op;
146 gulong msg_sent_handler;
147 gulong error_happened_handler;
150 static void send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
151 guint nth, guint total, gpointer userdata);
152 static void send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
153 GError *error, gpointer userdata);
154 static void common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
157 typedef struct _RefreshAsyncHelper {
158 ModestMailOperation *mail_op;
159 RefreshAsyncUserCallback user_callback;
161 } RefreshAsyncHelper;
163 typedef struct _XFerMsgAsyncHelper
165 ModestMailOperation *mail_op;
167 TnyFolder *dest_folder;
168 XferAsyncUserCallback user_callback;
171 gint last_total_bytes;
172 gint sum_total_bytes;
174 } XFerMsgAsyncHelper;
176 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
180 static void modest_mail_operation_create_msg (ModestMailOperation *self,
181 const gchar *from, const gchar *to,
182 const gchar *cc, const gchar *bcc,
183 const gchar *subject, const gchar *plain_body,
184 const gchar *html_body, const GList *attachments_list,
185 const GList *images_list,
186 TnyHeaderFlags priority_flags,
187 ModestMailOperationCreateMsgCallback callback,
190 static gboolean idle_notify_queue (gpointer data);
193 ModestMailOperation *mail_op;
201 GList *attachments_list;
203 TnyHeaderFlags priority_flags;
204 ModestMailOperationCreateMsgCallback callback;
210 ModestMailOperation *mail_op;
212 ModestMailOperationCreateMsgCallback callback;
217 static GObjectClass *parent_class = NULL;
219 static guint signals[NUM_SIGNALS] = {0};
222 modest_mail_operation_get_type (void)
224 static GType my_type = 0;
226 static const GTypeInfo my_info = {
227 sizeof(ModestMailOperationClass),
228 NULL, /* base init */
229 NULL, /* base finalize */
230 (GClassInitFunc) modest_mail_operation_class_init,
231 NULL, /* class finalize */
232 NULL, /* class data */
233 sizeof(ModestMailOperation),
235 (GInstanceInitFunc) modest_mail_operation_init,
238 my_type = g_type_register_static (G_TYPE_OBJECT,
239 "ModestMailOperation",
246 modest_mail_operation_class_init (ModestMailOperationClass *klass)
248 GObjectClass *gobject_class;
249 gobject_class = (GObjectClass*) klass;
251 parent_class = g_type_class_peek_parent (klass);
252 gobject_class->finalize = modest_mail_operation_finalize;
254 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
257 * ModestMailOperation::progress-changed
258 * @self: the #MailOperation that emits the signal
259 * @user_data: user data set when the signal handler was connected
261 * Emitted when the progress of a mail operation changes
263 signals[PROGRESS_CHANGED_SIGNAL] =
264 g_signal_new ("progress-changed",
265 G_TYPE_FROM_CLASS (gobject_class),
267 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
269 g_cclosure_marshal_VOID__POINTER,
270 G_TYPE_NONE, 1, G_TYPE_POINTER);
274 * This signal is issued whenever a mail operation starts, and
275 * starts mean when the tinymail operation is issued. This
276 * means that it could happen that something wrong happens and
277 * the tinymail function is never called. In this situation a
278 * operation-finished will be issued without any
281 signals[OPERATION_STARTED_SIGNAL] =
282 g_signal_new ("operation-started",
283 G_TYPE_FROM_CLASS (gobject_class),
285 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
287 g_cclosure_marshal_VOID__VOID,
292 * This signal is issued whenever a mail operation
293 * finishes. Note that this signal could be issued without any
294 * previous "operation-started" signal, because this last one
295 * is only issued when the tinymail operation is successfully
298 signals[OPERATION_FINISHED_SIGNAL] =
299 g_signal_new ("operation-finished",
300 G_TYPE_FROM_CLASS (gobject_class),
302 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
304 g_cclosure_marshal_VOID__VOID,
309 modest_mail_operation_init (ModestMailOperation *obj)
311 ModestMailOperationPrivate *priv;
313 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
315 priv->account = NULL;
316 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
317 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
322 priv->error_checking = NULL;
323 priv->error_checking_user_data = NULL;
327 modest_mail_operation_finalize (GObject *obj)
329 ModestMailOperationPrivate *priv;
331 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
336 g_error_free (priv->error);
340 g_object_unref (priv->source);
344 g_object_unref (priv->account);
345 priv->account = NULL;
349 G_OBJECT_CLASS(parent_class)->finalize (obj);
353 modest_mail_operation_new (GObject *source)
355 ModestMailOperation *obj;
356 ModestMailOperationPrivate *priv;
358 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
359 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
362 priv->source = g_object_ref(source);
368 modest_mail_operation_new_with_error_handling (GObject *source,
369 ErrorCheckingUserCallback error_handler,
371 ErrorCheckingUserDataDestroyer error_handler_destroyer)
373 ModestMailOperation *obj;
374 ModestMailOperationPrivate *priv;
376 obj = modest_mail_operation_new (source);
377 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
379 g_return_val_if_fail (error_handler != NULL, obj);
380 priv->error_checking = error_handler;
381 priv->error_checking_user_data = user_data;
382 priv->error_checking_user_data_destroyer = error_handler_destroyer;
388 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
390 ModestMailOperationPrivate *priv;
392 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
394 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
395 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
397 /* Call the user callback */
398 if (priv->error_checking != NULL)
399 priv->error_checking (self, priv->error_checking_user_data);
403 ModestMailOperationTypeOperation
404 modest_mail_operation_get_type_operation (ModestMailOperation *self)
406 ModestMailOperationPrivate *priv;
408 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
409 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
411 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
413 return priv->op_type;
417 modest_mail_operation_is_mine (ModestMailOperation *self,
420 ModestMailOperationPrivate *priv;
422 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
425 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
426 if (priv->source == NULL) return FALSE;
428 return priv->source == me;
432 modest_mail_operation_get_source (ModestMailOperation *self)
434 ModestMailOperationPrivate *priv;
436 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
439 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
441 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
445 return (priv->source) ? g_object_ref (priv->source) : NULL;
448 ModestMailOperationStatus
449 modest_mail_operation_get_status (ModestMailOperation *self)
451 ModestMailOperationPrivate *priv;
453 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
454 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
455 MODEST_MAIL_OPERATION_STATUS_INVALID);
457 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
459 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
460 return MODEST_MAIL_OPERATION_STATUS_INVALID;
467 modest_mail_operation_get_error (ModestMailOperation *self)
469 ModestMailOperationPrivate *priv;
471 g_return_val_if_fail (self, NULL);
472 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
474 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
477 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
485 modest_mail_operation_cancel (ModestMailOperation *self)
487 ModestMailOperationPrivate *priv;
488 gboolean canceled = FALSE;
490 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
492 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
494 /* Note that if we call cancel with an already canceled mail
495 operation the progress changed signal won't be emitted */
496 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
500 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
502 /* Cancel the mail operation. We need to wrap it between this
503 start/stop operations to allow following calls to the
505 g_return_val_if_fail (priv->account, FALSE);
507 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
508 ModestTnySendQueue *queue;
509 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
510 /* Cancel sending without removing the item */
511 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), FALSE, NULL);
513 /* Cancel operation */
514 tny_account_cancel (priv->account);
521 modest_mail_operation_get_task_done (ModestMailOperation *self)
523 ModestMailOperationPrivate *priv;
525 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
528 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
533 modest_mail_operation_get_task_total (ModestMailOperation *self)
535 ModestMailOperationPrivate *priv;
537 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
540 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
545 modest_mail_operation_is_finished (ModestMailOperation *self)
547 ModestMailOperationPrivate *priv;
548 gboolean retval = FALSE;
550 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
553 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
555 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
556 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
557 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
558 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
568 * Creates an image of the current state of a mail operation, the
569 * caller must free it
571 static ModestMailOperationState *
572 modest_mail_operation_clone_state (ModestMailOperation *self)
574 ModestMailOperationState *state;
575 ModestMailOperationPrivate *priv;
577 /* FIXME: this should be fixed properly
579 * in some cases, priv was NULL, so checking here to
582 g_return_val_if_fail (self, NULL);
583 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
584 g_return_val_if_fail (priv, NULL);
589 state = g_slice_new (ModestMailOperationState);
591 state->status = priv->status;
592 state->op_type = priv->op_type;
593 state->done = priv->done;
594 state->total = priv->total;
595 state->finished = modest_mail_operation_is_finished (self);
596 state->bytes_done = 0;
597 state->bytes_total = 0;
602 /* ******************************************************************* */
603 /* ************************** SEND ACTIONS ************************* */
604 /* ******************************************************************* */
607 modest_mail_operation_send_mail (ModestMailOperation *self,
608 TnyTransportAccount *transport_account,
611 TnySendQueue *send_queue = NULL;
612 ModestMailOperationPrivate *priv;
615 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
616 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
617 g_return_if_fail (msg && TNY_IS_MSG (msg));
619 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
621 /* Get account and set it into mail_operation */
622 priv->account = g_object_ref (transport_account);
623 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
627 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
628 if (!TNY_IS_SEND_QUEUE(send_queue)) {
629 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
630 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
631 "modest: could not find send queue for account\n");
632 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
633 modest_mail_operation_notify_end (self);
636 /* Add the msg to the queue */
637 modest_mail_operation_notify_start (self);
638 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
642 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
644 info = g_slice_new0 (SendMsgInfo);
646 info->mail_op = g_object_ref (self);
647 info->msg = g_object_ref (msg);
648 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
649 G_CALLBACK (send_mail_msg_sent_handler), info);
650 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
651 G_CALLBACK (send_mail_error_happened_handler), info);
657 common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
660 g_signal_handler_disconnect (queue, info->msg_sent_handler);
661 g_signal_handler_disconnect (queue, info->error_happened_handler);
663 g_object_unref (info->msg);
664 modest_mail_operation_notify_end (info->mail_op);
665 g_object_unref (info->mail_op);
667 g_slice_free (SendMsgInfo, info);
671 send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
672 guint nth, guint total, gpointer userdata)
674 SendMsgInfo *info = (SendMsgInfo *) userdata;
675 TnyHeader *hdr1, *hdr2;
676 const char *msgid1, *msgid2;
677 hdr1 = tny_msg_get_header(msg);
678 hdr2 = tny_msg_get_header(info->msg);
679 msgid1 = tny_header_get_message_id(hdr1);
680 msgid2 = tny_header_get_message_id(hdr2);
681 if (msgid1 == NULL) msgid1 = "(null)";
682 if (msgid2 == NULL) msgid2 = "(null)";
684 if (!strcmp (msgid1, msgid2)) {
685 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
686 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
688 common_send_mail_operation_end (queue, msg, info);
690 g_object_unref(G_OBJECT(hdr1));
691 g_object_unref(G_OBJECT(hdr2));
695 send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
696 GError *error, gpointer userdata)
698 SendMsgInfo *info = (SendMsgInfo *) userdata;
699 TnyHeader *hdr1, *hdr2;
700 const char *msgid1, *msgid2;
702 hdr1 = tny_msg_get_header(msg);
703 hdr2 = tny_msg_get_header(info->msg);
704 msgid1 = tny_header_get_message_id(hdr1);
705 msgid2 = tny_header_get_message_id(hdr2);
706 if (msgid1 == NULL) msgid1 = "(null)";
707 if (msgid2 == NULL) msgid2 = "(null)";
709 if (!strcmp (msgid1, msgid2)) {
710 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
711 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
712 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
713 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
714 "modest: send mail failed\n");
716 common_send_mail_operation_end (queue, msg, info);
718 g_object_unref(G_OBJECT(hdr1));
719 g_object_unref(G_OBJECT(hdr2));
724 idle_create_msg_cb (gpointer idle_data)
726 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
728 /* This is a GDK lock because we are an idle callback and
729 * info->callback can contain Gtk+ code */
731 gdk_threads_enter (); /* CHECKED */
732 info->callback (info->mail_op, info->msg, info->userdata);
734 g_object_unref (info->mail_op);
736 g_object_unref (info->msg);
737 g_slice_free (CreateMsgIdleInfo, info);
738 gdk_threads_leave (); /* CHECKED */
744 create_msg_thread (gpointer thread_data)
746 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
747 TnyMsg *new_msg = NULL;
748 ModestMailOperationPrivate *priv;
750 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
751 if (info->html_body == NULL) {
752 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
753 info->bcc, info->subject, info->plain_body,
754 info->attachments_list);
756 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
757 info->bcc, info->subject, info->html_body,
758 info->plain_body, info->attachments_list,
765 /* Set priority flags in message */
766 header = tny_msg_get_header (new_msg);
767 tny_header_set_flag (header, info->priority_flags);
769 /* Set attachment flags in message */
770 if (info->attachments_list != NULL)
771 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
773 g_object_unref (G_OBJECT(header));
775 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
776 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
777 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
778 "modest: failed to create a new msg\n");
786 g_free (info->plain_body);
787 g_free (info->html_body);
788 g_free (info->subject);
789 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
790 g_list_free (info->attachments_list);
791 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
792 g_list_free (info->images_list);
794 if (info->callback) {
795 CreateMsgIdleInfo *idle_info;
796 idle_info = g_slice_new0 (CreateMsgIdleInfo);
797 idle_info->mail_op = g_object_ref (info->mail_op);
798 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
799 idle_info->callback = info->callback;
800 idle_info->userdata = info->userdata;
801 g_idle_add (idle_create_msg_cb, idle_info);
803 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
806 g_object_unref (info->mail_op);
807 g_slice_free (CreateMsgInfo, info);
808 if (new_msg) g_object_unref(new_msg);
813 modest_mail_operation_create_msg (ModestMailOperation *self,
814 const gchar *from, const gchar *to,
815 const gchar *cc, const gchar *bcc,
816 const gchar *subject, const gchar *plain_body,
817 const gchar *html_body,
818 const GList *attachments_list,
819 const GList *images_list,
820 TnyHeaderFlags priority_flags,
821 ModestMailOperationCreateMsgCallback callback,
824 CreateMsgInfo *info = NULL;
826 info = g_slice_new0 (CreateMsgInfo);
827 info->mail_op = g_object_ref (self);
829 info->from = g_strdup (from);
830 info->to = g_strdup (to);
831 info->cc = g_strdup (cc);
832 info->bcc = g_strdup (bcc);
833 info->subject = g_strdup (subject);
834 info->plain_body = g_strdup (plain_body);
835 info->html_body = g_strdup (html_body);
836 info->attachments_list = g_list_copy ((GList *) attachments_list);
837 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
838 info->images_list = g_list_copy ((GList *) images_list);
839 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
840 info->priority_flags = priority_flags;
842 info->callback = callback;
843 info->userdata = userdata;
845 g_thread_create (create_msg_thread, info, FALSE, NULL);
850 TnyTransportAccount *transport_account;
855 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
859 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
860 TnyFolder *draft_folder = NULL;
861 TnyFolder *outbox_folder = NULL;
869 /* Call mail operation */
870 modest_mail_operation_send_mail (self, info->transport_account, msg);
872 /* Remove old mail from its source folder */
873 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
874 TNY_FOLDER_TYPE_DRAFTS);
876 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder", __FUNCTION__);
879 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
880 TNY_FOLDER_TYPE_OUTBOX);
881 if (!outbox_folder) {
882 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder", __FUNCTION__);
885 if (info->draft_msg != NULL) {
886 TnyFolder *folder = NULL;
887 TnyFolder *src_folder = NULL;
888 TnyFolderType folder_type;
889 folder = tny_msg_get_folder (info->draft_msg);
890 if (folder == NULL) goto end;
891 folder_type = modest_tny_folder_guess_folder_type (folder);
893 if (folder_type == TNY_FOLDER_TYPE_INVALID)
894 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
896 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
897 src_folder = outbox_folder;
899 src_folder = draft_folder;
901 /* Note: This can fail (with a warning) if the message is not really already in a folder,
902 * because this function requires it to have a UID. */
903 header = tny_msg_get_header (info->draft_msg);
904 tny_folder_remove_msg (src_folder, header, NULL);
906 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
907 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
909 g_object_unref (header);
910 g_object_unref (folder);
917 g_object_unref (info->draft_msg);
919 g_object_unref (draft_folder);
921 g_object_unref (outbox_folder);
922 if (info->transport_account)
923 g_object_unref (info->transport_account);
924 g_slice_free (SendNewMailInfo, info);
928 modest_mail_operation_send_new_mail (ModestMailOperation *self,
929 TnyTransportAccount *transport_account,
931 const gchar *from, const gchar *to,
932 const gchar *cc, const gchar *bcc,
933 const gchar *subject, const gchar *plain_body,
934 const gchar *html_body,
935 const GList *attachments_list,
936 const GList *images_list,
937 TnyHeaderFlags priority_flags)
939 ModestMailOperationPrivate *priv = NULL;
940 SendNewMailInfo *info;
942 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
943 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
945 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
946 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
947 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
948 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
950 /* Check parametters */
952 /* Set status failed and set an error */
953 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
954 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
955 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
956 _("Error trying to send a mail. You need to set at least one recipient"));
959 info = g_slice_new0 (SendNewMailInfo);
960 info->transport_account = transport_account;
961 if (transport_account)
962 g_object_ref (transport_account);
963 info->draft_msg = draft_msg;
965 g_object_ref (draft_msg);
968 modest_mail_operation_notify_start (self);
969 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
970 attachments_list, images_list, priority_flags,
971 modest_mail_operation_send_new_mail_cb, info);
977 TnyTransportAccount *transport_account;
979 SaveToDraftstCallback callback;
983 ModestMailOperation *mailop;
984 } SaveToDraftsAddMsgInfo;
987 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
992 ModestMailOperationPrivate *priv = NULL;
993 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
995 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
998 g_warning ("%s: priv->error != NULL", __FUNCTION__);
999 g_error_free(priv->error);
1002 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1004 if ((!priv->error) && (info->draft_msg != NULL)) {
1005 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1006 TnyFolder *src_folder = tny_header_get_folder (header);
1008 /* Remove the old draft */
1009 tny_folder_remove_msg (src_folder, header, NULL);
1011 /* Synchronize to expunge and to update the msg counts */
1012 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1013 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1015 g_object_unref (G_OBJECT(header));
1016 g_object_unref (G_OBJECT(src_folder));
1020 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1022 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1024 /* Call the user callback */
1026 info->callback (info->mailop, info->msg, info->user_data);
1028 if (info->transport_account)
1029 g_object_unref (G_OBJECT(info->transport_account));
1030 if (info->draft_msg)
1031 g_object_unref (G_OBJECT (info->draft_msg));
1033 g_object_unref (G_OBJECT(info->drafts));
1035 g_object_unref (G_OBJECT (info->msg));
1036 g_slice_free (SaveToDraftsAddMsgInfo, info);
1038 modest_mail_operation_notify_end (info->mailop);
1039 g_object_unref(info->mailop);
1044 TnyTransportAccount *transport_account;
1046 SaveToDraftstCallback callback;
1051 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1055 TnyFolder *drafts = NULL;
1056 ModestMailOperationPrivate *priv = NULL;
1057 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1059 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1062 if (!(priv->error)) {
1063 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1064 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1065 "modest: failed to create a new msg\n");
1068 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1069 TNY_FOLDER_TYPE_DRAFTS);
1070 if (!drafts && !(priv->error)) {
1071 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1072 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1073 "modest: failed to create a new msg\n");
1078 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1079 cb_info->transport_account = g_object_ref(info->transport_account);
1080 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1081 cb_info->callback = info->callback;
1082 cb_info->user_data = info->user_data;
1083 cb_info->drafts = g_object_ref(drafts);
1084 cb_info->msg = g_object_ref(msg);
1085 cb_info->mailop = g_object_ref(self);
1086 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1089 /* Call the user callback */
1090 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1092 info->callback (self, msg, info->user_data);
1093 modest_mail_operation_notify_end (self);
1097 g_object_unref (G_OBJECT(drafts));
1098 if (info->draft_msg)
1099 g_object_unref (G_OBJECT (info->draft_msg));
1100 if (info->transport_account)
1101 g_object_unref (G_OBJECT(info->transport_account));
1102 g_slice_free (SaveToDraftsInfo, info);
1106 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1107 TnyTransportAccount *transport_account,
1109 const gchar *from, const gchar *to,
1110 const gchar *cc, const gchar *bcc,
1111 const gchar *subject, const gchar *plain_body,
1112 const gchar *html_body,
1113 const GList *attachments_list,
1114 const GList *images_list,
1115 TnyHeaderFlags priority_flags,
1116 SaveToDraftstCallback callback,
1119 ModestMailOperationPrivate *priv = NULL;
1120 SaveToDraftsInfo *info = NULL;
1122 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1123 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1125 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1127 /* Get account and set it into mail_operation */
1128 priv->account = g_object_ref (transport_account);
1129 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1131 info = g_slice_new0 (SaveToDraftsInfo);
1132 info->transport_account = g_object_ref (transport_account);
1133 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1134 info->callback = callback;
1135 info->user_data = user_data;
1137 modest_mail_operation_notify_start (self);
1138 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1139 attachments_list, images_list, priority_flags,
1140 modest_mail_operation_save_to_drafts_cb, info);
1145 ModestMailOperation *mail_op;
1146 TnyMimePart *mime_part;
1148 GetMimePartSizeCallback callback;
1150 } GetMimePartSizeInfo;
1152 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1153 /* We use this folder observer to track the headers that have been
1154 * added to a folder */
1157 TnyList *new_headers;
1158 } InternalFolderObserver;
1161 GObjectClass parent;
1162 } InternalFolderObserverClass;
1164 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1166 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1167 internal_folder_observer,
1169 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1173 foreach_add_item (gpointer header, gpointer user_data)
1175 tny_list_prepend (TNY_LIST (user_data),
1176 g_object_ref (G_OBJECT (header)));
1179 /* This is the method that looks for new messages in a folder */
1181 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1183 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1185 TnyFolderChangeChanged changed;
1187 changed = tny_folder_change_get_changed (change);
1189 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1192 /* Get added headers */
1193 list = tny_simple_list_new ();
1194 tny_folder_change_get_added_headers (change, list);
1196 /* Add them to the folder observer */
1197 tny_list_foreach (list, foreach_add_item,
1198 derived->new_headers);
1200 g_object_unref (G_OBJECT (list));
1205 internal_folder_observer_init (InternalFolderObserver *self)
1207 self->new_headers = tny_simple_list_new ();
1210 internal_folder_observer_finalize (GObject *object)
1212 InternalFolderObserver *self;
1214 self = (InternalFolderObserver *) object;
1215 g_object_unref (self->new_headers);
1217 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1220 tny_folder_observer_init (TnyFolderObserverIface *iface)
1222 iface->update_func = internal_folder_observer_update;
1225 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1227 GObjectClass *object_class;
1229 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1230 object_class = (GObjectClass*) klass;
1231 object_class->finalize = internal_folder_observer_finalize;
1236 ModestMailOperation *mail_op;
1237 gchar *account_name;
1238 UpdateAccountCallback callback;
1243 TnyFolderObserver *inbox_observer;
1244 RetrieveAllCallback retrieve_all_cb;
1245 } UpdateAccountInfo;
1249 destroy_update_account_info (UpdateAccountInfo *info)
1251 g_free (info->account_name);
1252 g_object_unref (info->folders);
1253 g_object_unref (info->mail_op);
1254 g_slice_free (UpdateAccountInfo, info);
1258 update_account_get_msg_async_cb (TnyFolder *folder,
1264 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1266 /* Just delete the helper. Don't do anything with the new
1267 msg. There is also no need to check for errors */
1268 g_object_unref (msg_info->mail_op);
1269 g_object_unref (msg_info->header);
1270 g_slice_free (GetMsgInfo, msg_info);
1275 inbox_refreshed_cb (TnyFolder *inbox,
1280 UpdateAccountInfo *info;
1281 ModestMailOperationPrivate *priv;
1282 TnyIterator *new_headers_iter;
1283 GPtrArray *new_headers_array = NULL;
1284 gint max_size, retrieve_limit, i;
1285 ModestAccountMgr *mgr;
1286 ModestAccountRetrieveType retrieve_type;
1287 TnyList *new_headers = NULL;
1288 gboolean headers_only, ignore_limit;
1289 TnyTransportAccount *transport_account;
1290 ModestTnySendQueue *send_queue;
1292 info = (UpdateAccountInfo *) user_data;
1293 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1294 mgr = modest_runtime_get_account_mgr ();
1296 if (canceled || err || !inbox) {
1297 /* Try to send anyway */
1301 /* Get the message max size */
1302 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1303 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1305 max_size = G_MAXINT;
1307 max_size = max_size * KB;
1309 /* Create the new headers array. We need it to sort the
1310 new headers by date */
1311 new_headers_array = g_ptr_array_new ();
1312 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1313 while (!tny_iterator_is_done (new_headers_iter)) {
1314 TnyHeader *header = NULL;
1316 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1317 /* Apply per-message size limits */
1318 if (tny_header_get_message_size (header) < max_size)
1319 g_ptr_array_add (new_headers_array, g_object_ref (header));
1321 g_object_unref (header);
1322 tny_iterator_next (new_headers_iter);
1324 g_object_unref (new_headers_iter);
1325 tny_folder_remove_observer (inbox, info->inbox_observer);
1326 g_object_unref (info->inbox_observer);
1327 info->inbox_observer = NULL;
1329 /* Update the last updated key, even if we don't have to get new headers */
1330 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1332 if (new_headers_array->len == 0)
1335 /* Get per-account message amount retrieval limit */
1336 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1337 if (retrieve_limit == 0)
1338 retrieve_limit = G_MAXINT;
1340 /* Get per-account retrieval type */
1341 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1342 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1345 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1347 /* Ask the users if they want to retrieve all the messages
1348 even though the limit was exceeded */
1349 ignore_limit = FALSE;
1350 if (new_headers_array->len > retrieve_limit) {
1351 /* Ask the user if a callback has been specified and
1352 if the mail operation has a source (this means that
1353 was invoked by the user and not automatically by a
1355 if (info->retrieve_all_cb && priv->source)
1356 ignore_limit = info->retrieve_all_cb (priv->source,
1357 new_headers_array->len,
1361 if (!headers_only) {
1363 const gint msg_list_size = compute_message_array_size (new_headers_array);
1367 priv->total = new_headers_array->len;
1369 priv->total = MIN (new_headers_array->len, retrieve_limit);
1370 while (msg_num < priv->total) {
1371 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1372 TnyFolder *folder = tny_header_get_folder (header);
1373 GetMsgInfo *msg_info;
1375 /* Create the message info */
1376 msg_info = g_slice_new0 (GetMsgInfo);
1377 msg_info->mail_op = g_object_ref (info->mail_op);
1378 msg_info->header = g_object_ref (header);
1379 msg_info->total_bytes = msg_list_size;
1381 /* Get message in an async way */
1382 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1383 get_msg_status_cb, msg_info);
1385 g_object_unref (folder);
1391 /* Copy the headers to a list and free the array */
1392 new_headers = tny_simple_list_new ();
1393 for (i=0; i < new_headers_array->len; i++) {
1394 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1395 tny_list_append (new_headers, G_OBJECT (header));
1397 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1398 g_ptr_array_free (new_headers_array, FALSE);
1405 /* Get the transport account */
1406 transport_account = (TnyTransportAccount *)
1407 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1408 info->account_name);
1411 send_queue = modest_runtime_get_send_queue (transport_account);
1412 modest_tny_send_queue_try_to_send (send_queue);
1414 /* Check if the operation was a success */
1416 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1418 /* Set the account back to not busy */
1419 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1421 /* Call the user callback */
1423 info->callback (info->mail_op, new_headers, info->user_data);
1425 /* Notify about operation end */
1426 modest_mail_operation_notify_end (info->mail_op);
1430 g_object_unref (new_headers);
1431 destroy_update_account_info (info);
1435 recurse_folders_async_cb (TnyFolderStore *folder_store,
1441 UpdateAccountInfo *info;
1442 ModestMailOperationPrivate *priv;
1444 info = (UpdateAccountInfo *) user_data;
1445 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1447 if (err || canceled) {
1448 /* Try to continue anyway */
1450 TnyIterator *iter = tny_list_create_iterator (list);
1451 while (!tny_iterator_is_done (iter)) {
1452 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1453 TnyList *folders = tny_simple_list_new ();
1455 /* Add to the list of all folders */
1456 tny_list_append (info->folders, (GObject *) folder);
1458 /* Add pending call */
1459 info->pending_calls++;
1461 tny_folder_store_get_folders_async (folder, folders, NULL,
1462 recurse_folders_async_cb,
1465 g_object_unref (G_OBJECT (folder));
1467 tny_iterator_next (iter);
1469 g_object_unref (G_OBJECT (iter));
1470 g_object_unref (G_OBJECT (list));
1473 /* Remove my own pending call */
1474 info->pending_calls--;
1476 /* This means that we have all the folders */
1477 if (info->pending_calls == 0) {
1478 TnyIterator *iter_all_folders;
1479 TnyFolder *inbox = NULL;
1481 iter_all_folders = tny_list_create_iterator (info->folders);
1483 /* Do a poke status over all folders */
1484 while (!tny_iterator_is_done (iter_all_folders) &&
1485 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1486 TnyFolder *folder = NULL;
1488 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1490 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1491 /* Get a reference to the INBOX */
1492 inbox = g_object_ref (folder);
1494 /* Issue a poke status over the folder */
1496 tny_folder_poke_status (folder);
1499 /* Free and go to next */
1500 g_object_unref (folder);
1501 tny_iterator_next (iter_all_folders);
1503 g_object_unref (iter_all_folders);
1505 /* Refresh the INBOX */
1507 /* Refresh the folder. Our observer receives
1508 * the new emails during folder refreshes, so
1509 * we can use observer->new_headers
1511 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1512 tny_folder_add_observer (inbox, info->inbox_observer);
1514 /* Refresh the INBOX */
1515 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1516 g_object_unref (inbox);
1518 /* We could not perform the inbox refresh but
1519 we'll try to send mails anyway */
1520 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1526 modest_mail_operation_update_account (ModestMailOperation *self,
1527 const gchar *account_name,
1529 RetrieveAllCallback retrieve_all_cb,
1530 UpdateAccountCallback callback,
1533 UpdateAccountInfo *info = NULL;
1534 ModestMailOperationPrivate *priv = NULL;
1535 ModestTnyAccountStore *account_store = NULL;
1536 TnyStoreAccount *store_account = NULL;
1539 /* Init mail operation */
1540 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1543 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1544 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1546 /* Get the store account */
1547 account_store = modest_runtime_get_account_store ();
1548 store_account = (TnyStoreAccount *)
1549 modest_tny_account_store_get_server_account (account_store,
1551 TNY_ACCOUNT_TYPE_STORE);
1552 priv->account = g_object_ref (store_account);
1554 /* Create the helper object */
1555 info = g_slice_new0 (UpdateAccountInfo);
1556 info->pending_calls = 1;
1557 info->folders = tny_simple_list_new ();
1558 info->mail_op = g_object_ref (self);
1559 info->poke_all = poke_all;
1560 info->account_name = g_strdup (account_name);
1561 info->callback = callback;
1562 info->user_data = user_data;
1563 info->retrieve_all_cb = retrieve_all_cb;
1565 /* Set account busy */
1566 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1567 modest_mail_operation_notify_start (self);
1569 /* notify about the start of the operation */
1570 ModestMailOperationState *state;
1571 state = modest_mail_operation_clone_state (self);
1575 /* Start notifying progress */
1576 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
1578 g_slice_free (ModestMailOperationState, state);
1580 /* Get all folders and continue in the callback */
1581 folders = tny_simple_list_new ();
1582 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1584 recurse_folders_async_cb,
1589 * Used to notify the queue from the main
1590 * loop. We call it inside an idle call to achieve that
1593 idle_notify_queue (gpointer data)
1595 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1597 gdk_threads_enter ();
1598 modest_mail_operation_notify_end (mail_op);
1599 gdk_threads_leave ();
1600 g_object_unref (mail_op);
1606 compare_headers_by_date (gconstpointer a,
1609 TnyHeader **header1, **header2;
1610 time_t sent1, sent2;
1612 header1 = (TnyHeader **) a;
1613 header2 = (TnyHeader **) b;
1615 sent1 = tny_header_get_date_sent (*header1);
1616 sent2 = tny_header_get_date_sent (*header2);
1618 /* We want the most recent ones (greater time_t) at the
1627 /* ******************************************************************* */
1628 /* ************************** STORE ACTIONS ************************* */
1629 /* ******************************************************************* */
1632 ModestMailOperation *mail_op;
1633 CreateFolderUserCallback callback;
1639 create_folder_cb (TnyFolderStore *parent_folder,
1641 TnyFolder *new_folder,
1645 ModestMailOperationPrivate *priv;
1646 CreateFolderInfo *info;
1648 info = (CreateFolderInfo *) user_data;
1649 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1651 if (canceled || err) {
1652 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1654 priv->error = g_error_copy (err);
1656 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1657 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1660 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1663 /* The user will unref the new_folder */
1665 info->callback (info->mail_op, parent_folder,
1666 new_folder, info->user_data);
1668 /* Notify about operation end */
1669 modest_mail_operation_notify_end (info->mail_op);
1672 g_object_unref (info->mail_op);
1673 g_slice_free (CreateFolderInfo, info);
1677 modest_mail_operation_create_folder (ModestMailOperation *self,
1678 TnyFolderStore *parent,
1680 CreateFolderUserCallback callback,
1683 ModestMailOperationPrivate *priv;
1685 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1686 g_return_if_fail (name);
1688 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1689 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1690 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1691 g_object_ref (parent) :
1692 modest_tny_folder_get_account (TNY_FOLDER (parent));
1694 /* Check for already existing folder */
1695 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1696 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1697 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1698 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1699 _CS("ckdg_ib_folder_already_exists"));
1703 if (TNY_IS_FOLDER (parent)) {
1704 /* Check folder rules */
1705 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1706 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1707 /* Set status failed and set an error */
1708 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1709 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1710 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1711 _("mail_in_ui_folder_create_error"));
1715 if (!strcmp (name, " ") || strchr (name, '/')) {
1716 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1717 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1718 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1719 _("mail_in_ui_folder_create_error"));
1723 CreateFolderInfo *info;
1725 info = g_slice_new0 (CreateFolderInfo);
1726 info->mail_op = g_object_ref (self);
1727 info->callback = callback;
1728 info->user_data = user_data;
1730 modest_mail_operation_notify_start (self);
1732 /* Create the folder */
1733 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1736 /* Call the user callback anyway */
1738 callback (self, parent, NULL, user_data);
1739 /* Notify about operation end */
1740 modest_mail_operation_notify_end (self);
1745 modest_mail_operation_remove_folder (ModestMailOperation *self,
1747 gboolean remove_to_trash)
1749 TnyAccount *account;
1750 ModestMailOperationPrivate *priv;
1751 ModestTnyFolderRules rules;
1753 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1754 g_return_if_fail (TNY_IS_FOLDER (folder));
1756 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1758 /* Check folder rules */
1759 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1760 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1761 /* Set status failed and set an error */
1762 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1763 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1764 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1765 _("mail_in_ui_folder_delete_error"));
1769 /* Get the account */
1770 account = modest_tny_folder_get_account (folder);
1771 priv->account = g_object_ref(account);
1772 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1774 /* Delete folder or move to trash */
1775 if (remove_to_trash) {
1776 TnyFolder *trash_folder = NULL;
1777 trash_folder = modest_tny_account_get_special_folder (account,
1778 TNY_FOLDER_TYPE_TRASH);
1779 /* TODO: error_handling */
1781 modest_mail_operation_notify_start (self);
1782 modest_mail_operation_xfer_folder (self, folder,
1783 TNY_FOLDER_STORE (trash_folder),
1785 g_object_unref (trash_folder);
1787 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1790 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1792 modest_mail_operation_notify_start (self);
1793 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1794 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1797 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1799 g_object_unref (parent);
1801 g_warning ("%s: could not get parent folder", __FUNCTION__);
1803 g_object_unref (G_OBJECT (account));
1806 /* Notify about operation end */
1807 modest_mail_operation_notify_end (self);
1811 transfer_folder_status_cb (GObject *obj,
1815 ModestMailOperation *self;
1816 ModestMailOperationPrivate *priv;
1817 ModestMailOperationState *state;
1818 XFerMsgAsyncHelper *helper;
1820 g_return_if_fail (status != NULL);
1821 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1823 helper = (XFerMsgAsyncHelper *) user_data;
1824 g_return_if_fail (helper != NULL);
1826 self = helper->mail_op;
1827 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1829 priv->done = status->position;
1830 priv->total = status->of_total;
1832 state = modest_mail_operation_clone_state (self);
1834 /* This is not a GDK lock because we are a Tinymail callback
1835 * which is already GDK locked by Tinymail */
1837 /* no gdk_threads_enter (), CHECKED */
1839 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1841 /* no gdk_threads_leave (), CHECKED */
1843 g_slice_free (ModestMailOperationState, state);
1848 transfer_folder_cb (TnyFolder *folder,
1850 TnyFolderStore *into,
1851 TnyFolder *new_folder,
1855 XFerMsgAsyncHelper *helper;
1856 ModestMailOperation *self = NULL;
1857 ModestMailOperationPrivate *priv = NULL;
1859 helper = (XFerMsgAsyncHelper *) user_data;
1860 g_return_if_fail (helper != NULL);
1862 self = helper->mail_op;
1863 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1866 priv->error = g_error_copy (err);
1868 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1869 } else if (cancelled) {
1870 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1871 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1872 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1873 _("Transference of %s was cancelled."),
1874 tny_folder_get_name (folder));
1877 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1880 /* Notify about operation end */
1881 modest_mail_operation_notify_end (self);
1883 /* If user defined callback function was defined, call it */
1884 if (helper->user_callback) {
1886 /* This is not a GDK lock because we are a Tinymail callback
1887 * which is already GDK locked by Tinymail */
1889 /* no gdk_threads_enter (), CHECKED */
1890 helper->user_callback (self, helper->user_data);
1891 /* no gdk_threads_leave () , CHECKED */
1895 g_object_unref (helper->mail_op);
1896 g_slice_free (XFerMsgAsyncHelper, helper);
1901 * This function checks if the new name is a valid name for our local
1902 * folders account. The new name could not be the same than then name
1903 * of any of the mandatory local folders
1905 * We can not rely on tinymail because tinymail does not check the
1906 * name of the virtual folders that the account could have in the case
1907 * that we're doing a rename (because it directly calls Camel which
1908 * knows nothing about our virtual folders).
1910 * In the case of an actual copy/move (i.e. move/copy a folder between
1911 * accounts) tinymail uses the tny_folder_store_create_account which
1912 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1913 * checks the new name of the folder, so this call in that case
1914 * wouldn't be needed. *But* NOTE that if tinymail changes its
1915 * implementation (if folder transfers within the same account is no
1916 * longer implemented as a rename) this call will allow Modest to work
1919 * If the new name is not valid, this function will set the status to
1920 * failed and will set also an error in the mail operation
1923 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1924 TnyFolderStore *into,
1925 const gchar *new_name)
1927 if (TNY_IS_ACCOUNT (into) &&
1928 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1929 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1931 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1932 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1933 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1934 _CS("ckdg_ib_folder_already_exists"));
1941 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1943 TnyFolderStore *parent,
1944 gboolean delete_original,
1945 XferAsyncUserCallback user_callback,
1948 ModestMailOperationPrivate *priv = NULL;
1949 ModestTnyFolderRules parent_rules = 0, rules;
1950 XFerMsgAsyncHelper *helper = NULL;
1951 const gchar *folder_name = NULL;
1952 const gchar *error_msg;
1954 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1955 g_return_if_fail (TNY_IS_FOLDER (folder));
1956 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1958 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1959 folder_name = tny_folder_get_name (folder);
1961 /* Set the error msg */
1962 error_msg = _("mail_in_ui_folder_move_target_error");
1964 /* Get account and set it into mail_operation */
1965 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1966 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1967 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1969 /* Get folder rules */
1970 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1971 if (TNY_IS_FOLDER (parent))
1972 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1974 /* Apply operation constraints */
1975 if ((gpointer) parent == (gpointer) folder ||
1976 (!TNY_IS_FOLDER_STORE (parent)) ||
1977 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1980 } else if (TNY_IS_FOLDER (parent) &&
1981 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1985 } else if (TNY_IS_FOLDER (parent) &&
1986 TNY_IS_FOLDER_STORE (folder) &&
1987 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1988 TNY_FOLDER_STORE (folder))) {
1989 /* Do not move a parent into a child */
1991 } else if (TNY_IS_FOLDER_STORE (parent) &&
1992 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1993 /* Check that the new folder name is not used by any
1996 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1997 /* Check that the new folder name is not used by any
1998 special local folder */
2001 /* Create the helper */
2002 helper = g_slice_new0 (XFerMsgAsyncHelper);
2003 helper->mail_op = g_object_ref (self);
2004 helper->dest_folder = NULL;
2005 helper->headers = NULL;
2006 helper->user_callback = user_callback;
2007 helper->user_data = user_data;
2009 /* Move/Copy folder */
2010 modest_mail_operation_notify_start (self);
2011 tny_folder_copy_async (folder,
2013 tny_folder_get_name (folder),
2016 transfer_folder_status_cb,
2022 /* Set status failed and set an error */
2023 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2024 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2025 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2028 /* Call the user callback if exists */
2030 user_callback (self, user_data);
2032 /* Notify the queue */
2033 modest_mail_operation_notify_end (self);
2037 modest_mail_operation_rename_folder (ModestMailOperation *self,
2041 ModestMailOperationPrivate *priv;
2042 ModestTnyFolderRules rules;
2043 XFerMsgAsyncHelper *helper;
2045 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2046 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2047 g_return_if_fail (name);
2049 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2051 /* Get account and set it into mail_operation */
2052 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2053 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2055 /* Check folder rules */
2056 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2057 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2058 /* Set status failed and set an error */
2059 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2060 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2061 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2062 _("FIXME: unable to rename"));
2064 /* Notify about operation end */
2065 modest_mail_operation_notify_end (self);
2066 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2067 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2068 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2069 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2070 _("FIXME: unable to rename"));
2071 /* Notify about operation end */
2072 modest_mail_operation_notify_end (self);
2074 TnyFolderStore *into;
2076 into = tny_folder_get_folder_store (folder);
2078 /* Check that the new folder name is not used by any
2079 special local folder */
2080 if (new_name_valid_if_local_account (priv, into, name)) {
2081 /* Create the helper */
2082 helper = g_slice_new0 (XFerMsgAsyncHelper);
2083 helper->mail_op = g_object_ref(self);
2084 helper->dest_folder = NULL;
2085 helper->headers = NULL;
2086 helper->user_callback = NULL;
2087 helper->user_data = NULL;
2089 /* Rename. Camel handles folder subscription/unsubscription */
2090 modest_mail_operation_notify_start (self);
2091 tny_folder_copy_async (folder, into, name, TRUE,
2093 transfer_folder_status_cb,
2096 modest_mail_operation_notify_end (self);
2098 g_object_unref (into);
2102 /* ******************************************************************* */
2103 /* ************************** MSG ACTIONS ************************* */
2104 /* ******************************************************************* */
2107 modest_mail_operation_get_msg (ModestMailOperation *self,
2109 GetMsgAsyncUserCallback user_callback,
2112 GetMsgInfo *helper = NULL;
2114 ModestMailOperationPrivate *priv;
2116 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2117 g_return_if_fail (TNY_IS_HEADER (header));
2119 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2120 folder = tny_header_get_folder (header);
2122 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2126 /* Get account and set it into mail_operation */
2127 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2129 /* Check for cached messages */
2130 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2131 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2133 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2135 /* Create the helper */
2136 helper = g_slice_new0 (GetMsgInfo);
2137 helper->header = g_object_ref (header);
2138 helper->mail_op = g_object_ref (self);
2139 helper->user_callback = user_callback;
2140 helper->user_data = user_data;
2141 helper->destroy_notify = NULL;
2142 helper->last_total_bytes = 0;
2143 helper->sum_total_bytes = 0;
2144 helper->total_bytes = tny_header_get_message_size (header);
2146 modest_mail_operation_notify_start (self);
2148 /* notify about the start of the operation */
2149 ModestMailOperationState *state;
2150 state = modest_mail_operation_clone_state (self);
2153 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2156 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2158 g_object_unref (G_OBJECT (folder));
2162 get_msg_status_cb (GObject *obj,
2166 GetMsgInfo *helper = NULL;
2168 g_return_if_fail (status != NULL);
2169 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2171 helper = (GetMsgInfo *) user_data;
2172 g_return_if_fail (helper != NULL);
2174 /* Notify progress */
2175 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2176 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2180 get_msg_async_cb (TnyFolder *folder,
2186 GetMsgInfo *info = NULL;
2187 ModestMailOperationPrivate *priv = NULL;
2190 info = (GetMsgInfo *) user_data;
2192 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2194 finished = (priv->done == priv->total) ? TRUE : FALSE;
2197 if (canceled || err) {
2198 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2200 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2201 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2204 /* Set the success status before calling the user callback */
2205 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2206 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2210 /* Call the user callback */
2211 if (info->user_callback)
2212 info->user_callback (info->mail_op, info->header, canceled,
2213 msg, err, info->user_data);
2215 /* Notify about operation end if this is the last callback */
2217 /* Free user data */
2218 if (info->destroy_notify)
2219 info->destroy_notify (info->user_data);
2221 /* Notify about operation end */
2222 modest_mail_operation_notify_end (info->mail_op);
2226 g_object_unref (info->header);
2227 g_object_unref (info->mail_op);
2228 g_slice_free (GetMsgInfo, info);
2232 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2233 TnyList *header_list,
2234 GetMsgAsyncUserCallback user_callback,
2236 GDestroyNotify notify)
2238 ModestMailOperationPrivate *priv = NULL;
2239 gboolean size_ok = TRUE;
2241 TnyIterator *iter = NULL;
2243 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2245 /* Init mail operation */
2246 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2247 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2248 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2250 priv->total = tny_list_get_length(header_list);
2252 /* Get account and set it into mail_operation */
2253 if (tny_list_get_length (header_list) >= 1) {
2254 iter = tny_list_create_iterator (header_list);
2255 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2257 TnyFolder *folder = tny_header_get_folder (header);
2259 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2260 g_object_unref (folder);
2262 g_object_unref (header);
2265 if (tny_list_get_length (header_list) == 1) {
2266 g_object_unref (iter);
2271 /* Get msg size limit */
2272 max_size = modest_conf_get_int (modest_runtime_get_conf (),
2273 MODEST_CONF_MSG_SIZE_LIMIT,
2276 g_clear_error (&(priv->error));
2277 max_size = G_MAXINT;
2279 max_size = max_size * KB;
2282 /* Check message size limits. If there is only one message
2283 always retrieve it */
2285 while (!tny_iterator_is_done (iter) && size_ok) {
2286 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2288 if (tny_header_get_message_size (header) >= max_size)
2290 g_object_unref (header);
2293 tny_iterator_next (iter);
2295 g_object_unref (iter);
2299 const gint msg_list_size = compute_message_list_size (header_list);
2301 modest_mail_operation_notify_start (self);
2302 iter = tny_list_create_iterator (header_list);
2303 while (!tny_iterator_is_done (iter)) {
2304 /* notify about the start of the operation */
2305 ModestMailOperationState *state;
2306 state = modest_mail_operation_clone_state (self);
2309 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2312 GetMsgInfo *msg_info = NULL;
2313 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2314 TnyFolder *folder = tny_header_get_folder (header);
2316 /* Create the message info */
2317 msg_info = g_slice_new0 (GetMsgInfo);
2318 msg_info->mail_op = g_object_ref (self);
2319 msg_info->header = g_object_ref (header);
2320 msg_info->user_callback = user_callback;
2321 msg_info->user_data = user_data;
2322 msg_info->destroy_notify = notify;
2323 msg_info->last_total_bytes = 0;
2324 msg_info->sum_total_bytes = 0;
2325 msg_info->total_bytes = msg_list_size;
2327 /* The callback will call it per each header */
2328 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2330 /* Free and go on */
2331 g_object_unref (header);
2332 g_object_unref (folder);
2333 tny_iterator_next (iter);
2335 g_object_unref (iter);
2337 /* Set status failed and set an error */
2338 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2339 /* FIXME: the error msg is different for pop */
2340 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2341 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
2342 _("emev_ni_ui_imap_msg_size_exceed_error"));
2343 /* Remove from queue and free resources */
2344 modest_mail_operation_notify_end (self);
2353 modest_mail_operation_remove_msg (ModestMailOperation *self,
2355 gboolean remove_to_trash /*ignored*/)
2358 ModestMailOperationPrivate *priv;
2360 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2361 g_return_if_fail (TNY_IS_HEADER (header));
2363 if (remove_to_trash)
2364 g_warning ("remove to trash is not implemented");
2366 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2367 folder = tny_header_get_folder (header);
2369 /* Get account and set it into mail_operation */
2370 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2371 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2372 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2374 /* remove message from folder */
2375 tny_folder_remove_msg (folder, header, &(priv->error));
2377 gboolean expunge, leave_on_server;
2378 const gchar *account_name;
2379 TnyAccount *account;
2380 ModestTransportStoreProtocol account_proto;
2382 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2383 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2385 modest_mail_operation_notify_start (self);
2387 /* Get leave on server setting */
2388 account = tny_folder_get_account (folder);
2389 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2391 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2394 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2396 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2397 modest_tny_folder_is_remote_folder (folder) == FALSE)
2403 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2406 g_object_unref (account);
2412 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2414 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2417 g_object_unref (G_OBJECT (folder));
2419 /* Notify about operation end */
2420 modest_mail_operation_notify_end (self);
2424 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2426 gboolean remove_to_trash /*ignored*/)
2429 ModestMailOperationPrivate *priv;
2430 TnyIterator *iter = NULL;
2431 TnyHeader *header = NULL;
2432 TnyList *remove_headers = NULL;
2433 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2435 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2436 g_return_if_fail (TNY_IS_LIST (headers));
2438 if (remove_to_trash)
2439 g_warning ("remove to trash is not implemented");
2441 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2443 remove_headers = g_object_ref(headers);
2445 /* Get folder from first header and sync it */
2446 iter = tny_list_create_iterator (headers);
2447 header = TNY_HEADER (tny_iterator_get_current (iter));
2448 folder = tny_header_get_folder (header);
2450 /* Don't remove messages that are being sent */
2451 if (modest_tny_folder_is_local_folder (folder)) {
2452 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2454 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2455 TnyTransportAccount *traccount = NULL;
2456 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2457 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2459 ModestTnySendQueueStatus status;
2460 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2461 TnyIterator *iter = tny_list_create_iterator(headers);
2462 g_object_unref(remove_headers);
2463 remove_headers = TNY_LIST(tny_simple_list_new());
2464 while (!tny_iterator_is_done(iter)) {
2466 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2467 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2468 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2469 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2470 tny_list_append(remove_headers, G_OBJECT(hdr));
2472 g_object_unref(hdr);
2474 tny_iterator_next(iter);
2476 g_object_unref(iter);
2477 g_object_unref(traccount);
2481 /* Get account and set it into mail_operation */
2482 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2483 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2484 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2486 /* remove message from folder */
2487 modest_mail_operation_notify_start (self);
2489 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2491 gboolean expunge, leave_on_server;
2492 const gchar *account_name;
2493 TnyAccount *account;
2494 ModestTransportStoreProtocol account_proto;
2496 account = tny_folder_get_account (folder);
2497 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2499 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2502 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2504 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2505 modest_tny_folder_is_remote_folder (folder) == FALSE)
2511 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2513 g_object_unref (account);
2519 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2521 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2524 g_object_unref (remove_headers);
2525 g_object_unref (header);
2526 g_object_unref (iter);
2527 g_object_unref (G_OBJECT (folder));
2529 /* Notify about operation end */
2530 modest_mail_operation_notify_end (self);
2534 notify_progress_of_multiple_messages (ModestMailOperation *self,
2536 gint *last_total_bytes,
2537 gint *sum_total_bytes,
2539 gboolean increment_done)
2541 ModestMailOperationPrivate *priv;
2542 ModestMailOperationState *state;
2543 gboolean is_num_bytes;
2545 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2547 /* We know that tinymail sends us information about
2548 transferred bytes with this particular message */
2549 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2551 state = modest_mail_operation_clone_state (self);
2552 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2553 /* We know that we're in a different message when the
2554 total number of bytes to transfer is different. Of
2555 course it could fail if we're transferring messages
2556 of the same size, but this is a workarround */
2557 if (status->of_total != *last_total_bytes) {
2558 /* We need to increment the done when there is
2559 no information about each individual
2560 message, we need to do this in message
2561 transfers, and we don't do it for getting
2565 *sum_total_bytes += *last_total_bytes;
2566 *last_total_bytes = status->of_total;
2568 state->bytes_done += status->position + *sum_total_bytes;
2569 state->bytes_total = total_bytes;
2571 /* Notify the status change. Only notify about changes
2572 referred to bytes */
2573 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2577 g_slice_free (ModestMailOperationState, state);
2581 transfer_msgs_status_cb (GObject *obj,
2585 XFerMsgAsyncHelper *helper;
2587 g_return_if_fail (status != NULL);
2588 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2590 helper = (XFerMsgAsyncHelper *) user_data;
2591 g_return_if_fail (helper != NULL);
2593 /* Notify progress */
2594 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2595 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2600 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2602 XFerMsgAsyncHelper *helper;
2603 ModestMailOperation *self;
2604 ModestMailOperationPrivate *priv;
2605 TnyIterator *iter = NULL;
2606 TnyHeader *header = NULL;
2608 helper = (XFerMsgAsyncHelper *) user_data;
2609 self = helper->mail_op;
2611 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2614 priv->error = g_error_copy (err);
2616 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2617 } else if (cancelled) {
2618 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2619 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2620 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2621 _("Error trying to refresh the contents of %s"),
2622 tny_folder_get_name (folder));
2625 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2627 /* Update folder counts */
2628 tny_folder_poke_status (folder);
2629 tny_folder_poke_status (helper->dest_folder);
2633 /* Mark headers as deleted and seen */
2634 if ((helper->delete) &&
2635 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2636 iter = tny_list_create_iterator (helper->headers);
2637 while (!tny_iterator_is_done (iter)) {
2638 header = TNY_HEADER (tny_iterator_get_current (iter));
2639 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2640 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2641 g_object_unref (header);
2643 tny_iterator_next (iter);
2649 /* Notify about operation end */
2650 modest_mail_operation_notify_end (self);
2652 /* If user defined callback function was defined, call it */
2653 if (helper->user_callback) {
2654 /* This is not a GDK lock because we are a Tinymail callback and
2655 * Tinymail already acquires the Gdk lock */
2657 /* no gdk_threads_enter (), CHECKED */
2658 helper->user_callback (self, helper->user_data);
2659 /* no gdk_threads_leave (), CHECKED */
2663 if (helper->headers)
2664 g_object_unref (helper->headers);
2665 if (helper->dest_folder)
2666 g_object_unref (helper->dest_folder);
2667 if (helper->mail_op)
2668 g_object_unref (helper->mail_op);
2670 g_object_unref (folder);
2672 g_object_unref (iter);
2673 g_slice_free (XFerMsgAsyncHelper, helper);
2677 compute_message_list_size (TnyList *headers)
2682 iter = tny_list_create_iterator (headers);
2683 while (!tny_iterator_is_done (iter)) {
2684 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2685 size += tny_header_get_message_size (header);
2686 g_object_unref (header);
2687 tny_iterator_next (iter);
2689 g_object_unref (iter);
2695 compute_message_array_size (GPtrArray *headers)
2700 for (i = 0; i < headers->len; i++) {
2701 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2702 size += tny_header_get_message_size (header);
2710 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2713 gboolean delete_original,
2714 XferAsyncUserCallback user_callback,
2717 ModestMailOperationPrivate *priv = NULL;
2718 TnyIterator *iter = NULL;
2719 TnyFolder *src_folder = NULL;
2720 XFerMsgAsyncHelper *helper = NULL;
2721 TnyHeader *header = NULL;
2722 ModestTnyFolderRules rules = 0;
2724 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2725 g_return_if_fail (headers && TNY_IS_LIST (headers));
2726 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2728 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2729 priv->total = tny_list_get_length (headers);
2731 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2732 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2734 /* Apply folder rules */
2735 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2736 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
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_FOLDER_RULES,
2741 _CS("ckct_ib_unable_to_paste_here"));
2742 /* Notify the queue */
2743 modest_mail_operation_notify_end (self);
2747 /* Get source folder */
2748 iter = tny_list_create_iterator (headers);
2749 header = TNY_HEADER (tny_iterator_get_current (iter));
2751 src_folder = tny_header_get_folder (header);
2752 g_object_unref (header);
2754 g_object_unref (iter);
2756 if (src_folder == NULL) {
2757 /* Notify the queue */
2758 modest_mail_operation_notify_end (self);
2760 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2765 /* Check folder source and destination */
2766 if (src_folder == folder) {
2767 /* Set status failed and set an error */
2768 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2769 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2770 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2771 _("mail_in_ui_folder_copy_target_error"));
2773 /* Notify the queue */
2774 modest_mail_operation_notify_end (self);
2777 g_object_unref (src_folder);
2781 /* Create the helper */
2782 helper = g_slice_new0 (XFerMsgAsyncHelper);
2783 helper->mail_op = g_object_ref(self);
2784 helper->dest_folder = g_object_ref(folder);
2785 helper->headers = g_object_ref(headers);
2786 helper->user_callback = user_callback;
2787 helper->user_data = user_data;
2788 helper->delete = delete_original;
2789 helper->last_total_bytes = 0;
2790 helper->sum_total_bytes = 0;
2791 helper->total_bytes = compute_message_list_size (headers);
2793 /* Get account and set it into mail_operation */
2794 priv->account = modest_tny_folder_get_account (src_folder);
2796 /* Transfer messages */
2797 modest_mail_operation_notify_start (self);
2798 tny_folder_transfer_msgs_async (src_folder,
2803 transfer_msgs_status_cb,
2809 on_refresh_folder (TnyFolder *folder,
2814 RefreshAsyncHelper *helper = NULL;
2815 ModestMailOperation *self = NULL;
2816 ModestMailOperationPrivate *priv = NULL;
2818 helper = (RefreshAsyncHelper *) user_data;
2819 self = helper->mail_op;
2820 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2822 g_return_if_fail(priv!=NULL);
2825 priv->error = g_error_copy (error);
2826 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2831 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2832 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2833 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2834 _("Error trying to refresh the contents of %s"),
2835 tny_folder_get_name (folder));
2839 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2842 /* Call user defined callback, if it exists */
2843 if (helper->user_callback) {
2845 /* This is not a GDK lock because we are a Tinymail callback and
2846 * Tinymail already acquires the Gdk lock */
2847 helper->user_callback (self, folder, helper->user_data);
2851 g_slice_free (RefreshAsyncHelper, helper);
2853 /* Notify about operation end */
2854 modest_mail_operation_notify_end (self);
2855 g_object_unref(self);
2859 on_refresh_folder_status_update (GObject *obj,
2863 RefreshAsyncHelper *helper = NULL;
2864 ModestMailOperation *self = NULL;
2865 ModestMailOperationPrivate *priv = NULL;
2866 ModestMailOperationState *state;
2868 g_return_if_fail (user_data != NULL);
2869 g_return_if_fail (status != NULL);
2870 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2872 helper = (RefreshAsyncHelper *) user_data;
2873 self = helper->mail_op;
2874 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2876 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2878 priv->done = status->position;
2879 priv->total = status->of_total;
2881 state = modest_mail_operation_clone_state (self);
2883 /* This is not a GDK lock because we are a Tinymail callback and
2884 * Tinymail already acquires the Gdk lock */
2885 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2887 g_slice_free (ModestMailOperationState, state);
2891 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2893 RefreshAsyncUserCallback user_callback,
2896 ModestMailOperationPrivate *priv = NULL;
2897 RefreshAsyncHelper *helper = NULL;
2899 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2901 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2903 /* Get account and set it into mail_operation */
2904 priv->account = modest_tny_folder_get_account (folder);
2905 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2907 /* Create the helper */
2908 helper = g_slice_new0 (RefreshAsyncHelper);
2909 helper->mail_op = g_object_ref(self);
2910 helper->user_callback = user_callback;
2911 helper->user_data = user_data;
2913 /* Refresh the folder. TODO: tinymail could issue a status
2914 updates before the callback call then this could happen. We
2915 must review the design */
2916 modest_mail_operation_notify_start (self);
2918 /* notify that the operation was started */
2919 ModestMailOperationState *state;
2920 state = modest_mail_operation_clone_state (self);
2923 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2926 tny_folder_refresh_async (folder,
2928 on_refresh_folder_status_update,
2934 modest_mail_operation_notify_start (ModestMailOperation *self)
2936 ModestMailOperationPrivate *priv = NULL;
2938 g_return_if_fail (self);
2940 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2942 /* Ensure that all the fields are filled correctly */
2943 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2945 /* Notify the observers about the mail operation. We do not
2946 wrapp this emission because we assume that this function is
2947 always called from within the main lock */
2948 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2953 * It's used by the mail operation queue to notify the observers
2954 * attached to that signal that the operation finished. We need to use
2955 * that because tinymail does not give us the progress of a given
2956 * operation when it finishes (it directly calls the operation
2960 modest_mail_operation_notify_end (ModestMailOperation *self)
2962 ModestMailOperationPrivate *priv = NULL;
2964 g_return_if_fail (self);
2966 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2968 /* Notify the observers about the mail operation end. We do
2969 not wrapp this emission because we assume that this
2970 function is always called from within the main lock */
2971 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2973 /* Remove the error user data */
2974 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2975 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2979 modest_mail_operation_get_account (ModestMailOperation *self)
2981 ModestMailOperationPrivate *priv = NULL;
2983 g_return_val_if_fail (self, NULL);
2985 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2987 return (priv->account) ? g_object_ref (priv->account) : NULL;
2991 modest_mail_operation_noop (ModestMailOperation *self)
2993 ModestMailOperationPrivate *priv = NULL;
2995 g_return_if_fail (self);
2997 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2998 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2999 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3003 /* This mail operation does nothing actually */
3004 modest_mail_operation_notify_start (self);
3005 modest_mail_operation_notify_end (self);