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);
875 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
876 TNY_FOLDER_TYPE_OUTBOX);
877 if (info->draft_msg != NULL) {
878 TnyFolder *folder = NULL;
879 TnyFolder *src_folder = NULL;
880 TnyFolderType folder_type;
881 folder = tny_msg_get_folder (info->draft_msg);
882 if (folder == NULL) goto end;
883 folder_type = modest_tny_folder_guess_folder_type (folder);
885 if (folder_type == TNY_FOLDER_TYPE_INVALID)
886 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
888 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
889 src_folder = outbox_folder;
891 src_folder = draft_folder;
893 /* Note: This can fail (with a warning) if the message is not really already in a folder,
894 * because this function requires it to have a UID. */
895 header = tny_msg_get_header (info->draft_msg);
896 tny_folder_remove_msg (src_folder, header, NULL);
898 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
899 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
901 g_object_unref (header);
902 g_object_unref (folder);
909 g_object_unref (info->draft_msg);
911 g_object_unref (draft_folder);
913 g_object_unref (outbox_folder);
914 if (info->transport_account)
915 g_object_unref (info->transport_account);
916 g_slice_free (SendNewMailInfo, info);
920 modest_mail_operation_send_new_mail (ModestMailOperation *self,
921 TnyTransportAccount *transport_account,
923 const gchar *from, const gchar *to,
924 const gchar *cc, const gchar *bcc,
925 const gchar *subject, const gchar *plain_body,
926 const gchar *html_body,
927 const GList *attachments_list,
928 const GList *images_list,
929 TnyHeaderFlags priority_flags)
931 ModestMailOperationPrivate *priv = NULL;
932 SendNewMailInfo *info;
934 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
935 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
937 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
938 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
939 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
940 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
942 /* Check parametters */
944 /* Set status failed and set an error */
945 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
946 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
947 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
948 _("Error trying to send a mail. You need to set at least one recipient"));
951 info = g_slice_new0 (SendNewMailInfo);
952 info->transport_account = transport_account;
953 if (transport_account)
954 g_object_ref (transport_account);
955 info->draft_msg = draft_msg;
957 g_object_ref (draft_msg);
960 modest_mail_operation_notify_start (self);
961 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
962 attachments_list, images_list, priority_flags,
963 modest_mail_operation_send_new_mail_cb, info);
969 TnyTransportAccount *transport_account;
971 SaveToDraftstCallback callback;
975 ModestMailOperation *mailop;
976 } SaveToDraftsAddMsgInfo;
979 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
984 ModestMailOperationPrivate *priv = NULL;
985 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
987 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
990 g_warning ("%s: priv->error != NULL", __FUNCTION__);
991 g_error_free(priv->error);
994 priv->error = (err == NULL) ? NULL : g_error_copy(err);
996 if ((!priv->error) && (info->draft_msg != NULL)) {
997 TnyHeader *header = tny_msg_get_header (info->draft_msg);
998 TnyFolder *src_folder = tny_header_get_folder (header);
1000 /* Remove the old draft */
1001 tny_folder_remove_msg (src_folder, header, NULL);
1003 /* Synchronize to expunge and to update the msg counts */
1004 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1005 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1007 g_object_unref (G_OBJECT(header));
1008 g_object_unref (G_OBJECT(src_folder));
1012 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1014 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1016 /* Call the user callback */
1018 info->callback (info->mailop, info->msg, info->user_data);
1020 if (info->transport_account)
1021 g_object_unref (G_OBJECT(info->transport_account));
1022 if (info->draft_msg)
1023 g_object_unref (G_OBJECT (info->draft_msg));
1025 g_object_unref (G_OBJECT(info->drafts));
1027 g_object_unref (G_OBJECT (info->msg));
1028 g_slice_free (SaveToDraftsAddMsgInfo, info);
1030 modest_mail_operation_notify_end (info->mailop);
1031 g_object_unref(info->mailop);
1036 TnyTransportAccount *transport_account;
1038 SaveToDraftstCallback callback;
1043 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1047 TnyFolder *drafts = NULL;
1048 ModestMailOperationPrivate *priv = NULL;
1049 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1051 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1054 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1055 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1056 "modest: failed to create a new msg\n");
1058 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1059 TNY_FOLDER_TYPE_DRAFTS);
1061 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1062 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1063 "modest: failed to create a new msg\n");
1068 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1069 cb_info->transport_account = g_object_ref(info->transport_account);
1070 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1071 cb_info->callback = info->callback;
1072 cb_info->user_data = info->user_data;
1073 cb_info->drafts = g_object_ref(drafts);
1074 cb_info->msg = g_object_ref(msg);
1075 cb_info->mailop = g_object_ref(self);
1076 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1079 /* Call the user callback */
1080 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1082 info->callback (self, msg, info->user_data);
1083 modest_mail_operation_notify_end (self);
1087 g_object_unref (G_OBJECT(drafts));
1088 if (info->draft_msg)
1089 g_object_unref (G_OBJECT (info->draft_msg));
1090 if (info->transport_account)
1091 g_object_unref (G_OBJECT(info->transport_account));
1092 g_slice_free (SaveToDraftsInfo, info);
1096 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1097 TnyTransportAccount *transport_account,
1099 const gchar *from, const gchar *to,
1100 const gchar *cc, const gchar *bcc,
1101 const gchar *subject, const gchar *plain_body,
1102 const gchar *html_body,
1103 const GList *attachments_list,
1104 const GList *images_list,
1105 TnyHeaderFlags priority_flags,
1106 SaveToDraftstCallback callback,
1109 ModestMailOperationPrivate *priv = NULL;
1110 SaveToDraftsInfo *info = NULL;
1112 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1113 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1115 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1117 /* Get account and set it into mail_operation */
1118 priv->account = g_object_ref (transport_account);
1119 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1121 info = g_slice_new0 (SaveToDraftsInfo);
1122 info->transport_account = g_object_ref (transport_account);
1123 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1124 info->callback = callback;
1125 info->user_data = user_data;
1127 modest_mail_operation_notify_start (self);
1128 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1129 attachments_list, images_list, priority_flags,
1130 modest_mail_operation_save_to_drafts_cb, info);
1135 ModestMailOperation *mail_op;
1136 TnyMimePart *mime_part;
1138 GetMimePartSizeCallback callback;
1140 } GetMimePartSizeInfo;
1142 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1143 /* We use this folder observer to track the headers that have been
1144 * added to a folder */
1147 TnyList *new_headers;
1148 } InternalFolderObserver;
1151 GObjectClass parent;
1152 } InternalFolderObserverClass;
1154 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1156 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1157 internal_folder_observer,
1159 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1163 foreach_add_item (gpointer header, gpointer user_data)
1165 tny_list_prepend (TNY_LIST (user_data),
1166 g_object_ref (G_OBJECT (header)));
1169 /* This is the method that looks for new messages in a folder */
1171 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1173 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1175 TnyFolderChangeChanged changed;
1177 changed = tny_folder_change_get_changed (change);
1179 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1182 /* Get added headers */
1183 list = tny_simple_list_new ();
1184 tny_folder_change_get_added_headers (change, list);
1186 /* Add them to the folder observer */
1187 tny_list_foreach (list, foreach_add_item,
1188 derived->new_headers);
1190 g_object_unref (G_OBJECT (list));
1195 internal_folder_observer_init (InternalFolderObserver *self)
1197 self->new_headers = tny_simple_list_new ();
1200 internal_folder_observer_finalize (GObject *object)
1202 InternalFolderObserver *self;
1204 self = (InternalFolderObserver *) object;
1205 g_object_unref (self->new_headers);
1207 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1210 tny_folder_observer_init (TnyFolderObserverIface *iface)
1212 iface->update_func = internal_folder_observer_update;
1215 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1217 GObjectClass *object_class;
1219 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1220 object_class = (GObjectClass*) klass;
1221 object_class->finalize = internal_folder_observer_finalize;
1226 ModestMailOperation *mail_op;
1227 gchar *account_name;
1228 UpdateAccountCallback callback;
1233 TnyFolderObserver *inbox_observer;
1234 guint update_timeout;
1235 RetrieveAllCallback retrieve_all_cb;
1236 } UpdateAccountInfo;
1240 destroy_update_account_info (UpdateAccountInfo *info)
1242 if (info->update_timeout) {
1243 g_source_remove (info->update_timeout);
1244 info->update_timeout = 0;
1247 g_free (info->account_name);
1248 g_object_unref (info->folders);
1249 g_object_unref (info->mail_op);
1250 g_slice_free (UpdateAccountInfo, info);
1254 update_account_get_msg_async_cb (TnyFolder *folder,
1260 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1262 /* Just delete the helper. Don't do anything with the new
1263 msg. There is also no need to check for errors */
1264 g_object_unref (msg_info->mail_op);
1265 g_object_unref (msg_info->header);
1266 g_slice_free (GetMsgInfo, msg_info);
1271 inbox_refreshed_cb (TnyFolder *inbox,
1276 UpdateAccountInfo *info;
1277 ModestMailOperationPrivate *priv;
1278 TnyIterator *new_headers_iter;
1279 GPtrArray *new_headers_array = NULL;
1280 gint max_size, retrieve_limit, i;
1281 ModestAccountMgr *mgr;
1282 ModestAccountRetrieveType retrieve_type;
1283 TnyList *new_headers = NULL;
1284 gboolean headers_only, ignore_limit;
1285 TnyTransportAccount *transport_account;
1286 ModestTnySendQueue *send_queue;
1288 info = (UpdateAccountInfo *) user_data;
1289 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1290 mgr = modest_runtime_get_account_mgr ();
1292 if (canceled || err || !inbox) {
1293 /* Try to send anyway */
1297 /* Get the message max size */
1298 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1299 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1301 max_size = G_MAXINT;
1303 max_size = max_size * KB;
1305 /* Create the new headers array. We need it to sort the
1306 new headers by date */
1307 new_headers_array = g_ptr_array_new ();
1308 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1309 while (!tny_iterator_is_done (new_headers_iter)) {
1310 TnyHeader *header = NULL;
1312 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1313 /* Apply per-message size limits */
1314 if (tny_header_get_message_size (header) < max_size)
1315 g_ptr_array_add (new_headers_array, g_object_ref (header));
1317 g_object_unref (header);
1318 tny_iterator_next (new_headers_iter);
1320 g_object_unref (new_headers_iter);
1321 tny_folder_remove_observer (inbox, info->inbox_observer);
1322 g_object_unref (info->inbox_observer);
1323 info->inbox_observer = NULL;
1325 /* Update the last updated key, even if we don't have to get new headers */
1326 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1328 if (new_headers_array->len == 0)
1331 /* Get per-account message amount retrieval limit */
1332 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1333 if (retrieve_limit == 0)
1334 retrieve_limit = G_MAXINT;
1336 /* Get per-account retrieval type */
1337 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1338 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1341 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1343 /* Ask the users if they want to retrieve all the messages
1344 even though the limit was exceeded */
1345 ignore_limit = FALSE;
1346 if (new_headers_array->len > retrieve_limit) {
1347 /* Ask the user if a callback has been specified and
1348 if the mail operation has a source (this means that
1349 was invoked by the user and not automatically by a
1351 if (info->retrieve_all_cb && priv->source)
1352 ignore_limit = info->retrieve_all_cb (priv->source,
1353 new_headers_array->len,
1357 if (!headers_only) {
1359 const gint msg_list_size = compute_message_array_size (new_headers_array);
1363 priv->total = new_headers_array->len;
1365 priv->total = MIN (new_headers_array->len, retrieve_limit);
1366 while (msg_num < priv->total) {
1367 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1368 TnyFolder *folder = tny_header_get_folder (header);
1369 GetMsgInfo *msg_info;
1371 /* Create the message info */
1372 msg_info = g_slice_new0 (GetMsgInfo);
1373 msg_info->mail_op = g_object_ref (info->mail_op);
1374 msg_info->header = g_object_ref (header);
1375 msg_info->total_bytes = msg_list_size;
1377 /* Get message in an async way */
1378 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1379 get_msg_status_cb, msg_info);
1381 g_object_unref (folder);
1387 /* Copy the headers to a list and free the array */
1388 new_headers = tny_simple_list_new ();
1389 for (i=0; i < new_headers_array->len; i++) {
1390 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1391 tny_list_append (new_headers, G_OBJECT (header));
1393 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1394 g_ptr_array_free (new_headers_array, FALSE);
1401 /* Get the transport account */
1402 transport_account = (TnyTransportAccount *)
1403 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1404 info->account_name);
1407 send_queue = modest_runtime_get_send_queue (transport_account);
1408 modest_tny_send_queue_try_to_send (send_queue);
1410 /* Check if the operation was a success */
1412 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1414 /* Set the account back to not busy */
1415 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1417 /* Call the user callback */
1419 info->callback (info->mail_op, new_headers, info->user_data);
1421 /* Notify about operation end */
1422 modest_mail_operation_notify_end (info->mail_op);
1426 g_object_unref (new_headers);
1427 destroy_update_account_info (info);
1431 recurse_folders_async_cb (TnyFolderStore *folder_store,
1437 UpdateAccountInfo *info;
1438 ModestMailOperationPrivate *priv;
1440 info = (UpdateAccountInfo *) user_data;
1441 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1443 if (err || canceled) {
1444 /* Try to continue anyway */
1446 TnyIterator *iter = tny_list_create_iterator (list);
1447 while (!tny_iterator_is_done (iter)) {
1448 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1449 TnyList *folders = tny_simple_list_new ();
1451 /* Add to the list of all folders */
1452 tny_list_append (info->folders, (GObject *) folder);
1454 /* Add pending call */
1455 info->pending_calls++;
1457 tny_folder_store_get_folders_async (folder, folders, recurse_folders_async_cb,
1460 g_object_unref (G_OBJECT (folder));
1462 tny_iterator_next (iter);
1464 g_object_unref (G_OBJECT (iter));
1465 g_object_unref (G_OBJECT (list));
1468 /* Remove my own pending call */
1469 info->pending_calls--;
1471 /* This means that we have all the folders */
1472 if (info->pending_calls == 0) {
1473 TnyIterator *iter_all_folders;
1474 TnyFolder *inbox = NULL;
1476 iter_all_folders = tny_list_create_iterator (info->folders);
1478 /* Do a poke status over all folders */
1479 while (!tny_iterator_is_done (iter_all_folders) &&
1480 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1481 TnyFolder *folder = NULL;
1483 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1485 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1486 /* Get a reference to the INBOX */
1487 inbox = g_object_ref (folder);
1489 /* Issue a poke status over the folder */
1491 tny_folder_poke_status (folder);
1494 /* Free and go to next */
1495 g_object_unref (folder);
1496 tny_iterator_next (iter_all_folders);
1498 g_object_unref (iter_all_folders);
1500 /* Stop the progress notification */
1501 g_source_remove (info->update_timeout);
1502 info->update_timeout = 0;
1504 /* Refresh the INBOX */
1506 /* Refresh the folder. Our observer receives
1507 * the new emails during folder refreshes, so
1508 * we can use observer->new_headers
1510 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1511 tny_folder_add_observer (inbox, info->inbox_observer);
1513 /* Refresh the INBOX */
1514 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1515 g_object_unref (inbox);
1517 /* We could not perform the inbox refresh but
1518 we'll try to send mails anyway */
1519 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1525 * Issues the "progress-changed" signal. The timer won't be removed,
1526 * so you must call g_source_remove to stop the signal emission
1529 timeout_notify_progress (gpointer data)
1531 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1532 ModestMailOperationState *state;
1534 state = modest_mail_operation_clone_state (mail_op);
1536 /* This is a GDK lock because we are an idle callback and
1537 * the handlers of this signal can contain Gtk+ code */
1539 gdk_threads_enter (); /* CHECKED */
1540 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1541 gdk_threads_leave (); /* CHECKED */
1543 g_slice_free (ModestMailOperationState, state);
1549 modest_mail_operation_update_account (ModestMailOperation *self,
1550 const gchar *account_name,
1552 RetrieveAllCallback retrieve_all_cb,
1553 UpdateAccountCallback callback,
1556 UpdateAccountInfo *info = NULL;
1557 ModestMailOperationPrivate *priv = NULL;
1558 ModestTnyAccountStore *account_store = NULL;
1559 TnyStoreAccount *store_account = NULL;
1562 /* Init mail operation */
1563 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1566 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1567 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1569 /* Get the store account */
1570 account_store = modest_runtime_get_account_store ();
1571 store_account = (TnyStoreAccount *)
1572 modest_tny_account_store_get_server_account (account_store,
1574 TNY_ACCOUNT_TYPE_STORE);
1575 priv->account = g_object_ref (store_account);
1577 /* Create the helper object */
1578 info = g_slice_new0 (UpdateAccountInfo);
1579 info->pending_calls = 1;
1580 info->folders = tny_simple_list_new ();
1581 info->mail_op = g_object_ref (self);
1582 info->poke_all = poke_all;
1583 info->account_name = g_strdup (account_name);
1584 info->callback = callback;
1585 info->user_data = user_data;
1586 info->update_timeout = g_timeout_add (250, timeout_notify_progress, self);
1587 info->retrieve_all_cb = retrieve_all_cb;
1589 /* Set account busy */
1590 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1591 modest_mail_operation_notify_start (self);
1593 /* notify about the start of the operation */
1594 ModestMailOperationState *state;
1595 state = modest_mail_operation_clone_state (self);
1598 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
1601 /* Get all folders and continue in the callback */
1602 folders = tny_simple_list_new ();
1603 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1604 folders, recurse_folders_async_cb,
1609 * Used to notify the queue from the main
1610 * loop. We call it inside an idle call to achieve that
1613 idle_notify_queue (gpointer data)
1615 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1617 gdk_threads_enter ();
1618 modest_mail_operation_notify_end (mail_op);
1619 gdk_threads_leave ();
1620 g_object_unref (mail_op);
1626 compare_headers_by_date (gconstpointer a,
1629 TnyHeader **header1, **header2;
1630 time_t sent1, sent2;
1632 header1 = (TnyHeader **) a;
1633 header2 = (TnyHeader **) b;
1635 sent1 = tny_header_get_date_sent (*header1);
1636 sent2 = tny_header_get_date_sent (*header2);
1638 /* We want the most recent ones (greater time_t) at the
1647 /* ******************************************************************* */
1648 /* ************************** STORE ACTIONS ************************* */
1649 /* ******************************************************************* */
1652 ModestMailOperation *mail_op;
1653 CreateFolderUserCallback callback;
1659 create_folder_cb (TnyFolderStore *parent_folder,
1661 TnyFolder *new_folder,
1665 ModestMailOperationPrivate *priv;
1666 CreateFolderInfo *info;
1668 info = (CreateFolderInfo *) user_data;
1669 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1671 if (canceled || err) {
1672 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1674 priv->error = g_error_copy (err);
1676 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1677 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1680 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1683 /* The user will unref the new_folder */
1685 info->callback (info->mail_op, parent_folder,
1686 new_folder, info->user_data);
1688 /* Notify about operation end */
1689 modest_mail_operation_notify_end (info->mail_op);
1692 g_object_unref (info->mail_op);
1693 g_slice_free (CreateFolderInfo, info);
1697 modest_mail_operation_create_folder (ModestMailOperation *self,
1698 TnyFolderStore *parent,
1700 CreateFolderUserCallback callback,
1703 ModestMailOperationPrivate *priv;
1705 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1706 g_return_if_fail (name);
1708 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1709 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1710 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1711 g_object_ref (parent) :
1712 modest_tny_folder_get_account (TNY_FOLDER (parent));
1714 /* Check for already existing folder */
1715 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1716 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1717 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1718 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1719 _CS("ckdg_ib_folder_already_exists"));
1723 if (TNY_IS_FOLDER (parent)) {
1724 /* Check folder rules */
1725 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1726 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1727 /* Set status failed and set an error */
1728 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1729 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1730 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1731 _("mail_in_ui_folder_create_error"));
1735 if (!strcmp (name, " ") || strchr (name, '/')) {
1736 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1737 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1738 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1739 _("mail_in_ui_folder_create_error"));
1743 CreateFolderInfo *info;
1745 info = g_slice_new0 (CreateFolderInfo);
1746 info->mail_op = g_object_ref (self);
1747 info->callback = callback;
1748 info->user_data = user_data;
1750 modest_mail_operation_notify_start (self);
1752 /* Create the folder */
1753 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1756 /* Call the user callback anyway */
1758 callback (self, parent, NULL, user_data);
1759 /* Notify about operation end */
1760 modest_mail_operation_notify_end (self);
1765 modest_mail_operation_remove_folder (ModestMailOperation *self,
1767 gboolean remove_to_trash)
1769 TnyAccount *account;
1770 ModestMailOperationPrivate *priv;
1771 ModestTnyFolderRules rules;
1773 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1774 g_return_if_fail (TNY_IS_FOLDER (folder));
1776 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1778 /* Check folder rules */
1779 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1780 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1781 /* Set status failed and set an error */
1782 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1783 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1784 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1785 _("mail_in_ui_folder_delete_error"));
1789 /* Get the account */
1790 account = modest_tny_folder_get_account (folder);
1791 priv->account = g_object_ref(account);
1792 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1794 /* Delete folder or move to trash */
1795 if (remove_to_trash) {
1796 TnyFolder *trash_folder = NULL;
1797 trash_folder = modest_tny_account_get_special_folder (account,
1798 TNY_FOLDER_TYPE_TRASH);
1799 /* TODO: error_handling */
1801 modest_mail_operation_notify_start (self);
1802 modest_mail_operation_xfer_folder (self, folder,
1803 TNY_FOLDER_STORE (trash_folder),
1805 g_object_unref (trash_folder);
1808 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1810 modest_mail_operation_notify_start (self);
1811 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1812 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1815 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1817 g_object_unref (parent);
1819 g_warning ("%s: could not get parent folder", __FUNCTION__);
1821 g_object_unref (G_OBJECT (account));
1824 /* Notify about operation end */
1825 modest_mail_operation_notify_end (self);
1829 transfer_folder_status_cb (GObject *obj,
1833 ModestMailOperation *self;
1834 ModestMailOperationPrivate *priv;
1835 ModestMailOperationState *state;
1836 XFerMsgAsyncHelper *helper;
1838 g_return_if_fail (status != NULL);
1839 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1841 helper = (XFerMsgAsyncHelper *) user_data;
1842 g_return_if_fail (helper != NULL);
1844 self = helper->mail_op;
1845 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1847 priv->done = status->position;
1848 priv->total = status->of_total;
1850 state = modest_mail_operation_clone_state (self);
1852 /* This is not a GDK lock because we are a Tinymail callback
1853 * which is already GDK locked by Tinymail */
1855 /* no gdk_threads_enter (), CHECKED */
1857 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1859 /* no gdk_threads_leave (), CHECKED */
1861 g_slice_free (ModestMailOperationState, state);
1866 transfer_folder_cb (TnyFolder *folder,
1868 TnyFolderStore *into,
1869 TnyFolder *new_folder,
1873 XFerMsgAsyncHelper *helper;
1874 ModestMailOperation *self = NULL;
1875 ModestMailOperationPrivate *priv = NULL;
1877 helper = (XFerMsgAsyncHelper *) user_data;
1878 g_return_if_fail (helper != NULL);
1880 self = helper->mail_op;
1881 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1884 priv->error = g_error_copy (err);
1886 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1887 } else if (cancelled) {
1888 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1889 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1890 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1891 _("Transference of %s was cancelled."),
1892 tny_folder_get_name (folder));
1895 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1898 /* Notify about operation end */
1899 modest_mail_operation_notify_end (self);
1901 /* If user defined callback function was defined, call it */
1902 if (helper->user_callback) {
1904 /* This is not a GDK lock because we are a Tinymail callback
1905 * which is already GDK locked by Tinymail */
1907 /* no gdk_threads_enter (), CHECKED */
1908 helper->user_callback (self, helper->user_data);
1909 /* no gdk_threads_leave () , CHECKED */
1913 g_object_unref (helper->mail_op);
1914 g_slice_free (XFerMsgAsyncHelper, helper);
1919 * This function checks if the new name is a valid name for our local
1920 * folders account. The new name could not be the same than then name
1921 * of any of the mandatory local folders
1923 * We can not rely on tinymail because tinymail does not check the
1924 * name of the virtual folders that the account could have in the case
1925 * that we're doing a rename (because it directly calls Camel which
1926 * knows nothing about our virtual folders).
1928 * In the case of an actual copy/move (i.e. move/copy a folder between
1929 * accounts) tinymail uses the tny_folder_store_create_account which
1930 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1931 * checks the new name of the folder, so this call in that case
1932 * wouldn't be needed. *But* NOTE that if tinymail changes its
1933 * implementation (if folder transfers within the same account is no
1934 * longer implemented as a rename) this call will allow Modest to work
1937 * If the new name is not valid, this function will set the status to
1938 * failed and will set also an error in the mail operation
1941 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1942 TnyFolderStore *into,
1943 const gchar *new_name)
1945 if (TNY_IS_ACCOUNT (into) &&
1946 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1947 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1949 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1950 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1951 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1952 _CS("ckdg_ib_folder_already_exists"));
1959 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1961 TnyFolderStore *parent,
1962 gboolean delete_original,
1963 XferAsyncUserCallback user_callback,
1966 ModestMailOperationPrivate *priv = NULL;
1967 ModestTnyFolderRules parent_rules = 0, rules;
1968 XFerMsgAsyncHelper *helper = NULL;
1969 const gchar *folder_name = NULL;
1970 const gchar *error_msg;
1972 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1973 g_return_if_fail (TNY_IS_FOLDER (folder));
1974 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1976 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1977 folder_name = tny_folder_get_name (folder);
1979 /* Set the error msg */
1980 error_msg = _("mail_in_ui_folder_move_target_error");
1982 /* Get account and set it into mail_operation */
1983 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1984 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1985 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1987 /* Get folder rules */
1988 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1989 if (TNY_IS_FOLDER (parent))
1990 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1992 /* Apply operation constraints */
1993 if ((gpointer) parent == (gpointer) folder ||
1994 (!TNY_IS_FOLDER_STORE (parent)) ||
1995 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1998 } else if (TNY_IS_FOLDER (parent) &&
1999 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2003 } else if (TNY_IS_FOLDER (parent) &&
2004 TNY_IS_FOLDER_STORE (folder) &&
2005 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2006 TNY_FOLDER_STORE (folder))) {
2007 /* Do not move a parent into a child */
2009 } else if (TNY_IS_FOLDER_STORE (parent) &&
2010 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2011 /* Check that the new folder name is not used by any
2014 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2015 /* Check that the new folder name is not used by any
2016 special local folder */
2019 /* Create the helper */
2020 helper = g_slice_new0 (XFerMsgAsyncHelper);
2021 helper->mail_op = g_object_ref (self);
2022 helper->dest_folder = NULL;
2023 helper->headers = NULL;
2024 helper->user_callback = user_callback;
2025 helper->user_data = user_data;
2027 /* Move/Copy folder */
2028 modest_mail_operation_notify_start (self);
2029 tny_folder_copy_async (folder,
2031 tny_folder_get_name (folder),
2034 transfer_folder_status_cb,
2040 /* Set status failed and set an error */
2041 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2042 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2043 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2046 /* Call the user callback if exists */
2048 user_callback (self, user_data);
2050 /* Notify the queue */
2051 modest_mail_operation_notify_end (self);
2055 modest_mail_operation_rename_folder (ModestMailOperation *self,
2059 ModestMailOperationPrivate *priv;
2060 ModestTnyFolderRules rules;
2061 XFerMsgAsyncHelper *helper;
2063 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2064 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2065 g_return_if_fail (name);
2067 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2069 /* Get account and set it into mail_operation */
2070 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2071 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2073 /* Check folder rules */
2074 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2075 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2076 /* Set status failed and set an error */
2077 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2078 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2079 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2080 _("FIXME: unable to rename"));
2082 /* Notify about operation end */
2083 modest_mail_operation_notify_end (self);
2084 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2085 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2086 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2087 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2088 _("FIXME: unable to rename"));
2089 /* Notify about operation end */
2090 modest_mail_operation_notify_end (self);
2092 TnyFolderStore *into;
2094 into = tny_folder_get_folder_store (folder);
2096 /* Check that the new folder name is not used by any
2097 special local folder */
2098 if (new_name_valid_if_local_account (priv, into, name)) {
2099 /* Create the helper */
2100 helper = g_slice_new0 (XFerMsgAsyncHelper);
2101 helper->mail_op = g_object_ref(self);
2102 helper->dest_folder = NULL;
2103 helper->headers = NULL;
2104 helper->user_callback = NULL;
2105 helper->user_data = NULL;
2107 /* Rename. Camel handles folder subscription/unsubscription */
2108 modest_mail_operation_notify_start (self);
2109 tny_folder_copy_async (folder, into, name, TRUE,
2111 transfer_folder_status_cb,
2114 modest_mail_operation_notify_end (self);
2116 g_object_unref (into);
2120 /* ******************************************************************* */
2121 /* ************************** MSG ACTIONS ************************* */
2122 /* ******************************************************************* */
2125 modest_mail_operation_get_msg (ModestMailOperation *self,
2127 GetMsgAsyncUserCallback user_callback,
2130 GetMsgInfo *helper = NULL;
2132 ModestMailOperationPrivate *priv;
2134 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2135 g_return_if_fail (TNY_IS_HEADER (header));
2137 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2138 folder = tny_header_get_folder (header);
2140 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2144 /* Get account and set it into mail_operation */
2145 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2147 /* Check for cached messages */
2148 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2149 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2151 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2153 /* Create the helper */
2154 helper = g_slice_new0 (GetMsgInfo);
2155 helper->header = g_object_ref (header);
2156 helper->mail_op = g_object_ref (self);
2157 helper->user_callback = user_callback;
2158 helper->user_data = user_data;
2159 helper->destroy_notify = NULL;
2160 helper->last_total_bytes = 0;
2161 helper->sum_total_bytes = 0;
2162 helper->total_bytes = tny_header_get_message_size (header);
2164 modest_mail_operation_notify_start (self);
2166 /* notify about the start of the operation */
2167 ModestMailOperationState *state;
2168 state = modest_mail_operation_clone_state (self);
2171 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2174 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2176 g_object_unref (G_OBJECT (folder));
2180 get_msg_status_cb (GObject *obj,
2184 GetMsgInfo *helper = NULL;
2186 g_return_if_fail (status != NULL);
2187 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2189 helper = (GetMsgInfo *) user_data;
2190 g_return_if_fail (helper != NULL);
2192 /* Notify progress */
2193 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2194 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2198 get_msg_async_cb (TnyFolder *folder,
2204 GetMsgInfo *info = NULL;
2205 ModestMailOperationPrivate *priv = NULL;
2208 info = (GetMsgInfo *) user_data;
2210 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2212 finished = (priv->done == priv->total) ? TRUE : FALSE;
2215 if (canceled || err) {
2216 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2218 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2219 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2222 /* Set the success status before calling the user callback */
2223 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2224 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2228 /* Call the user callback */
2229 if (info->user_callback)
2230 info->user_callback (info->mail_op, info->header, canceled,
2231 msg, err, info->user_data);
2233 /* Notify about operation end if this is the last callback */
2235 /* Free user data */
2236 if (info->destroy_notify)
2237 info->destroy_notify (info->user_data);
2239 /* Notify about operation end */
2240 modest_mail_operation_notify_end (info->mail_op);
2244 g_object_unref (info->header);
2245 g_object_unref (info->mail_op);
2246 g_slice_free (GetMsgInfo, info);
2250 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2251 TnyList *header_list,
2252 GetMsgAsyncUserCallback user_callback,
2254 GDestroyNotify notify)
2256 ModestMailOperationPrivate *priv = NULL;
2257 gboolean size_ok = TRUE;
2259 TnyIterator *iter = NULL;
2261 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2263 /* Init mail operation */
2264 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2265 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2266 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2268 priv->total = tny_list_get_length(header_list);
2270 /* Get account and set it into mail_operation */
2271 if (tny_list_get_length (header_list) >= 1) {
2272 iter = tny_list_create_iterator (header_list);
2273 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2275 TnyFolder *folder = tny_header_get_folder (header);
2277 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2278 g_object_unref (folder);
2280 g_object_unref (header);
2283 if (tny_list_get_length (header_list) == 1) {
2284 g_object_unref (iter);
2289 /* Get msg size limit */
2290 max_size = modest_conf_get_int (modest_runtime_get_conf (),
2291 MODEST_CONF_MSG_SIZE_LIMIT,
2294 g_clear_error (&(priv->error));
2295 max_size = G_MAXINT;
2297 max_size = max_size * KB;
2300 /* Check message size limits. If there is only one message
2301 always retrieve it */
2303 while (!tny_iterator_is_done (iter) && size_ok) {
2304 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2306 if (tny_header_get_message_size (header) >= max_size)
2308 g_object_unref (header);
2311 tny_iterator_next (iter);
2313 g_object_unref (iter);
2317 const gint msg_list_size = compute_message_list_size (header_list);
2319 modest_mail_operation_notify_start (self);
2320 iter = tny_list_create_iterator (header_list);
2321 while (!tny_iterator_is_done (iter)) {
2322 /* notify about the start of the operation */
2323 ModestMailOperationState *state;
2324 state = modest_mail_operation_clone_state (self);
2327 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2330 GetMsgInfo *msg_info = NULL;
2331 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2332 TnyFolder *folder = tny_header_get_folder (header);
2334 /* Create the message info */
2335 msg_info = g_slice_new0 (GetMsgInfo);
2336 msg_info->mail_op = g_object_ref (self);
2337 msg_info->header = g_object_ref (header);
2338 msg_info->user_callback = user_callback;
2339 msg_info->user_data = user_data;
2340 msg_info->destroy_notify = notify;
2341 msg_info->last_total_bytes = 0;
2342 msg_info->sum_total_bytes = 0;
2343 msg_info->total_bytes = msg_list_size;
2345 /* The callback will call it per each header */
2346 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2348 /* Free and go on */
2349 g_object_unref (header);
2350 g_object_unref (folder);
2351 tny_iterator_next (iter);
2353 g_object_unref (iter);
2355 /* Set status failed and set an error */
2356 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2357 /* FIXME: the error msg is different for pop */
2358 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2359 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
2360 _("emev_ni_ui_imap_msg_size_exceed_error"));
2361 /* Remove from queue and free resources */
2362 modest_mail_operation_notify_end (self);
2370 modest_mail_operation_remove_msg (ModestMailOperation *self,
2372 gboolean remove_to_trash /*ignored*/)
2375 ModestMailOperationPrivate *priv;
2377 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2378 g_return_if_fail (TNY_IS_HEADER (header));
2380 if (remove_to_trash)
2381 g_warning ("remove to trash is not implemented");
2383 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2384 folder = tny_header_get_folder (header);
2386 /* Get account and set it into mail_operation */
2387 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2388 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2389 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2391 /* remove message from folder */
2392 tny_folder_remove_msg (folder, header, &(priv->error));
2394 gboolean expunge, leave_on_server;
2395 const gchar *account_name;
2396 TnyAccount *account;
2397 ModestTransportStoreProtocol account_proto;
2399 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2400 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2402 modest_mail_operation_notify_start (self);
2404 /* Get leave on server setting */
2405 account = tny_folder_get_account (folder);
2406 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2408 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2411 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2413 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2414 modest_tny_folder_is_remote_folder (folder) == FALSE)
2420 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2423 g_object_unref (account);
2429 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2431 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2434 g_object_unref (G_OBJECT (folder));
2436 /* Notify about operation end */
2437 modest_mail_operation_notify_end (self);
2441 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2443 gboolean remove_to_trash /*ignored*/)
2446 ModestMailOperationPrivate *priv;
2447 TnyIterator *iter = NULL;
2448 TnyHeader *header = NULL;
2449 TnyList *remove_headers = NULL;
2450 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2452 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2453 g_return_if_fail (TNY_IS_LIST (headers));
2455 if (remove_to_trash)
2456 g_warning ("remove to trash is not implemented");
2458 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2460 remove_headers = g_object_ref(headers);
2462 /* Get folder from first header and sync it */
2463 iter = tny_list_create_iterator (headers);
2464 header = TNY_HEADER (tny_iterator_get_current (iter));
2465 folder = tny_header_get_folder (header);
2467 /* Don't remove messages that are being sent */
2468 if (modest_tny_folder_is_local_folder (folder)) {
2469 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2471 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2472 TnyTransportAccount *traccount = NULL;
2473 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2474 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2476 ModestTnySendQueueStatus status;
2477 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2478 TnyIterator *iter = tny_list_create_iterator(headers);
2479 g_object_unref(remove_headers);
2480 remove_headers = TNY_LIST(tny_simple_list_new());
2481 while (!tny_iterator_is_done(iter)) {
2483 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2484 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2485 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2486 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2487 tny_list_append(remove_headers, G_OBJECT(hdr));
2489 g_object_unref(hdr);
2491 tny_iterator_next(iter);
2493 g_object_unref(iter);
2494 g_object_unref(traccount);
2498 /* Get account and set it into mail_operation */
2499 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2500 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2501 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2503 /* remove message from folder */
2504 modest_mail_operation_notify_start (self);
2506 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2508 gboolean expunge, leave_on_server;
2509 const gchar *account_name;
2510 TnyAccount *account;
2511 ModestTransportStoreProtocol account_proto;
2513 account = tny_folder_get_account (folder);
2514 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2516 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2519 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2521 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2522 modest_tny_folder_is_remote_folder (folder) == FALSE)
2528 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2530 g_object_unref (account);
2536 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2538 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2541 g_object_unref (remove_headers);
2542 g_object_unref (header);
2543 g_object_unref (iter);
2544 g_object_unref (G_OBJECT (folder));
2546 /* Notify about operation end */
2547 modest_mail_operation_notify_end (self);
2551 notify_progress_of_multiple_messages (ModestMailOperation *self,
2553 gint *last_total_bytes,
2554 gint *sum_total_bytes,
2556 gboolean increment_done)
2558 ModestMailOperationPrivate *priv;
2559 ModestMailOperationState *state;
2560 gboolean is_num_bytes;
2562 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2564 /* We know that tinymail sends us information about
2565 transferred bytes with this particular message */
2566 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2568 state = modest_mail_operation_clone_state (self);
2569 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2570 /* We know that we're in a different message when the
2571 total number of bytes to transfer is different. Of
2572 course it could fail if we're transferring messages
2573 of the same size, but this is a workarround */
2574 if (status->of_total != *last_total_bytes) {
2575 /* We need to increment the done when there is
2576 no information about each individual
2577 message, we need to do this in message
2578 transfers, and we don't do it for getting
2582 *sum_total_bytes += *last_total_bytes;
2583 *last_total_bytes = status->of_total;
2585 state->bytes_done += status->position + *sum_total_bytes;
2586 state->bytes_total = total_bytes;
2588 /* Notify the status change. Only notify about changes
2589 referred to bytes */
2590 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2594 g_slice_free (ModestMailOperationState, state);
2598 transfer_msgs_status_cb (GObject *obj,
2602 XFerMsgAsyncHelper *helper;
2604 g_return_if_fail (status != NULL);
2605 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2607 helper = (XFerMsgAsyncHelper *) user_data;
2608 g_return_if_fail (helper != NULL);
2610 /* Notify progress */
2611 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2612 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2617 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2619 XFerMsgAsyncHelper *helper;
2620 ModestMailOperation *self;
2621 ModestMailOperationPrivate *priv;
2622 TnyIterator *iter = NULL;
2623 TnyHeader *header = NULL;
2625 helper = (XFerMsgAsyncHelper *) user_data;
2626 self = helper->mail_op;
2628 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2631 priv->error = g_error_copy (err);
2633 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2634 } else if (cancelled) {
2635 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2636 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2637 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2638 _("Error trying to refresh the contents of %s"),
2639 tny_folder_get_name (folder));
2642 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2644 /* Update folder counts */
2645 tny_folder_poke_status (folder);
2646 tny_folder_poke_status (helper->dest_folder);
2650 /* Mark headers as deleted and seen */
2651 if ((helper->delete) &&
2652 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2653 iter = tny_list_create_iterator (helper->headers);
2654 while (!tny_iterator_is_done (iter)) {
2655 header = TNY_HEADER (tny_iterator_get_current (iter));
2656 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2657 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2658 g_object_unref (header);
2660 tny_iterator_next (iter);
2666 /* Notify about operation end */
2667 modest_mail_operation_notify_end (self);
2669 /* If user defined callback function was defined, call it */
2670 if (helper->user_callback) {
2671 /* This is not a GDK lock because we are a Tinymail callback and
2672 * Tinymail already acquires the Gdk lock */
2674 /* no gdk_threads_enter (), CHECKED */
2675 helper->user_callback (self, helper->user_data);
2676 /* no gdk_threads_leave (), CHECKED */
2680 if (helper->headers)
2681 g_object_unref (helper->headers);
2682 if (helper->dest_folder)
2683 g_object_unref (helper->dest_folder);
2684 if (helper->mail_op)
2685 g_object_unref (helper->mail_op);
2687 g_object_unref (folder);
2689 g_object_unref (iter);
2690 g_slice_free (XFerMsgAsyncHelper, helper);
2694 compute_message_list_size (TnyList *headers)
2699 iter = tny_list_create_iterator (headers);
2700 while (!tny_iterator_is_done (iter)) {
2701 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2702 size += tny_header_get_message_size (header);
2703 g_object_unref (header);
2704 tny_iterator_next (iter);
2706 g_object_unref (iter);
2712 compute_message_array_size (GPtrArray *headers)
2717 for (i = 0; i < headers->len; i++) {
2718 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2719 size += tny_header_get_message_size (header);
2727 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2730 gboolean delete_original,
2731 XferAsyncUserCallback user_callback,
2734 ModestMailOperationPrivate *priv = NULL;
2735 TnyIterator *iter = NULL;
2736 TnyFolder *src_folder = NULL;
2737 XFerMsgAsyncHelper *helper = NULL;
2738 TnyHeader *header = NULL;
2739 ModestTnyFolderRules rules = 0;
2741 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2742 g_return_if_fail (headers && TNY_IS_LIST (headers));
2743 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2745 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2746 priv->total = tny_list_get_length (headers);
2748 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2749 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2751 /* Apply folder rules */
2752 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2753 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2754 /* Set status failed and set an error */
2755 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2756 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2757 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2758 _CS("ckct_ib_unable_to_paste_here"));
2759 /* Notify the queue */
2760 modest_mail_operation_notify_end (self);
2764 /* Get source folder */
2765 iter = tny_list_create_iterator (headers);
2766 header = TNY_HEADER (tny_iterator_get_current (iter));
2768 src_folder = tny_header_get_folder (header);
2769 g_object_unref (header);
2771 g_object_unref (iter);
2773 if (src_folder == NULL) {
2774 /* Notify the queue */
2775 modest_mail_operation_notify_end (self);
2777 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2782 /* Check folder source and destination */
2783 if (src_folder == folder) {
2784 /* Set status failed and set an error */
2785 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2786 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2787 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2788 _("mail_in_ui_folder_copy_target_error"));
2790 /* Notify the queue */
2791 modest_mail_operation_notify_end (self);
2794 g_object_unref (src_folder);
2798 /* Create the helper */
2799 helper = g_slice_new0 (XFerMsgAsyncHelper);
2800 helper->mail_op = g_object_ref(self);
2801 helper->dest_folder = g_object_ref(folder);
2802 helper->headers = g_object_ref(headers);
2803 helper->user_callback = user_callback;
2804 helper->user_data = user_data;
2805 helper->delete = delete_original;
2806 helper->last_total_bytes = 0;
2807 helper->sum_total_bytes = 0;
2808 helper->total_bytes = compute_message_list_size (headers);
2810 /* Get account and set it into mail_operation */
2811 priv->account = modest_tny_folder_get_account (src_folder);
2813 /* Transfer messages */
2814 modest_mail_operation_notify_start (self);
2815 tny_folder_transfer_msgs_async (src_folder,
2820 transfer_msgs_status_cb,
2826 on_refresh_folder (TnyFolder *folder,
2831 RefreshAsyncHelper *helper = NULL;
2832 ModestMailOperation *self = NULL;
2833 ModestMailOperationPrivate *priv = NULL;
2835 helper = (RefreshAsyncHelper *) user_data;
2836 self = helper->mail_op;
2837 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2839 g_return_if_fail(priv!=NULL);
2842 priv->error = g_error_copy (error);
2843 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2848 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2849 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2850 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2851 _("Error trying to refresh the contents of %s"),
2852 tny_folder_get_name (folder));
2856 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2859 /* Call user defined callback, if it exists */
2860 if (helper->user_callback) {
2862 /* This is not a GDK lock because we are a Tinymail callback and
2863 * Tinymail already acquires the Gdk lock */
2864 helper->user_callback (self, folder, helper->user_data);
2868 g_slice_free (RefreshAsyncHelper, helper);
2870 /* Notify about operation end */
2871 modest_mail_operation_notify_end (self);
2872 g_object_unref(self);
2876 on_refresh_folder_status_update (GObject *obj,
2880 RefreshAsyncHelper *helper = NULL;
2881 ModestMailOperation *self = NULL;
2882 ModestMailOperationPrivate *priv = NULL;
2883 ModestMailOperationState *state;
2885 g_return_if_fail (user_data != NULL);
2886 g_return_if_fail (status != NULL);
2887 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2889 helper = (RefreshAsyncHelper *) user_data;
2890 self = helper->mail_op;
2891 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2893 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2895 priv->done = status->position;
2896 priv->total = status->of_total;
2898 state = modest_mail_operation_clone_state (self);
2900 /* This is not a GDK lock because we are a Tinymail callback and
2901 * Tinymail already acquires the Gdk lock */
2902 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2904 g_slice_free (ModestMailOperationState, state);
2908 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2910 RefreshAsyncUserCallback user_callback,
2913 ModestMailOperationPrivate *priv = NULL;
2914 RefreshAsyncHelper *helper = NULL;
2916 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2918 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2920 /* Get account and set it into mail_operation */
2921 priv->account = modest_tny_folder_get_account (folder);
2922 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2924 /* Create the helper */
2925 helper = g_slice_new0 (RefreshAsyncHelper);
2926 helper->mail_op = g_object_ref(self);
2927 helper->user_callback = user_callback;
2928 helper->user_data = user_data;
2930 /* Refresh the folder. TODO: tinymail could issue a status
2931 updates before the callback call then this could happen. We
2932 must review the design */
2933 modest_mail_operation_notify_start (self);
2935 /* notify that the operation was started */
2936 ModestMailOperationState *state;
2937 state = modest_mail_operation_clone_state (self);
2940 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2943 tny_folder_refresh_async (folder,
2945 on_refresh_folder_status_update,
2951 modest_mail_operation_notify_start (ModestMailOperation *self)
2953 ModestMailOperationPrivate *priv = NULL;
2955 g_return_if_fail (self);
2957 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2959 /* Ensure that all the fields are filled correctly */
2960 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2962 /* Notify the observers about the mail operation. We do not
2963 wrapp this emission because we assume that this function is
2964 always called from within the main lock */
2965 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2970 * It's used by the mail operation queue to notify the observers
2971 * attached to that signal that the operation finished. We need to use
2972 * that because tinymail does not give us the progress of a given
2973 * operation when it finishes (it directly calls the operation
2977 modest_mail_operation_notify_end (ModestMailOperation *self)
2979 ModestMailOperationPrivate *priv = NULL;
2981 g_return_if_fail (self);
2983 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2985 /* Notify the observers about the mail operation end. We do
2986 not wrapp this emission because we assume that this
2987 function is always called from within the main lock */
2988 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2990 /* Remove the error user data */
2991 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2992 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2996 modest_mail_operation_get_account (ModestMailOperation *self)
2998 ModestMailOperationPrivate *priv = NULL;
3000 g_return_val_if_fail (self, NULL);
3002 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3004 return (priv->account) ? g_object_ref (priv->account) : NULL;
3008 modest_mail_operation_noop (ModestMailOperation *self)
3010 ModestMailOperationPrivate *priv = NULL;
3012 g_return_if_fail (self);
3014 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3015 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3016 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3020 /* This mail operation does nothing actually */
3021 modest_mail_operation_notify_start (self);
3022 modest_mail_operation_notify_end (self);