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 _XFerMsgsAsyncHelper
165 ModestMailOperation *mail_op;
167 TnyFolder *dest_folder;
168 XferMsgsAsyncUserCallback user_callback;
171 gint last_total_bytes;
172 gint sum_total_bytes;
174 } XFerMsgsAsyncHelper;
176 typedef struct _XFerFolderAsyncHelper
178 ModestMailOperation *mail_op;
179 XferFolderAsyncUserCallback user_callback;
181 } XFerFolderAsyncHelper;
183 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
187 static void modest_mail_operation_create_msg (ModestMailOperation *self,
188 const gchar *from, const gchar *to,
189 const gchar *cc, const gchar *bcc,
190 const gchar *subject, const gchar *plain_body,
191 const gchar *html_body, const GList *attachments_list,
192 const GList *images_list,
193 TnyHeaderFlags priority_flags,
194 ModestMailOperationCreateMsgCallback callback,
197 static gboolean idle_notify_queue (gpointer data);
200 ModestMailOperation *mail_op;
208 GList *attachments_list;
210 TnyHeaderFlags priority_flags;
211 ModestMailOperationCreateMsgCallback callback;
217 ModestMailOperation *mail_op;
219 ModestMailOperationCreateMsgCallback callback;
224 static GObjectClass *parent_class = NULL;
226 static guint signals[NUM_SIGNALS] = {0};
229 modest_mail_operation_get_type (void)
231 static GType my_type = 0;
233 static const GTypeInfo my_info = {
234 sizeof(ModestMailOperationClass),
235 NULL, /* base init */
236 NULL, /* base finalize */
237 (GClassInitFunc) modest_mail_operation_class_init,
238 NULL, /* class finalize */
239 NULL, /* class data */
240 sizeof(ModestMailOperation),
242 (GInstanceInitFunc) modest_mail_operation_init,
245 my_type = g_type_register_static (G_TYPE_OBJECT,
246 "ModestMailOperation",
253 modest_mail_operation_class_init (ModestMailOperationClass *klass)
255 GObjectClass *gobject_class;
256 gobject_class = (GObjectClass*) klass;
258 parent_class = g_type_class_peek_parent (klass);
259 gobject_class->finalize = modest_mail_operation_finalize;
261 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
264 * ModestMailOperation::progress-changed
265 * @self: the #MailOperation that emits the signal
266 * @user_data: user data set when the signal handler was connected
268 * Emitted when the progress of a mail operation changes
270 signals[PROGRESS_CHANGED_SIGNAL] =
271 g_signal_new ("progress-changed",
272 G_TYPE_FROM_CLASS (gobject_class),
274 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
276 g_cclosure_marshal_VOID__POINTER,
277 G_TYPE_NONE, 1, G_TYPE_POINTER);
281 * This signal is issued whenever a mail operation starts, and
282 * starts mean when the tinymail operation is issued. This
283 * means that it could happen that something wrong happens and
284 * the tinymail function is never called. In this situation a
285 * operation-finished will be issued without any
288 signals[OPERATION_STARTED_SIGNAL] =
289 g_signal_new ("operation-started",
290 G_TYPE_FROM_CLASS (gobject_class),
292 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
294 g_cclosure_marshal_VOID__VOID,
299 * This signal is issued whenever a mail operation
300 * finishes. Note that this signal could be issued without any
301 * previous "operation-started" signal, because this last one
302 * is only issued when the tinymail operation is successfully
305 signals[OPERATION_FINISHED_SIGNAL] =
306 g_signal_new ("operation-finished",
307 G_TYPE_FROM_CLASS (gobject_class),
309 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
311 g_cclosure_marshal_VOID__VOID,
316 modest_mail_operation_init (ModestMailOperation *obj)
318 ModestMailOperationPrivate *priv;
320 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
322 priv->account = NULL;
323 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
324 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
329 priv->error_checking = NULL;
330 priv->error_checking_user_data = NULL;
334 modest_mail_operation_finalize (GObject *obj)
336 ModestMailOperationPrivate *priv;
338 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
343 g_error_free (priv->error);
347 g_object_unref (priv->source);
351 g_object_unref (priv->account);
352 priv->account = NULL;
356 G_OBJECT_CLASS(parent_class)->finalize (obj);
360 modest_mail_operation_new (GObject *source)
362 ModestMailOperation *obj;
363 ModestMailOperationPrivate *priv;
365 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
366 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
369 priv->source = g_object_ref(source);
375 modest_mail_operation_new_with_error_handling (GObject *source,
376 ErrorCheckingUserCallback error_handler,
378 ErrorCheckingUserDataDestroyer error_handler_destroyer)
380 ModestMailOperation *obj;
381 ModestMailOperationPrivate *priv;
383 obj = modest_mail_operation_new (source);
384 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
386 g_return_val_if_fail (error_handler != NULL, obj);
387 priv->error_checking = error_handler;
388 priv->error_checking_user_data = user_data;
389 priv->error_checking_user_data_destroyer = error_handler_destroyer;
395 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
397 ModestMailOperationPrivate *priv;
399 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
401 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
402 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
404 /* Call the user callback */
405 if (priv->error_checking != NULL)
406 priv->error_checking (self, priv->error_checking_user_data);
410 ModestMailOperationTypeOperation
411 modest_mail_operation_get_type_operation (ModestMailOperation *self)
413 ModestMailOperationPrivate *priv;
415 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
416 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
418 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
420 return priv->op_type;
424 modest_mail_operation_is_mine (ModestMailOperation *self,
427 ModestMailOperationPrivate *priv;
429 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
432 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
433 if (priv->source == NULL) return FALSE;
435 return priv->source == me;
439 modest_mail_operation_get_source (ModestMailOperation *self)
441 ModestMailOperationPrivate *priv;
443 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
446 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
448 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
452 return (priv->source) ? g_object_ref (priv->source) : NULL;
455 ModestMailOperationStatus
456 modest_mail_operation_get_status (ModestMailOperation *self)
458 ModestMailOperationPrivate *priv;
460 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
461 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
462 MODEST_MAIL_OPERATION_STATUS_INVALID);
464 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
466 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
467 return MODEST_MAIL_OPERATION_STATUS_INVALID;
474 modest_mail_operation_get_error (ModestMailOperation *self)
476 ModestMailOperationPrivate *priv;
478 g_return_val_if_fail (self, NULL);
479 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
481 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
484 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
492 modest_mail_operation_cancel (ModestMailOperation *self)
494 ModestMailOperationPrivate *priv;
495 gboolean canceled = FALSE;
497 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
499 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
501 /* Note that if we call cancel with an already canceled mail
502 operation the progress changed signal won't be emitted */
503 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
507 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
509 /* Cancel the mail operation. We need to wrap it between this
510 start/stop operations to allow following calls to the
512 g_return_val_if_fail (priv->account, FALSE);
514 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
515 ModestTnySendQueue *queue;
516 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
517 /* Cancel sending without removing the item */
518 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), FALSE, NULL);
520 /* Cancel operation */
521 tny_account_cancel (priv->account);
528 modest_mail_operation_get_task_done (ModestMailOperation *self)
530 ModestMailOperationPrivate *priv;
532 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
535 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
540 modest_mail_operation_get_task_total (ModestMailOperation *self)
542 ModestMailOperationPrivate *priv;
544 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
547 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
552 modest_mail_operation_is_finished (ModestMailOperation *self)
554 ModestMailOperationPrivate *priv;
555 gboolean retval = FALSE;
557 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
560 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
562 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
563 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
564 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
565 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
575 * Creates an image of the current state of a mail operation, the
576 * caller must free it
578 static ModestMailOperationState *
579 modest_mail_operation_clone_state (ModestMailOperation *self)
581 ModestMailOperationState *state;
582 ModestMailOperationPrivate *priv;
584 /* FIXME: this should be fixed properly
586 * in some cases, priv was NULL, so checking here to
589 g_return_val_if_fail (self, NULL);
590 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
591 g_return_val_if_fail (priv, NULL);
596 state = g_slice_new (ModestMailOperationState);
598 state->status = priv->status;
599 state->op_type = priv->op_type;
600 state->done = priv->done;
601 state->total = priv->total;
602 state->finished = modest_mail_operation_is_finished (self);
603 state->bytes_done = 0;
604 state->bytes_total = 0;
609 /* ******************************************************************* */
610 /* ************************** SEND ACTIONS ************************* */
611 /* ******************************************************************* */
614 modest_mail_operation_send_mail (ModestMailOperation *self,
615 TnyTransportAccount *transport_account,
618 TnySendQueue *send_queue = NULL;
619 ModestMailOperationPrivate *priv;
622 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
623 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
624 g_return_if_fail (msg && TNY_IS_MSG (msg));
626 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
628 /* Get account and set it into mail_operation */
629 priv->account = g_object_ref (transport_account);
630 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
634 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
635 if (!TNY_IS_SEND_QUEUE(send_queue)) {
636 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
637 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
638 "modest: could not find send queue for account\n");
639 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
640 modest_mail_operation_notify_end (self);
643 /* Add the msg to the queue */
644 modest_mail_operation_notify_start (self);
646 info = g_slice_new0 (SendMsgInfo);
648 info->mail_op = g_object_ref (self);
649 info->msg = g_object_ref (msg);
650 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
651 G_CALLBACK (send_mail_msg_sent_handler), info);
652 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
653 G_CALLBACK (send_mail_error_happened_handler), info);
655 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
659 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
665 common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
668 g_signal_handler_disconnect (queue, info->msg_sent_handler);
669 g_signal_handler_disconnect (queue, info->error_happened_handler);
671 g_object_unref (info->msg);
672 modest_mail_operation_notify_end (info->mail_op);
673 g_object_unref (info->mail_op);
675 g_slice_free (SendMsgInfo, info);
679 send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
680 guint nth, guint total, gpointer userdata)
682 SendMsgInfo *info = (SendMsgInfo *) userdata;
683 TnyHeader *hdr1, *hdr2;
684 const char *msgid1, *msgid2;
685 hdr1 = tny_msg_get_header(msg);
686 hdr2 = tny_msg_get_header(info->msg);
687 msgid1 = tny_header_get_message_id(hdr1);
688 msgid2 = tny_header_get_message_id(hdr2);
689 if (msgid1 == NULL) msgid1 = "(null)";
690 if (msgid2 == NULL) msgid2 = "(null)";
692 if (!strcmp (msgid1, msgid2)) {
693 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
694 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
696 common_send_mail_operation_end (queue, msg, info);
698 g_object_unref(G_OBJECT(hdr1));
699 g_object_unref(G_OBJECT(hdr2));
703 send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
704 GError *error, gpointer userdata)
706 SendMsgInfo *info = (SendMsgInfo *) userdata;
707 TnyHeader *hdr1, *hdr2;
708 const char *msgid1, *msgid2;
710 hdr1 = tny_msg_get_header(msg);
711 hdr2 = tny_msg_get_header(info->msg);
712 msgid1 = tny_header_get_message_id(hdr1);
713 msgid2 = tny_header_get_message_id(hdr2);
714 if (msgid1 == NULL) msgid1 = "(null)";
715 if (msgid2 == NULL) msgid2 = "(null)";
717 if (!strcmp (msgid1, msgid2)) {
719 g_warning ("%s: %s\n", __FUNCTION__, error->message);
720 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
721 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
722 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
723 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
724 "modest: send mail failed\n");
726 common_send_mail_operation_end (queue, msg, info);
728 g_object_unref(G_OBJECT(hdr1));
729 g_object_unref(G_OBJECT(hdr2));
734 idle_create_msg_cb (gpointer idle_data)
736 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
738 /* This is a GDK lock because we are an idle callback and
739 * info->callback can contain Gtk+ code */
741 gdk_threads_enter (); /* CHECKED */
742 info->callback (info->mail_op, info->msg, info->userdata);
744 g_object_unref (info->mail_op);
746 g_object_unref (info->msg);
747 g_slice_free (CreateMsgIdleInfo, info);
748 gdk_threads_leave (); /* CHECKED */
754 create_msg_thread (gpointer thread_data)
756 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
757 TnyMsg *new_msg = NULL;
758 ModestMailOperationPrivate *priv;
760 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
761 if (info->html_body == NULL) {
762 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
763 info->bcc, info->subject, info->plain_body,
764 info->attachments_list);
766 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
767 info->bcc, info->subject, info->html_body,
768 info->plain_body, info->attachments_list,
775 /* Set priority flags in message */
776 header = tny_msg_get_header (new_msg);
777 tny_header_set_flag (header, info->priority_flags);
779 /* Set attachment flags in message */
780 if (info->attachments_list != NULL)
781 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
783 g_object_unref (G_OBJECT(header));
785 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
786 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
787 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
788 "modest: failed to create a new msg\n");
796 g_free (info->plain_body);
797 g_free (info->html_body);
798 g_free (info->subject);
799 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
800 g_list_free (info->attachments_list);
801 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
802 g_list_free (info->images_list);
804 if (info->callback) {
805 CreateMsgIdleInfo *idle_info;
806 idle_info = g_slice_new0 (CreateMsgIdleInfo);
807 idle_info->mail_op = g_object_ref (info->mail_op);
808 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
809 idle_info->callback = info->callback;
810 idle_info->userdata = info->userdata;
811 g_idle_add (idle_create_msg_cb, idle_info);
813 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
816 g_object_unref (info->mail_op);
817 g_slice_free (CreateMsgInfo, info);
818 if (new_msg) g_object_unref(new_msg);
823 modest_mail_operation_create_msg (ModestMailOperation *self,
824 const gchar *from, const gchar *to,
825 const gchar *cc, const gchar *bcc,
826 const gchar *subject, const gchar *plain_body,
827 const gchar *html_body,
828 const GList *attachments_list,
829 const GList *images_list,
830 TnyHeaderFlags priority_flags,
831 ModestMailOperationCreateMsgCallback callback,
834 CreateMsgInfo *info = NULL;
836 info = g_slice_new0 (CreateMsgInfo);
837 info->mail_op = g_object_ref (self);
839 info->from = g_strdup (from);
840 info->to = g_strdup (to);
841 info->cc = g_strdup (cc);
842 info->bcc = g_strdup (bcc);
843 info->subject = g_strdup (subject);
844 info->plain_body = g_strdup (plain_body);
845 info->html_body = g_strdup (html_body);
846 info->attachments_list = g_list_copy ((GList *) attachments_list);
847 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
848 info->images_list = g_list_copy ((GList *) images_list);
849 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
850 info->priority_flags = priority_flags;
852 info->callback = callback;
853 info->userdata = userdata;
855 g_thread_create (create_msg_thread, info, FALSE, NULL);
860 TnyTransportAccount *transport_account;
865 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
869 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
870 TnyFolder *draft_folder = NULL;
871 TnyFolder *outbox_folder = NULL;
879 /* Call mail operation */
880 modest_mail_operation_send_mail (self, info->transport_account, msg);
882 /* Remove old mail from its source folder */
883 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
884 TNY_FOLDER_TYPE_DRAFTS);
886 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder", __FUNCTION__);
889 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
890 TNY_FOLDER_TYPE_OUTBOX);
891 if (!outbox_folder) {
892 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder", __FUNCTION__);
895 if (info->draft_msg != NULL) {
896 TnyFolder *folder = NULL;
897 TnyFolder *src_folder = NULL;
898 TnyFolderType folder_type;
899 folder = tny_msg_get_folder (info->draft_msg);
900 if (folder == NULL) goto end;
901 folder_type = modest_tny_folder_guess_folder_type (folder);
903 if (folder_type == TNY_FOLDER_TYPE_INVALID)
904 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
906 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
907 src_folder = outbox_folder;
909 src_folder = draft_folder;
911 /* Note: This can fail (with a warning) if the message is not really already in a folder,
912 * because this function requires it to have a UID. */
913 header = tny_msg_get_header (info->draft_msg);
914 tny_folder_remove_msg (src_folder, header, NULL);
916 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
917 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
919 g_object_unref (header);
920 g_object_unref (folder);
927 g_object_unref (info->draft_msg);
929 g_object_unref (draft_folder);
931 g_object_unref (outbox_folder);
932 if (info->transport_account)
933 g_object_unref (info->transport_account);
934 g_slice_free (SendNewMailInfo, info);
938 modest_mail_operation_send_new_mail (ModestMailOperation *self,
939 TnyTransportAccount *transport_account,
941 const gchar *from, const gchar *to,
942 const gchar *cc, const gchar *bcc,
943 const gchar *subject, const gchar *plain_body,
944 const gchar *html_body,
945 const GList *attachments_list,
946 const GList *images_list,
947 TnyHeaderFlags priority_flags)
949 ModestMailOperationPrivate *priv = NULL;
950 SendNewMailInfo *info;
952 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
953 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
955 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
956 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
957 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
958 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
960 /* Check parametters */
962 /* Set status failed and set an error */
963 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
964 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
965 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
966 _("Error trying to send a mail. You need to set at least one recipient"));
969 info = g_slice_new0 (SendNewMailInfo);
970 info->transport_account = transport_account;
971 if (transport_account)
972 g_object_ref (transport_account);
973 info->draft_msg = draft_msg;
975 g_object_ref (draft_msg);
978 modest_mail_operation_notify_start (self);
979 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
980 attachments_list, images_list, priority_flags,
981 modest_mail_operation_send_new_mail_cb, info);
987 TnyTransportAccount *transport_account;
989 SaveToDraftstCallback callback;
993 ModestMailOperation *mailop;
994 } SaveToDraftsAddMsgInfo;
997 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1002 ModestMailOperationPrivate *priv = NULL;
1003 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1005 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1008 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1009 g_error_free(priv->error);
1012 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1014 if ((!priv->error) && (info->draft_msg != NULL)) {
1015 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1016 TnyFolder *src_folder = tny_header_get_folder (header);
1018 /* Remove the old draft */
1019 tny_folder_remove_msg (src_folder, header, NULL);
1021 /* Synchronize to expunge and to update the msg counts */
1022 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1023 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1025 g_object_unref (G_OBJECT(header));
1026 g_object_unref (G_OBJECT(src_folder));
1030 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1032 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1034 /* Call the user callback */
1036 info->callback (info->mailop, info->msg, info->user_data);
1038 if (info->transport_account)
1039 g_object_unref (G_OBJECT(info->transport_account));
1040 if (info->draft_msg)
1041 g_object_unref (G_OBJECT (info->draft_msg));
1043 g_object_unref (G_OBJECT(info->drafts));
1045 g_object_unref (G_OBJECT (info->msg));
1047 modest_mail_operation_notify_end (info->mailop);
1048 g_object_unref(info->mailop);
1049 g_slice_free (SaveToDraftsAddMsgInfo, info);
1054 TnyTransportAccount *transport_account;
1056 SaveToDraftstCallback callback;
1061 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1065 TnyFolder *drafts = NULL;
1066 ModestMailOperationPrivate *priv = NULL;
1067 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1069 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1072 if (!(priv->error)) {
1073 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1074 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1075 "modest: failed to create a new msg\n");
1078 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1079 TNY_FOLDER_TYPE_DRAFTS);
1080 if (!drafts && !(priv->error)) {
1081 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1082 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1083 "modest: failed to create a new msg\n");
1088 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1089 cb_info->transport_account = g_object_ref(info->transport_account);
1090 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1091 cb_info->callback = info->callback;
1092 cb_info->user_data = info->user_data;
1093 cb_info->drafts = g_object_ref(drafts);
1094 cb_info->msg = g_object_ref(msg);
1095 cb_info->mailop = g_object_ref(self);
1096 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1099 /* Call the user callback */
1100 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1102 info->callback (self, msg, info->user_data);
1103 modest_mail_operation_notify_end (self);
1107 g_object_unref (G_OBJECT(drafts));
1108 if (info->draft_msg)
1109 g_object_unref (G_OBJECT (info->draft_msg));
1110 if (info->transport_account)
1111 g_object_unref (G_OBJECT(info->transport_account));
1112 g_slice_free (SaveToDraftsInfo, info);
1116 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1117 TnyTransportAccount *transport_account,
1119 const gchar *from, const gchar *to,
1120 const gchar *cc, const gchar *bcc,
1121 const gchar *subject, const gchar *plain_body,
1122 const gchar *html_body,
1123 const GList *attachments_list,
1124 const GList *images_list,
1125 TnyHeaderFlags priority_flags,
1126 SaveToDraftstCallback callback,
1129 ModestMailOperationPrivate *priv = NULL;
1130 SaveToDraftsInfo *info = NULL;
1132 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1133 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1135 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1137 /* Get account and set it into mail_operation */
1138 priv->account = g_object_ref (transport_account);
1139 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1141 info = g_slice_new0 (SaveToDraftsInfo);
1142 info->transport_account = g_object_ref (transport_account);
1143 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1144 info->callback = callback;
1145 info->user_data = user_data;
1147 modest_mail_operation_notify_start (self);
1148 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1149 attachments_list, images_list, priority_flags,
1150 modest_mail_operation_save_to_drafts_cb, info);
1155 ModestMailOperation *mail_op;
1156 TnyMimePart *mime_part;
1158 GetMimePartSizeCallback callback;
1160 } GetMimePartSizeInfo;
1162 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1163 /* We use this folder observer to track the headers that have been
1164 * added to a folder */
1167 TnyList *new_headers;
1168 } InternalFolderObserver;
1171 GObjectClass parent;
1172 } InternalFolderObserverClass;
1174 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1176 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1177 internal_folder_observer,
1179 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1183 foreach_add_item (gpointer header, gpointer user_data)
1185 tny_list_prepend (TNY_LIST (user_data),
1186 g_object_ref (G_OBJECT (header)));
1189 /* This is the method that looks for new messages in a folder */
1191 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1193 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1195 TnyFolderChangeChanged changed;
1197 changed = tny_folder_change_get_changed (change);
1199 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1202 /* Get added headers */
1203 list = tny_simple_list_new ();
1204 tny_folder_change_get_added_headers (change, list);
1206 /* Add them to the folder observer */
1207 tny_list_foreach (list, foreach_add_item,
1208 derived->new_headers);
1210 g_object_unref (G_OBJECT (list));
1215 internal_folder_observer_init (InternalFolderObserver *self)
1217 self->new_headers = tny_simple_list_new ();
1220 internal_folder_observer_finalize (GObject *object)
1222 InternalFolderObserver *self;
1224 self = (InternalFolderObserver *) object;
1225 g_object_unref (self->new_headers);
1227 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1230 tny_folder_observer_init (TnyFolderObserverIface *iface)
1232 iface->update_func = internal_folder_observer_update;
1235 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1237 GObjectClass *object_class;
1239 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1240 object_class = (GObjectClass*) klass;
1241 object_class->finalize = internal_folder_observer_finalize;
1246 ModestMailOperation *mail_op;
1247 gchar *account_name;
1248 UpdateAccountCallback callback;
1253 TnyFolderObserver *inbox_observer;
1254 RetrieveAllCallback retrieve_all_cb;
1255 } UpdateAccountInfo;
1259 destroy_update_account_info (UpdateAccountInfo *info)
1261 g_free (info->account_name);
1262 g_object_unref (info->folders);
1263 g_object_unref (info->mail_op);
1264 g_slice_free (UpdateAccountInfo, info);
1268 update_account_get_msg_async_cb (TnyFolder *folder,
1274 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1276 /* Just delete the helper. Don't do anything with the new
1277 msg. There is also no need to check for errors */
1278 g_object_unref (msg_info->mail_op);
1279 g_object_unref (msg_info->header);
1280 g_slice_free (GetMsgInfo, msg_info);
1285 inbox_refreshed_cb (TnyFolder *inbox,
1290 UpdateAccountInfo *info;
1291 ModestMailOperationPrivate *priv;
1292 TnyIterator *new_headers_iter;
1293 GPtrArray *new_headers_array = NULL;
1294 gint max_size, retrieve_limit, i;
1295 ModestAccountMgr *mgr;
1296 ModestAccountRetrieveType retrieve_type;
1297 TnyList *new_headers = NULL;
1298 gboolean headers_only, ignore_limit;
1299 TnyTransportAccount *transport_account;
1300 ModestTnySendQueue *send_queue;
1302 info = (UpdateAccountInfo *) user_data;
1303 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1304 mgr = modest_runtime_get_account_mgr ();
1306 if (canceled || err || !inbox) {
1307 /* Try to send anyway */
1311 /* Get the message max size */
1312 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1313 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1315 max_size = G_MAXINT;
1317 max_size = max_size * KB;
1319 /* Create the new headers array. We need it to sort the
1320 new headers by date */
1321 new_headers_array = g_ptr_array_new ();
1322 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1323 while (!tny_iterator_is_done (new_headers_iter)) {
1324 TnyHeader *header = NULL;
1326 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1327 /* Apply per-message size limits */
1328 if (tny_header_get_message_size (header) < max_size)
1329 g_ptr_array_add (new_headers_array, g_object_ref (header));
1331 g_object_unref (header);
1332 tny_iterator_next (new_headers_iter);
1334 g_object_unref (new_headers_iter);
1335 tny_folder_remove_observer (inbox, info->inbox_observer);
1336 g_object_unref (info->inbox_observer);
1337 info->inbox_observer = NULL;
1339 /* Update the last updated key, even if we don't have to get new headers */
1340 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1342 if (new_headers_array->len == 0)
1345 /* Get per-account message amount retrieval limit */
1346 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1347 if (retrieve_limit == 0)
1348 retrieve_limit = G_MAXINT;
1350 /* Get per-account retrieval type */
1351 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1352 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1355 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1357 /* Ask the users if they want to retrieve all the messages
1358 even though the limit was exceeded */
1359 ignore_limit = FALSE;
1360 if (new_headers_array->len > retrieve_limit) {
1361 /* Ask the user if a callback has been specified and
1362 if the mail operation has a source (this means that
1363 was invoked by the user and not automatically by a
1365 if (info->retrieve_all_cb && priv->source)
1366 ignore_limit = info->retrieve_all_cb (priv->source,
1367 new_headers_array->len,
1371 if (!headers_only) {
1373 const gint msg_list_size = compute_message_array_size (new_headers_array);
1377 priv->total = new_headers_array->len;
1379 priv->total = MIN (new_headers_array->len, retrieve_limit);
1380 while (msg_num < priv->total) {
1381 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1382 TnyFolder *folder = tny_header_get_folder (header);
1383 GetMsgInfo *msg_info;
1385 /* Create the message info */
1386 msg_info = g_slice_new0 (GetMsgInfo);
1387 msg_info->mail_op = g_object_ref (info->mail_op);
1388 msg_info->header = g_object_ref (header);
1389 msg_info->total_bytes = msg_list_size;
1391 /* Get message in an async way */
1392 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1393 get_msg_status_cb, msg_info);
1395 g_object_unref (folder);
1401 /* Copy the headers to a list and free the array */
1402 new_headers = tny_simple_list_new ();
1403 for (i=0; i < new_headers_array->len; i++) {
1404 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1405 tny_list_append (new_headers, G_OBJECT (header));
1407 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1408 g_ptr_array_free (new_headers_array, FALSE);
1415 /* Get the transport account */
1416 transport_account = (TnyTransportAccount *)
1417 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1418 info->account_name);
1421 send_queue = modest_runtime_get_send_queue (transport_account);
1422 modest_tny_send_queue_try_to_send (send_queue);
1424 /* Check if the operation was a success */
1426 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1428 /* Set the account back to not busy */
1429 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1431 /* Call the user callback */
1433 info->callback (info->mail_op, new_headers, info->user_data);
1435 /* Notify about operation end */
1436 modest_mail_operation_notify_end (info->mail_op);
1440 g_object_unref (new_headers);
1441 destroy_update_account_info (info);
1445 recurse_folders_async_cb (TnyFolderStore *folder_store,
1451 UpdateAccountInfo *info;
1452 ModestMailOperationPrivate *priv;
1454 info = (UpdateAccountInfo *) user_data;
1455 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1457 if (err || canceled) {
1458 /* Try to continue anyway */
1460 TnyIterator *iter = tny_list_create_iterator (list);
1461 while (!tny_iterator_is_done (iter)) {
1462 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1463 TnyList *folders = tny_simple_list_new ();
1465 /* Add to the list of all folders */
1466 tny_list_append (info->folders, (GObject *) folder);
1468 /* Add pending call */
1469 info->pending_calls++;
1471 tny_folder_store_get_folders_async (folder, folders, NULL,
1472 recurse_folders_async_cb,
1475 g_object_unref (G_OBJECT (folder));
1477 tny_iterator_next (iter);
1479 g_object_unref (G_OBJECT (iter));
1480 g_object_unref (G_OBJECT (list));
1483 /* Remove my own pending call */
1484 info->pending_calls--;
1486 /* This means that we have all the folders */
1487 if (info->pending_calls == 0) {
1488 TnyIterator *iter_all_folders;
1489 TnyFolder *inbox = NULL;
1491 iter_all_folders = tny_list_create_iterator (info->folders);
1493 /* Do a poke status over all folders */
1494 while (!tny_iterator_is_done (iter_all_folders) &&
1495 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1496 TnyFolder *folder = NULL;
1498 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1500 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1501 /* Get a reference to the INBOX */
1502 inbox = g_object_ref (folder);
1504 /* Issue a poke status over the folder */
1506 tny_folder_poke_status (folder);
1509 /* Free and go to next */
1510 g_object_unref (folder);
1511 tny_iterator_next (iter_all_folders);
1513 g_object_unref (iter_all_folders);
1515 /* Refresh the INBOX */
1517 /* Refresh the folder. Our observer receives
1518 * the new emails during folder refreshes, so
1519 * we can use observer->new_headers
1521 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1522 tny_folder_add_observer (inbox, info->inbox_observer);
1524 /* Refresh the INBOX */
1525 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1526 g_object_unref (inbox);
1528 /* We could not perform the inbox refresh but
1529 we'll try to send mails anyway */
1530 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1536 modest_mail_operation_update_account (ModestMailOperation *self,
1537 const gchar *account_name,
1539 RetrieveAllCallback retrieve_all_cb,
1540 UpdateAccountCallback callback,
1543 UpdateAccountInfo *info = NULL;
1544 ModestMailOperationPrivate *priv = NULL;
1545 ModestTnyAccountStore *account_store = NULL;
1546 TnyStoreAccount *store_account = NULL;
1549 /* Init mail operation */
1550 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1553 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1554 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1556 /* Get the store account */
1557 account_store = modest_runtime_get_account_store ();
1558 store_account = (TnyStoreAccount *)
1559 modest_tny_account_store_get_server_account (account_store,
1561 TNY_ACCOUNT_TYPE_STORE);
1562 priv->account = g_object_ref (store_account);
1564 /* Create the helper object */
1565 info = g_slice_new0 (UpdateAccountInfo);
1566 info->pending_calls = 1;
1567 info->folders = tny_simple_list_new ();
1568 info->mail_op = g_object_ref (self);
1569 info->poke_all = poke_all;
1570 info->account_name = g_strdup (account_name);
1571 info->callback = callback;
1572 info->user_data = user_data;
1573 info->retrieve_all_cb = retrieve_all_cb;
1575 /* Set account busy */
1576 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1577 modest_mail_operation_notify_start (self);
1579 /* notify about the start of the operation */
1580 ModestMailOperationState *state;
1581 state = modest_mail_operation_clone_state (self);
1585 /* Start notifying progress */
1586 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
1588 g_slice_free (ModestMailOperationState, state);
1590 /* Get all folders and continue in the callback */
1591 folders = tny_simple_list_new ();
1592 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1594 recurse_folders_async_cb,
1599 * Used to notify the queue from the main
1600 * loop. We call it inside an idle call to achieve that
1603 idle_notify_queue (gpointer data)
1605 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1607 gdk_threads_enter ();
1608 modest_mail_operation_notify_end (mail_op);
1609 gdk_threads_leave ();
1610 g_object_unref (mail_op);
1616 compare_headers_by_date (gconstpointer a,
1619 TnyHeader **header1, **header2;
1620 time_t sent1, sent2;
1622 header1 = (TnyHeader **) a;
1623 header2 = (TnyHeader **) b;
1625 sent1 = tny_header_get_date_sent (*header1);
1626 sent2 = tny_header_get_date_sent (*header2);
1628 /* We want the most recent ones (greater time_t) at the
1637 /* ******************************************************************* */
1638 /* ************************** STORE ACTIONS ************************* */
1639 /* ******************************************************************* */
1642 ModestMailOperation *mail_op;
1643 CreateFolderUserCallback callback;
1649 create_folder_cb (TnyFolderStore *parent_folder,
1651 TnyFolder *new_folder,
1655 ModestMailOperationPrivate *priv;
1656 CreateFolderInfo *info;
1658 info = (CreateFolderInfo *) user_data;
1659 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1661 if (canceled || err) {
1662 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1664 priv->error = g_error_copy (err);
1666 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1667 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1670 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1673 /* The user will unref the new_folder */
1675 info->callback (info->mail_op, parent_folder,
1676 new_folder, info->user_data);
1678 /* Notify about operation end */
1679 modest_mail_operation_notify_end (info->mail_op);
1682 g_object_unref (info->mail_op);
1683 g_slice_free (CreateFolderInfo, info);
1687 modest_mail_operation_create_folder (ModestMailOperation *self,
1688 TnyFolderStore *parent,
1690 CreateFolderUserCallback callback,
1693 ModestMailOperationPrivate *priv;
1695 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1696 g_return_if_fail (name);
1698 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1699 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1700 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1701 g_object_ref (parent) :
1702 modest_tny_folder_get_account (TNY_FOLDER (parent));
1704 /* Check for already existing folder */
1705 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1706 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1707 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1708 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1709 _CS("ckdg_ib_folder_already_exists"));
1713 if (TNY_IS_FOLDER (parent)) {
1714 /* Check folder rules */
1715 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1716 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1717 /* Set status failed and set an error */
1718 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1719 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1720 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1721 _("mail_in_ui_folder_create_error"));
1725 if (!strcmp (name, " ") || strchr (name, '/')) {
1726 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1727 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1728 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1729 _("mail_in_ui_folder_create_error"));
1733 CreateFolderInfo *info;
1735 info = g_slice_new0 (CreateFolderInfo);
1736 info->mail_op = g_object_ref (self);
1737 info->callback = callback;
1738 info->user_data = user_data;
1740 modest_mail_operation_notify_start (self);
1742 /* Create the folder */
1743 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1746 /* Call the user callback anyway */
1748 callback (self, parent, NULL, user_data);
1749 /* Notify about operation end */
1750 modest_mail_operation_notify_end (self);
1755 modest_mail_operation_remove_folder (ModestMailOperation *self,
1757 gboolean remove_to_trash)
1759 TnyAccount *account;
1760 ModestMailOperationPrivate *priv;
1761 ModestTnyFolderRules rules;
1763 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1764 g_return_if_fail (TNY_IS_FOLDER (folder));
1766 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1768 /* Check folder rules */
1769 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1770 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1771 /* Set status failed and set an error */
1772 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1773 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1774 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1775 _("mail_in_ui_folder_delete_error"));
1779 /* Get the account */
1780 account = modest_tny_folder_get_account (folder);
1781 priv->account = g_object_ref(account);
1782 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1784 /* Delete folder or move to trash */
1785 if (remove_to_trash) {
1786 TnyFolder *trash_folder = NULL;
1787 trash_folder = modest_tny_account_get_special_folder (account,
1788 TNY_FOLDER_TYPE_TRASH);
1789 /* TODO: error_handling */
1791 modest_mail_operation_notify_start (self);
1792 modest_mail_operation_xfer_folder (self, folder,
1793 TNY_FOLDER_STORE (trash_folder),
1795 g_object_unref (trash_folder);
1797 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1800 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1802 modest_mail_operation_notify_start (self);
1803 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1804 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1807 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1809 g_object_unref (parent);
1811 g_warning ("%s: could not get parent folder", __FUNCTION__);
1813 g_object_unref (G_OBJECT (account));
1816 /* Notify about operation end */
1817 modest_mail_operation_notify_end (self);
1821 transfer_folder_status_cb (GObject *obj,
1825 ModestMailOperation *self;
1826 ModestMailOperationPrivate *priv;
1827 ModestMailOperationState *state;
1828 XFerFolderAsyncHelper *helper;
1830 g_return_if_fail (status != NULL);
1831 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1833 helper = (XFerFolderAsyncHelper *) user_data;
1834 g_return_if_fail (helper != NULL);
1836 self = helper->mail_op;
1837 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1839 priv->done = status->position;
1840 priv->total = status->of_total;
1842 state = modest_mail_operation_clone_state (self);
1844 /* This is not a GDK lock because we are a Tinymail callback
1845 * which is already GDK locked by Tinymail */
1847 /* no gdk_threads_enter (), CHECKED */
1849 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1851 /* no gdk_threads_leave (), CHECKED */
1853 g_slice_free (ModestMailOperationState, state);
1858 transfer_folder_cb (TnyFolder *folder,
1860 TnyFolderStore *into,
1861 TnyFolder *new_folder,
1865 XFerFolderAsyncHelper *helper;
1866 ModestMailOperation *self = NULL;
1867 ModestMailOperationPrivate *priv = NULL;
1869 helper = (XFerFolderAsyncHelper *) user_data;
1870 g_return_if_fail (helper != NULL);
1872 self = helper->mail_op;
1873 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1876 priv->error = g_error_copy (err);
1878 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1879 } else if (cancelled) {
1880 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1881 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1882 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1883 _("Transference of %s was cancelled."),
1884 tny_folder_get_name (folder));
1887 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1890 /* Notify about operation end */
1891 modest_mail_operation_notify_end (self);
1893 /* If user defined callback function was defined, call it */
1894 if (helper->user_callback) {
1896 /* This is not a GDK lock because we are a Tinymail callback
1897 * which is already GDK locked by Tinymail */
1899 /* no gdk_threads_enter (), CHECKED */
1900 helper->user_callback (self, new_folder, helper->user_data);
1901 /* no gdk_threads_leave () , CHECKED */
1905 g_object_unref (helper->mail_op);
1906 g_slice_free (XFerFolderAsyncHelper, helper);
1911 * This function checks if the new name is a valid name for our local
1912 * folders account. The new name could not be the same than then name
1913 * of any of the mandatory local folders
1915 * We can not rely on tinymail because tinymail does not check the
1916 * name of the virtual folders that the account could have in the case
1917 * that we're doing a rename (because it directly calls Camel which
1918 * knows nothing about our virtual folders).
1920 * In the case of an actual copy/move (i.e. move/copy a folder between
1921 * accounts) tinymail uses the tny_folder_store_create_account which
1922 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1923 * checks the new name of the folder, so this call in that case
1924 * wouldn't be needed. *But* NOTE that if tinymail changes its
1925 * implementation (if folder transfers within the same account is no
1926 * longer implemented as a rename) this call will allow Modest to work
1929 * If the new name is not valid, this function will set the status to
1930 * failed and will set also an error in the mail operation
1933 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1934 TnyFolderStore *into,
1935 const gchar *new_name)
1937 if (TNY_IS_ACCOUNT (into) &&
1938 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1939 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1941 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1942 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1943 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1944 _CS("ckdg_ib_folder_already_exists"));
1951 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1953 TnyFolderStore *parent,
1954 gboolean delete_original,
1955 XferFolderAsyncUserCallback user_callback,
1958 ModestMailOperationPrivate *priv = NULL;
1959 ModestTnyFolderRules parent_rules = 0, rules;
1960 XFerFolderAsyncHelper *helper = NULL;
1961 const gchar *folder_name = NULL;
1962 const gchar *error_msg;
1964 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1965 g_return_if_fail (TNY_IS_FOLDER (folder));
1966 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1968 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1969 folder_name = tny_folder_get_name (folder);
1971 /* Set the error msg */
1972 error_msg = _("mail_in_ui_folder_move_target_error");
1974 /* Get account and set it into mail_operation */
1975 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1976 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1977 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1979 /* Get folder rules */
1980 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1981 if (TNY_IS_FOLDER (parent))
1982 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1984 /* Apply operation constraints */
1985 if ((gpointer) parent == (gpointer) folder ||
1986 (!TNY_IS_FOLDER_STORE (parent)) ||
1987 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1990 } else if (TNY_IS_FOLDER (parent) &&
1991 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1995 } else if (TNY_IS_FOLDER (parent) &&
1996 TNY_IS_FOLDER_STORE (folder) &&
1997 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1998 TNY_FOLDER_STORE (folder))) {
1999 /* Do not move a parent into a child */
2001 } else if (TNY_IS_FOLDER_STORE (parent) &&
2002 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2003 /* Check that the new folder name is not used by any
2006 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2007 /* Check that the new folder name is not used by any
2008 special local folder */
2011 /* Create the helper */
2012 helper = g_slice_new0 (XFerFolderAsyncHelper);
2013 helper->mail_op = g_object_ref (self);
2014 helper->user_callback = user_callback;
2015 helper->user_data = user_data;
2017 /* Move/Copy folder */
2018 modest_mail_operation_notify_start (self);
2019 tny_folder_copy_async (folder,
2021 tny_folder_get_name (folder),
2024 transfer_folder_status_cb,
2030 /* Set status failed and set an error */
2031 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2032 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2033 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2036 /* Call the user callback if exists */
2038 user_callback (self, NULL, user_data);
2040 /* Notify the queue */
2041 modest_mail_operation_notify_end (self);
2045 modest_mail_operation_rename_folder (ModestMailOperation *self,
2048 XferFolderAsyncUserCallback user_callback,
2051 ModestMailOperationPrivate *priv;
2052 ModestTnyFolderRules rules;
2053 XFerFolderAsyncHelper *helper;
2055 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2056 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2057 g_return_if_fail (name);
2059 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2061 /* Get account and set it into mail_operation */
2062 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2063 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2065 /* Check folder rules */
2066 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2067 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2069 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2072 TnyFolderStore *into;
2074 into = tny_folder_get_folder_store (folder);
2076 /* Check that the new folder name is not used by any
2077 special local folder */
2078 if (new_name_valid_if_local_account (priv, into, name)) {
2079 /* Create the helper */
2080 helper = g_slice_new0 (XFerFolderAsyncHelper);
2081 helper->mail_op = g_object_ref(self);
2082 helper->user_callback = user_callback;
2083 helper->user_data = user_data;
2085 /* Rename. Camel handles folder subscription/unsubscription */
2086 modest_mail_operation_notify_start (self);
2087 tny_folder_copy_async (folder, into, name, TRUE,
2089 transfer_folder_status_cb,
2094 g_object_unref (into);
2099 /* Set status failed and set an error */
2100 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2101 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2102 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2103 _("FIXME: unable to rename"));
2106 user_callback (self, NULL, user_data);
2108 /* Notify about operation end */
2109 modest_mail_operation_notify_end (self);
2112 /* ******************************************************************* */
2113 /* ************************** MSG ACTIONS ************************* */
2114 /* ******************************************************************* */
2117 modest_mail_operation_get_msg (ModestMailOperation *self,
2119 GetMsgAsyncUserCallback user_callback,
2122 GetMsgInfo *helper = NULL;
2124 ModestMailOperationPrivate *priv;
2126 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2127 g_return_if_fail (TNY_IS_HEADER (header));
2129 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2130 folder = tny_header_get_folder (header);
2132 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2136 /* Get account and set it into mail_operation */
2137 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2139 /* Check for cached messages */
2140 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2141 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2143 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2145 /* Create the helper */
2146 helper = g_slice_new0 (GetMsgInfo);
2147 helper->header = g_object_ref (header);
2148 helper->mail_op = g_object_ref (self);
2149 helper->user_callback = user_callback;
2150 helper->user_data = user_data;
2151 helper->destroy_notify = NULL;
2152 helper->last_total_bytes = 0;
2153 helper->sum_total_bytes = 0;
2154 helper->total_bytes = tny_header_get_message_size (header);
2156 modest_mail_operation_notify_start (self);
2158 /* notify about the start of the operation */
2159 ModestMailOperationState *state;
2160 state = modest_mail_operation_clone_state (self);
2163 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2166 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2168 g_object_unref (G_OBJECT (folder));
2172 get_msg_status_cb (GObject *obj,
2176 GetMsgInfo *helper = NULL;
2178 g_return_if_fail (status != NULL);
2179 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2181 helper = (GetMsgInfo *) user_data;
2182 g_return_if_fail (helper != NULL);
2184 /* Notify progress */
2185 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2186 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2190 get_msg_async_cb (TnyFolder *folder,
2196 GetMsgInfo *info = NULL;
2197 ModestMailOperationPrivate *priv = NULL;
2200 info = (GetMsgInfo *) user_data;
2202 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2204 finished = (priv->done == priv->total) ? TRUE : FALSE;
2207 if (canceled || err) {
2208 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2210 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2211 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2214 /* Set the success status before calling the user callback */
2215 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2216 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2220 /* Call the user callback */
2221 if (info->user_callback)
2222 info->user_callback (info->mail_op, info->header, canceled,
2223 msg, err, info->user_data);
2225 /* Notify about operation end if this is the last callback */
2227 /* Free user data */
2228 if (info->destroy_notify)
2229 info->destroy_notify (info->user_data);
2231 /* Notify about operation end */
2232 modest_mail_operation_notify_end (info->mail_op);
2236 g_object_unref (info->header);
2237 g_object_unref (info->mail_op);
2238 g_slice_free (GetMsgInfo, info);
2242 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2243 TnyList *header_list,
2244 GetMsgAsyncUserCallback user_callback,
2246 GDestroyNotify notify)
2248 ModestMailOperationPrivate *priv = NULL;
2249 gboolean size_ok = TRUE;
2251 TnyIterator *iter = NULL;
2253 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2255 /* Init mail operation */
2256 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2257 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2258 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2260 priv->total = tny_list_get_length(header_list);
2262 /* Get account and set it into mail_operation */
2263 if (tny_list_get_length (header_list) >= 1) {
2264 iter = tny_list_create_iterator (header_list);
2265 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2267 TnyFolder *folder = tny_header_get_folder (header);
2269 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2270 g_object_unref (folder);
2272 g_object_unref (header);
2275 if (tny_list_get_length (header_list) == 1) {
2276 g_object_unref (iter);
2281 /* Get msg size limit */
2282 max_size = modest_conf_get_int (modest_runtime_get_conf (),
2283 MODEST_CONF_MSG_SIZE_LIMIT,
2286 g_clear_error (&(priv->error));
2287 max_size = G_MAXINT;
2289 max_size = max_size * KB;
2292 /* Check message size limits. If there is only one message
2293 always retrieve it */
2295 while (!tny_iterator_is_done (iter) && size_ok) {
2296 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2298 if (tny_header_get_message_size (header) >= max_size)
2300 g_object_unref (header);
2303 tny_iterator_next (iter);
2305 g_object_unref (iter);
2309 const gint msg_list_size = compute_message_list_size (header_list);
2311 modest_mail_operation_notify_start (self);
2312 iter = tny_list_create_iterator (header_list);
2313 while (!tny_iterator_is_done (iter)) {
2314 /* notify about the start of the operation */
2315 ModestMailOperationState *state;
2316 state = modest_mail_operation_clone_state (self);
2319 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2322 GetMsgInfo *msg_info = NULL;
2323 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2324 TnyFolder *folder = tny_header_get_folder (header);
2326 /* Create the message info */
2327 msg_info = g_slice_new0 (GetMsgInfo);
2328 msg_info->mail_op = g_object_ref (self);
2329 msg_info->header = g_object_ref (header);
2330 msg_info->user_callback = user_callback;
2331 msg_info->user_data = user_data;
2332 msg_info->destroy_notify = notify;
2333 msg_info->last_total_bytes = 0;
2334 msg_info->sum_total_bytes = 0;
2335 msg_info->total_bytes = msg_list_size;
2337 /* The callback will call it per each header */
2338 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2340 /* Free and go on */
2341 g_object_unref (header);
2342 g_object_unref (folder);
2343 tny_iterator_next (iter);
2345 g_object_unref (iter);
2347 /* Set status failed and set an error */
2348 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2349 /* FIXME: the error msg is different for pop */
2350 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2351 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
2352 _("emev_ni_ui_imap_msg_size_exceed_error"));
2353 /* Remove from queue and free resources */
2354 modest_mail_operation_notify_end (self);
2363 modest_mail_operation_remove_msg (ModestMailOperation *self,
2365 gboolean remove_to_trash /*ignored*/)
2368 ModestMailOperationPrivate *priv;
2370 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2371 g_return_if_fail (TNY_IS_HEADER (header));
2373 if (remove_to_trash)
2374 g_warning ("remove to trash is not implemented");
2376 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2377 folder = tny_header_get_folder (header);
2379 /* Get account and set it into mail_operation */
2380 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2381 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2382 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2384 /* remove message from folder */
2385 tny_folder_remove_msg (folder, header, &(priv->error));
2387 gboolean expunge, leave_on_server;
2388 const gchar *account_name;
2389 TnyAccount *account;
2390 ModestTransportStoreProtocol account_proto;
2392 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2393 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2395 modest_mail_operation_notify_start (self);
2397 /* Get leave on server setting */
2398 account = tny_folder_get_account (folder);
2399 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2401 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2404 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2406 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2407 modest_tny_folder_is_remote_folder (folder) == FALSE)
2413 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2416 g_object_unref (account);
2422 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2424 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2427 g_object_unref (G_OBJECT (folder));
2429 /* Notify about operation end */
2430 modest_mail_operation_notify_end (self);
2434 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2436 gboolean remove_to_trash /*ignored*/)
2439 ModestMailOperationPrivate *priv;
2440 TnyIterator *iter = NULL;
2441 TnyHeader *header = NULL;
2442 TnyList *remove_headers = NULL;
2443 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2445 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2446 g_return_if_fail (TNY_IS_LIST (headers));
2448 if (remove_to_trash)
2449 g_warning ("remove to trash is not implemented");
2451 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2453 remove_headers = g_object_ref(headers);
2455 /* Get folder from first header and sync it */
2456 iter = tny_list_create_iterator (headers);
2457 header = TNY_HEADER (tny_iterator_get_current (iter));
2458 folder = tny_header_get_folder (header);
2460 /* Don't remove messages that are being sent */
2461 if (modest_tny_folder_is_local_folder (folder)) {
2462 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2464 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2465 TnyTransportAccount *traccount = NULL;
2466 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2467 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2469 ModestTnySendQueueStatus status;
2470 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2471 TnyIterator *iter = tny_list_create_iterator(headers);
2472 g_object_unref(remove_headers);
2473 remove_headers = TNY_LIST(tny_simple_list_new());
2474 while (!tny_iterator_is_done(iter)) {
2476 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2477 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2478 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2479 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2480 tny_list_append(remove_headers, G_OBJECT(hdr));
2482 g_object_unref(hdr);
2484 tny_iterator_next(iter);
2486 g_object_unref(iter);
2487 g_object_unref(traccount);
2491 /* Get account and set it into mail_operation */
2492 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2493 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2494 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2496 /* remove message from folder */
2497 modest_mail_operation_notify_start (self);
2499 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2501 gboolean expunge, leave_on_server;
2502 const gchar *account_name;
2504 TnyAccount *account;
2505 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2507 account = tny_folder_get_account (folder);
2508 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2510 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2513 proto = tny_account_get_proto (account);
2515 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2518 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2519 modest_tny_folder_is_remote_folder (folder) == FALSE)
2525 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2527 g_object_unref (account);
2533 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2535 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2538 g_object_unref (remove_headers);
2539 g_object_unref (header);
2540 g_object_unref (iter);
2541 g_object_unref (G_OBJECT (folder));
2543 /* Notify about operation end */
2544 modest_mail_operation_notify_end (self);
2548 notify_progress_of_multiple_messages (ModestMailOperation *self,
2550 gint *last_total_bytes,
2551 gint *sum_total_bytes,
2553 gboolean increment_done)
2555 ModestMailOperationPrivate *priv;
2556 ModestMailOperationState *state;
2557 gboolean is_num_bytes = FALSE;
2559 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2561 /* We know that tinymail sends us information about
2562 * transferred bytes with this particular message
2564 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2565 * I just added the 'if' so we don't get runtime warning)
2567 if (status->message)
2568 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2570 state = modest_mail_operation_clone_state (self);
2571 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2572 /* We know that we're in a different message when the
2573 total number of bytes to transfer is different. Of
2574 course it could fail if we're transferring messages
2575 of the same size, but this is a workarround */
2576 if (status->of_total != *last_total_bytes) {
2577 /* We need to increment the done when there is
2578 no information about each individual
2579 message, we need to do this in message
2580 transfers, and we don't do it for getting
2584 *sum_total_bytes += *last_total_bytes;
2585 *last_total_bytes = status->of_total;
2587 state->bytes_done += status->position + *sum_total_bytes;
2588 state->bytes_total = total_bytes;
2590 /* Notify the status change. Only notify about changes
2591 referred to bytes */
2592 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2596 g_slice_free (ModestMailOperationState, state);
2600 transfer_msgs_status_cb (GObject *obj,
2604 XFerMsgsAsyncHelper *helper;
2606 g_return_if_fail (status != NULL);
2607 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2609 helper = (XFerMsgsAsyncHelper *) user_data;
2610 g_return_if_fail (helper != NULL);
2612 /* Notify progress */
2613 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2614 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2619 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2621 XFerMsgsAsyncHelper *helper;
2622 ModestMailOperation *self;
2623 ModestMailOperationPrivate *priv;
2624 TnyIterator *iter = NULL;
2625 TnyHeader *header = NULL;
2627 helper = (XFerMsgsAsyncHelper *) user_data;
2628 self = helper->mail_op;
2630 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2633 priv->error = g_error_copy (err);
2635 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2636 } else if (cancelled) {
2637 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2638 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2639 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2640 _("Error trying to refresh the contents of %s"),
2641 tny_folder_get_name (folder));
2644 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2646 /* Update folder counts */
2647 tny_folder_poke_status (folder);
2648 tny_folder_poke_status (helper->dest_folder);
2652 /* Mark headers as deleted and seen */
2653 if ((helper->delete) &&
2654 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2655 iter = tny_list_create_iterator (helper->headers);
2656 while (!tny_iterator_is_done (iter)) {
2657 header = TNY_HEADER (tny_iterator_get_current (iter));
2658 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2659 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2660 g_object_unref (header);
2662 tny_iterator_next (iter);
2667 /* Notify about operation end */
2668 modest_mail_operation_notify_end (self);
2670 /* If user defined callback function was defined, call it */
2671 if (helper->user_callback) {
2672 /* This is not a GDK lock because we are a Tinymail callback and
2673 * Tinymail already acquires the Gdk lock */
2675 /* no gdk_threads_enter (), CHECKED */
2676 helper->user_callback (self, helper->user_data);
2677 /* no gdk_threads_leave (), CHECKED */
2681 if (helper->headers)
2682 g_object_unref (helper->headers);
2683 if (helper->dest_folder)
2684 g_object_unref (helper->dest_folder);
2685 if (helper->mail_op)
2686 g_object_unref (helper->mail_op);
2688 g_object_unref (folder);
2690 g_object_unref (iter);
2691 g_slice_free (XFerMsgsAsyncHelper, helper);
2695 compute_message_list_size (TnyList *headers)
2700 iter = tny_list_create_iterator (headers);
2701 while (!tny_iterator_is_done (iter)) {
2702 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2703 size += tny_header_get_message_size (header);
2704 g_object_unref (header);
2705 tny_iterator_next (iter);
2707 g_object_unref (iter);
2713 compute_message_array_size (GPtrArray *headers)
2718 for (i = 0; i < headers->len; i++) {
2719 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2720 size += tny_header_get_message_size (header);
2728 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2731 gboolean delete_original,
2732 XferMsgsAsyncUserCallback user_callback,
2735 ModestMailOperationPrivate *priv = NULL;
2736 TnyIterator *iter = NULL;
2737 TnyFolder *src_folder = NULL;
2738 XFerMsgsAsyncHelper *helper = NULL;
2739 TnyHeader *header = NULL;
2740 ModestTnyFolderRules rules = 0;
2742 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2743 g_return_if_fail (headers && TNY_IS_LIST (headers));
2744 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2746 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2747 priv->total = tny_list_get_length (headers);
2749 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2750 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2752 /* Apply folder rules */
2753 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2754 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2755 /* Set status failed and set an error */
2756 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2757 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2758 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2759 _CS("ckct_ib_unable_to_paste_here"));
2760 /* Notify the queue */
2761 modest_mail_operation_notify_end (self);
2765 /* Get source folder */
2766 iter = tny_list_create_iterator (headers);
2767 header = TNY_HEADER (tny_iterator_get_current (iter));
2769 src_folder = tny_header_get_folder (header);
2770 g_object_unref (header);
2772 g_object_unref (iter);
2774 if (src_folder == NULL) {
2775 /* Notify the queue */
2776 modest_mail_operation_notify_end (self);
2778 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2783 /* Check folder source and destination */
2784 if (src_folder == folder) {
2785 /* Set status failed and set an error */
2786 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2787 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2788 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2789 _("mail_in_ui_folder_copy_target_error"));
2791 /* Notify the queue */
2792 modest_mail_operation_notify_end (self);
2795 g_object_unref (src_folder);
2799 /* Create the helper */
2800 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2801 helper->mail_op = g_object_ref(self);
2802 helper->dest_folder = g_object_ref(folder);
2803 helper->headers = g_object_ref(headers);
2804 helper->user_callback = user_callback;
2805 helper->user_data = user_data;
2806 helper->delete = delete_original;
2807 helper->last_total_bytes = 0;
2808 helper->sum_total_bytes = 0;
2809 helper->total_bytes = compute_message_list_size (headers);
2811 /* Get account and set it into mail_operation */
2812 priv->account = modest_tny_folder_get_account (src_folder);
2814 /* Transfer messages */
2815 modest_mail_operation_notify_start (self);
2816 tny_folder_transfer_msgs_async (src_folder,
2821 transfer_msgs_status_cb,
2827 on_refresh_folder (TnyFolder *folder,
2832 RefreshAsyncHelper *helper = NULL;
2833 ModestMailOperation *self = NULL;
2834 ModestMailOperationPrivate *priv = NULL;
2836 helper = (RefreshAsyncHelper *) user_data;
2837 self = helper->mail_op;
2838 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2840 g_return_if_fail(priv!=NULL);
2843 priv->error = g_error_copy (error);
2844 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2849 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2850 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2851 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2852 _("Error trying to refresh the contents of %s"),
2853 tny_folder_get_name (folder));
2857 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2860 /* Call user defined callback, if it exists */
2861 if (helper->user_callback) {
2863 /* This is not a GDK lock because we are a Tinymail callback and
2864 * Tinymail already acquires the Gdk lock */
2865 helper->user_callback (self, folder, helper->user_data);
2869 g_slice_free (RefreshAsyncHelper, helper);
2871 /* Notify about operation end */
2872 modest_mail_operation_notify_end (self);
2873 g_object_unref(self);
2877 on_refresh_folder_status_update (GObject *obj,
2881 RefreshAsyncHelper *helper = NULL;
2882 ModestMailOperation *self = NULL;
2883 ModestMailOperationPrivate *priv = NULL;
2884 ModestMailOperationState *state;
2886 g_return_if_fail (user_data != NULL);
2887 g_return_if_fail (status != NULL);
2888 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2890 helper = (RefreshAsyncHelper *) user_data;
2891 self = helper->mail_op;
2892 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2894 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2896 priv->done = status->position;
2897 priv->total = status->of_total;
2899 state = modest_mail_operation_clone_state (self);
2901 /* This is not a GDK lock because we are a Tinymail callback and
2902 * Tinymail already acquires the Gdk lock */
2903 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2905 g_slice_free (ModestMailOperationState, state);
2909 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2911 RefreshAsyncUserCallback user_callback,
2914 ModestMailOperationPrivate *priv = NULL;
2915 RefreshAsyncHelper *helper = NULL;
2917 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2919 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2921 /* Get account and set it into mail_operation */
2922 priv->account = modest_tny_folder_get_account (folder);
2923 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2925 /* Create the helper */
2926 helper = g_slice_new0 (RefreshAsyncHelper);
2927 helper->mail_op = g_object_ref(self);
2928 helper->user_callback = user_callback;
2929 helper->user_data = user_data;
2931 /* Refresh the folder. TODO: tinymail could issue a status
2932 updates before the callback call then this could happen. We
2933 must review the design */
2934 modest_mail_operation_notify_start (self);
2936 /* notify that the operation was started */
2937 ModestMailOperationState *state;
2938 state = modest_mail_operation_clone_state (self);
2941 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2944 tny_folder_refresh_async (folder,
2946 on_refresh_folder_status_update,
2952 modest_mail_operation_notify_start (ModestMailOperation *self)
2954 ModestMailOperationPrivate *priv = NULL;
2956 g_return_if_fail (self);
2958 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2960 /* Ensure that all the fields are filled correctly */
2961 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2963 /* Notify the observers about the mail operation. We do not
2964 wrapp this emission because we assume that this function is
2965 always called from within the main lock */
2966 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2971 * It's used by the mail operation queue to notify the observers
2972 * attached to that signal that the operation finished. We need to use
2973 * that because tinymail does not give us the progress of a given
2974 * operation when it finishes (it directly calls the operation
2978 modest_mail_operation_notify_end (ModestMailOperation *self)
2980 ModestMailOperationPrivate *priv = NULL;
2982 g_return_if_fail (self);
2984 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2986 /* Notify the observers about the mail operation end. We do
2987 not wrapp this emission because we assume that this
2988 function is always called from within the main lock */
2989 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2991 /* Remove the error user data */
2992 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2993 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2997 modest_mail_operation_get_account (ModestMailOperation *self)
2999 ModestMailOperationPrivate *priv = NULL;
3001 g_return_val_if_fail (self, NULL);
3003 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3005 return (priv->account) ? g_object_ref (priv->account) : NULL;
3009 modest_mail_operation_noop (ModestMailOperation *self)
3011 ModestMailOperationPrivate *priv = NULL;
3013 g_return_if_fail (self);
3015 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3016 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3017 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3021 /* This mail operation does nothing actually */
3022 modest_mail_operation_notify_start (self);
3023 modest_mail_operation_notify_end (self);
3028 modest_mail_operation_to_string (ModestMailOperation *self)
3030 const gchar *type, *status, *account_id;
3031 ModestMailOperationPrivate *priv = NULL;
3033 g_return_val_if_fail (self, NULL);
3035 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3037 /* new operations don't have anything interesting */
3038 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3039 return g_strdup_printf ("%p <new operation>", self);
3041 switch (priv->op_type) {
3042 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3043 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3044 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3045 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3046 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3047 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3048 default: type = "UNEXPECTED"; break;
3051 switch (priv->status) {
3052 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3053 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3054 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3055 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3056 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3057 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3058 default: status= "UNEXPECTED"; break;
3061 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3063 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3064 priv->done, priv->total,
3065 priv->error && priv->error->message ? priv->error->message : "");