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 if (!TNY_IS_MSG(msg)) {
711 g_warning ("%s: did not receive a valid msg", __FUNCTION__);
715 hdr1 = tny_msg_get_header(msg);
716 hdr2 = tny_msg_get_header(info->msg);
717 msgid1 = tny_header_get_message_id(hdr1);
718 msgid2 = tny_header_get_message_id(hdr2);
719 if (msgid1 == NULL) msgid1 = "(null)";
720 if (msgid2 == NULL) msgid2 = "(null)";
722 if (!strcmp (msgid1, msgid2)) {
724 g_warning ("%s: %s\n", __FUNCTION__, error->message);
725 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
726 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
727 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
728 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
729 "modest: send mail failed\n");
731 common_send_mail_operation_end (queue, msg, info);
733 g_object_unref(G_OBJECT(hdr1));
734 g_object_unref(G_OBJECT(hdr2));
739 idle_create_msg_cb (gpointer idle_data)
741 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
743 /* This is a GDK lock because we are an idle callback and
744 * info->callback can contain Gtk+ code */
746 gdk_threads_enter (); /* CHECKED */
747 info->callback (info->mail_op, info->msg, info->userdata);
749 g_object_unref (info->mail_op);
751 g_object_unref (info->msg);
752 g_slice_free (CreateMsgIdleInfo, info);
753 gdk_threads_leave (); /* CHECKED */
759 create_msg_thread (gpointer thread_data)
761 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
762 TnyMsg *new_msg = NULL;
763 ModestMailOperationPrivate *priv;
765 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
766 if (info->html_body == NULL) {
767 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
768 info->bcc, info->subject, info->plain_body,
769 info->attachments_list);
771 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
772 info->bcc, info->subject, info->html_body,
773 info->plain_body, info->attachments_list,
780 /* Set priority flags in message */
781 header = tny_msg_get_header (new_msg);
782 tny_header_set_flag (header, info->priority_flags);
784 /* Set attachment flags in message */
785 if (info->attachments_list != NULL)
786 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
788 g_object_unref (G_OBJECT(header));
790 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
791 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
792 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
793 "modest: failed to create a new msg\n");
801 g_free (info->plain_body);
802 g_free (info->html_body);
803 g_free (info->subject);
804 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
805 g_list_free (info->attachments_list);
806 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
807 g_list_free (info->images_list);
809 if (info->callback) {
810 CreateMsgIdleInfo *idle_info;
811 idle_info = g_slice_new0 (CreateMsgIdleInfo);
812 idle_info->mail_op = g_object_ref (info->mail_op);
813 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
814 idle_info->callback = info->callback;
815 idle_info->userdata = info->userdata;
816 g_idle_add (idle_create_msg_cb, idle_info);
818 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
821 g_object_unref (info->mail_op);
822 g_slice_free (CreateMsgInfo, info);
823 if (new_msg) g_object_unref(new_msg);
828 modest_mail_operation_create_msg (ModestMailOperation *self,
829 const gchar *from, const gchar *to,
830 const gchar *cc, const gchar *bcc,
831 const gchar *subject, const gchar *plain_body,
832 const gchar *html_body,
833 const GList *attachments_list,
834 const GList *images_list,
835 TnyHeaderFlags priority_flags,
836 ModestMailOperationCreateMsgCallback callback,
839 CreateMsgInfo *info = NULL;
841 info = g_slice_new0 (CreateMsgInfo);
842 info->mail_op = g_object_ref (self);
844 info->from = g_strdup (from);
845 info->to = g_strdup (to);
846 info->cc = g_strdup (cc);
847 info->bcc = g_strdup (bcc);
848 info->subject = g_strdup (subject);
849 info->plain_body = g_strdup (plain_body);
850 info->html_body = g_strdup (html_body);
851 info->attachments_list = g_list_copy ((GList *) attachments_list);
852 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
853 info->images_list = g_list_copy ((GList *) images_list);
854 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
855 info->priority_flags = priority_flags;
857 info->callback = callback;
858 info->userdata = userdata;
860 g_thread_create (create_msg_thread, info, FALSE, NULL);
865 TnyTransportAccount *transport_account;
870 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
874 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
875 TnyFolder *draft_folder = NULL;
876 TnyFolder *outbox_folder = NULL;
884 /* Call mail operation */
885 modest_mail_operation_send_mail (self, info->transport_account, msg);
887 /* Remove old mail from its source folder */
888 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
889 TNY_FOLDER_TYPE_DRAFTS);
891 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder", __FUNCTION__);
894 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
895 TNY_FOLDER_TYPE_OUTBOX);
896 if (!outbox_folder) {
897 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder", __FUNCTION__);
900 if (info->draft_msg != NULL) {
901 TnyFolder *folder = NULL;
902 TnyFolder *src_folder = NULL;
903 TnyFolderType folder_type;
904 folder = tny_msg_get_folder (info->draft_msg);
905 if (folder == NULL) goto end;
906 folder_type = modest_tny_folder_guess_folder_type (folder);
908 if (folder_type == TNY_FOLDER_TYPE_INVALID)
909 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
911 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
912 src_folder = outbox_folder;
914 src_folder = draft_folder;
916 /* Note: This can fail (with a warning) if the message is not really already in a folder,
917 * because this function requires it to have a UID. */
918 header = tny_msg_get_header (info->draft_msg);
919 tny_folder_remove_msg (src_folder, header, NULL);
921 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
922 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
924 g_object_unref (header);
925 g_object_unref (folder);
932 g_object_unref (info->draft_msg);
934 g_object_unref (draft_folder);
936 g_object_unref (outbox_folder);
937 if (info->transport_account)
938 g_object_unref (info->transport_account);
939 g_slice_free (SendNewMailInfo, info);
943 modest_mail_operation_send_new_mail (ModestMailOperation *self,
944 TnyTransportAccount *transport_account,
946 const gchar *from, const gchar *to,
947 const gchar *cc, const gchar *bcc,
948 const gchar *subject, const gchar *plain_body,
949 const gchar *html_body,
950 const GList *attachments_list,
951 const GList *images_list,
952 TnyHeaderFlags priority_flags)
954 ModestMailOperationPrivate *priv = NULL;
955 SendNewMailInfo *info;
957 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
958 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
960 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
961 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
962 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
963 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
965 /* Check parametters */
967 /* Set status failed and set an error */
968 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
969 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
970 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
971 _("Error trying to send a mail. You need to set at least one recipient"));
974 info = g_slice_new0 (SendNewMailInfo);
975 info->transport_account = transport_account;
976 if (transport_account)
977 g_object_ref (transport_account);
978 info->draft_msg = draft_msg;
980 g_object_ref (draft_msg);
983 modest_mail_operation_notify_start (self);
984 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
985 attachments_list, images_list, priority_flags,
986 modest_mail_operation_send_new_mail_cb, info);
992 TnyTransportAccount *transport_account;
994 SaveToDraftstCallback callback;
998 ModestMailOperation *mailop;
999 } SaveToDraftsAddMsgInfo;
1002 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1007 ModestMailOperationPrivate *priv = NULL;
1008 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1010 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1013 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1014 g_error_free(priv->error);
1017 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1019 if ((!priv->error) && (info->draft_msg != NULL)) {
1020 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1021 TnyFolder *src_folder = tny_header_get_folder (header);
1023 /* Remove the old draft */
1024 tny_folder_remove_msg (src_folder, header, NULL);
1026 /* Synchronize to expunge and to update the msg counts */
1027 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1028 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1030 g_object_unref (G_OBJECT(header));
1031 g_object_unref (G_OBJECT(src_folder));
1035 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1037 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1039 /* Call the user callback */
1041 info->callback (info->mailop, info->msg, info->user_data);
1043 if (info->transport_account)
1044 g_object_unref (G_OBJECT(info->transport_account));
1045 if (info->draft_msg)
1046 g_object_unref (G_OBJECT (info->draft_msg));
1048 g_object_unref (G_OBJECT(info->drafts));
1050 g_object_unref (G_OBJECT (info->msg));
1052 modest_mail_operation_notify_end (info->mailop);
1053 g_object_unref(info->mailop);
1054 g_slice_free (SaveToDraftsAddMsgInfo, info);
1059 TnyTransportAccount *transport_account;
1061 SaveToDraftstCallback callback;
1066 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1070 TnyFolder *drafts = NULL;
1071 ModestMailOperationPrivate *priv = NULL;
1072 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1074 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1077 if (!(priv->error)) {
1078 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1079 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1080 "modest: failed to create a new msg\n");
1083 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1084 TNY_FOLDER_TYPE_DRAFTS);
1085 if (!drafts && !(priv->error)) {
1086 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1087 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1088 "modest: failed to create a new msg\n");
1093 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1094 cb_info->transport_account = g_object_ref(info->transport_account);
1095 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1096 cb_info->callback = info->callback;
1097 cb_info->user_data = info->user_data;
1098 cb_info->drafts = g_object_ref(drafts);
1099 cb_info->msg = g_object_ref(msg);
1100 cb_info->mailop = g_object_ref(self);
1101 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1104 /* Call the user callback */
1105 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1107 info->callback (self, msg, info->user_data);
1108 modest_mail_operation_notify_end (self);
1112 g_object_unref (G_OBJECT(drafts));
1113 if (info->draft_msg)
1114 g_object_unref (G_OBJECT (info->draft_msg));
1115 if (info->transport_account)
1116 g_object_unref (G_OBJECT(info->transport_account));
1117 g_slice_free (SaveToDraftsInfo, info);
1121 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1122 TnyTransportAccount *transport_account,
1124 const gchar *from, const gchar *to,
1125 const gchar *cc, const gchar *bcc,
1126 const gchar *subject, const gchar *plain_body,
1127 const gchar *html_body,
1128 const GList *attachments_list,
1129 const GList *images_list,
1130 TnyHeaderFlags priority_flags,
1131 SaveToDraftstCallback callback,
1134 ModestMailOperationPrivate *priv = NULL;
1135 SaveToDraftsInfo *info = NULL;
1137 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1138 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1140 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1142 /* Get account and set it into mail_operation */
1143 priv->account = g_object_ref (transport_account);
1144 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1146 info = g_slice_new0 (SaveToDraftsInfo);
1147 info->transport_account = g_object_ref (transport_account);
1148 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1149 info->callback = callback;
1150 info->user_data = user_data;
1152 modest_mail_operation_notify_start (self);
1153 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1154 attachments_list, images_list, priority_flags,
1155 modest_mail_operation_save_to_drafts_cb, info);
1160 ModestMailOperation *mail_op;
1161 TnyMimePart *mime_part;
1163 GetMimePartSizeCallback callback;
1165 } GetMimePartSizeInfo;
1167 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1168 /* We use this folder observer to track the headers that have been
1169 * added to a folder */
1172 TnyList *new_headers;
1173 } InternalFolderObserver;
1176 GObjectClass parent;
1177 } InternalFolderObserverClass;
1179 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1181 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1182 internal_folder_observer,
1184 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1188 foreach_add_item (gpointer header, gpointer user_data)
1190 tny_list_prepend (TNY_LIST (user_data),
1191 g_object_ref (G_OBJECT (header)));
1194 /* This is the method that looks for new messages in a folder */
1196 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1198 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1200 TnyFolderChangeChanged changed;
1202 changed = tny_folder_change_get_changed (change);
1204 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1207 /* Get added headers */
1208 list = tny_simple_list_new ();
1209 tny_folder_change_get_added_headers (change, list);
1211 /* Add them to the folder observer */
1212 tny_list_foreach (list, foreach_add_item,
1213 derived->new_headers);
1215 g_object_unref (G_OBJECT (list));
1220 internal_folder_observer_init (InternalFolderObserver *self)
1222 self->new_headers = tny_simple_list_new ();
1225 internal_folder_observer_finalize (GObject *object)
1227 InternalFolderObserver *self;
1229 self = (InternalFolderObserver *) object;
1230 g_object_unref (self->new_headers);
1232 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1235 tny_folder_observer_init (TnyFolderObserverIface *iface)
1237 iface->update_func = internal_folder_observer_update;
1240 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1242 GObjectClass *object_class;
1244 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1245 object_class = (GObjectClass*) klass;
1246 object_class->finalize = internal_folder_observer_finalize;
1251 ModestMailOperation *mail_op;
1252 gchar *account_name;
1253 UpdateAccountCallback callback;
1258 TnyFolderObserver *inbox_observer;
1259 RetrieveAllCallback retrieve_all_cb;
1260 } UpdateAccountInfo;
1264 destroy_update_account_info (UpdateAccountInfo *info)
1266 g_free (info->account_name);
1267 g_object_unref (info->folders);
1268 g_object_unref (info->mail_op);
1269 g_slice_free (UpdateAccountInfo, info);
1273 update_account_get_msg_async_cb (TnyFolder *folder,
1279 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1281 /* Just delete the helper. Don't do anything with the new
1282 msg. There is also no need to check for errors */
1283 g_object_unref (msg_info->mail_op);
1284 g_object_unref (msg_info->header);
1285 g_slice_free (GetMsgInfo, msg_info);
1290 inbox_refreshed_cb (TnyFolder *inbox,
1295 UpdateAccountInfo *info;
1296 ModestMailOperationPrivate *priv;
1297 TnyIterator *new_headers_iter;
1298 GPtrArray *new_headers_array = NULL;
1299 gint max_size, retrieve_limit, i;
1300 ModestAccountMgr *mgr;
1301 ModestAccountRetrieveType retrieve_type;
1302 TnyList *new_headers = NULL;
1303 gboolean headers_only, ignore_limit;
1304 TnyTransportAccount *transport_account;
1305 ModestTnySendQueue *send_queue;
1307 info = (UpdateAccountInfo *) user_data;
1308 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1309 mgr = modest_runtime_get_account_mgr ();
1311 if (canceled || err || !inbox) {
1312 /* Try to send anyway */
1316 /* Get the message max size */
1317 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1318 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1320 max_size = G_MAXINT;
1322 max_size = max_size * KB;
1324 /* Create the new headers array. We need it to sort the
1325 new headers by date */
1326 new_headers_array = g_ptr_array_new ();
1327 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1328 while (!tny_iterator_is_done (new_headers_iter)) {
1329 TnyHeader *header = NULL;
1331 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1332 /* Apply per-message size limits */
1333 if (tny_header_get_message_size (header) < max_size)
1334 g_ptr_array_add (new_headers_array, g_object_ref (header));
1336 g_object_unref (header);
1337 tny_iterator_next (new_headers_iter);
1339 g_object_unref (new_headers_iter);
1340 tny_folder_remove_observer (inbox, info->inbox_observer);
1341 g_object_unref (info->inbox_observer);
1342 info->inbox_observer = NULL;
1344 /* Update the last updated key, even if we don't have to get new headers */
1345 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1347 if (new_headers_array->len == 0)
1350 /* Get per-account message amount retrieval limit */
1351 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1352 if (retrieve_limit == 0)
1353 retrieve_limit = G_MAXINT;
1355 /* Get per-account retrieval type */
1356 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1357 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1360 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1362 /* Ask the users if they want to retrieve all the messages
1363 even though the limit was exceeded */
1364 ignore_limit = FALSE;
1365 if (new_headers_array->len > retrieve_limit) {
1366 /* Ask the user if a callback has been specified and
1367 if the mail operation has a source (this means that
1368 was invoked by the user and not automatically by a
1370 if (info->retrieve_all_cb && priv->source)
1371 ignore_limit = info->retrieve_all_cb (priv->source,
1372 new_headers_array->len,
1376 if (!headers_only) {
1378 const gint msg_list_size = compute_message_array_size (new_headers_array);
1382 priv->total = new_headers_array->len;
1384 priv->total = MIN (new_headers_array->len, retrieve_limit);
1385 while (msg_num < priv->total) {
1386 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1387 TnyFolder *folder = tny_header_get_folder (header);
1388 GetMsgInfo *msg_info;
1390 /* Create the message info */
1391 msg_info = g_slice_new0 (GetMsgInfo);
1392 msg_info->mail_op = g_object_ref (info->mail_op);
1393 msg_info->header = g_object_ref (header);
1394 msg_info->total_bytes = msg_list_size;
1396 /* Get message in an async way */
1397 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1398 get_msg_status_cb, msg_info);
1400 g_object_unref (folder);
1406 /* Copy the headers to a list and free the array */
1407 new_headers = tny_simple_list_new ();
1408 for (i=0; i < new_headers_array->len; i++) {
1409 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1410 tny_list_append (new_headers, G_OBJECT (header));
1412 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1413 g_ptr_array_free (new_headers_array, FALSE);
1420 /* Get the transport account */
1421 transport_account = (TnyTransportAccount *)
1422 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1423 info->account_name);
1426 send_queue = modest_runtime_get_send_queue (transport_account);
1427 modest_tny_send_queue_try_to_send (send_queue);
1429 /* Check if the operation was a success */
1431 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1433 /* Set the account back to not busy */
1434 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1436 /* Call the user callback */
1438 info->callback (info->mail_op, new_headers, info->user_data);
1440 /* Notify about operation end */
1441 modest_mail_operation_notify_end (info->mail_op);
1445 g_object_unref (new_headers);
1446 destroy_update_account_info (info);
1450 recurse_folders_async_cb (TnyFolderStore *folder_store,
1456 UpdateAccountInfo *info;
1457 ModestMailOperationPrivate *priv;
1459 info = (UpdateAccountInfo *) user_data;
1460 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1462 if (err || canceled) {
1463 /* Try to continue anyway */
1465 TnyIterator *iter = tny_list_create_iterator (list);
1466 while (!tny_iterator_is_done (iter)) {
1467 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1468 TnyList *folders = tny_simple_list_new ();
1470 /* Add to the list of all folders */
1471 tny_list_append (info->folders, (GObject *) folder);
1473 /* Add pending call */
1474 info->pending_calls++;
1476 tny_folder_store_get_folders_async (folder, folders, NULL,
1477 recurse_folders_async_cb,
1480 g_object_unref (G_OBJECT (folder));
1482 tny_iterator_next (iter);
1484 g_object_unref (G_OBJECT (iter));
1485 g_object_unref (G_OBJECT (list));
1488 /* Remove my own pending call */
1489 info->pending_calls--;
1491 /* This means that we have all the folders */
1492 if (info->pending_calls == 0) {
1493 TnyIterator *iter_all_folders;
1494 TnyFolder *inbox = NULL;
1496 iter_all_folders = tny_list_create_iterator (info->folders);
1498 /* Do a poke status over all folders */
1499 while (!tny_iterator_is_done (iter_all_folders) &&
1500 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1501 TnyFolder *folder = NULL;
1503 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1505 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1506 /* Get a reference to the INBOX */
1507 inbox = g_object_ref (folder);
1509 /* Issue a poke status over the folder */
1511 tny_folder_poke_status (folder);
1514 /* Free and go to next */
1515 g_object_unref (folder);
1516 tny_iterator_next (iter_all_folders);
1518 g_object_unref (iter_all_folders);
1520 /* Refresh the INBOX */
1522 /* Refresh the folder. Our observer receives
1523 * the new emails during folder refreshes, so
1524 * we can use observer->new_headers
1526 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1527 tny_folder_add_observer (inbox, info->inbox_observer);
1529 /* Refresh the INBOX */
1530 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1531 g_object_unref (inbox);
1533 /* We could not perform the inbox refresh but
1534 we'll try to send mails anyway */
1535 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1541 modest_mail_operation_update_account (ModestMailOperation *self,
1542 const gchar *account_name,
1544 RetrieveAllCallback retrieve_all_cb,
1545 UpdateAccountCallback callback,
1548 UpdateAccountInfo *info = NULL;
1549 ModestMailOperationPrivate *priv = NULL;
1550 ModestTnyAccountStore *account_store = NULL;
1551 TnyStoreAccount *store_account = NULL;
1554 /* Init mail operation */
1555 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1558 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1559 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1561 /* Get the store account */
1562 account_store = modest_runtime_get_account_store ();
1563 store_account = (TnyStoreAccount *)
1564 modest_tny_account_store_get_server_account (account_store,
1566 TNY_ACCOUNT_TYPE_STORE);
1567 priv->account = g_object_ref (store_account);
1569 /* Create the helper object */
1570 info = g_slice_new0 (UpdateAccountInfo);
1571 info->pending_calls = 1;
1572 info->folders = tny_simple_list_new ();
1573 info->mail_op = g_object_ref (self);
1574 info->poke_all = poke_all;
1575 info->account_name = g_strdup (account_name);
1576 info->callback = callback;
1577 info->user_data = user_data;
1578 info->retrieve_all_cb = retrieve_all_cb;
1580 /* Set account busy */
1581 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1582 modest_mail_operation_notify_start (self);
1584 /* notify about the start of the operation */
1585 ModestMailOperationState *state;
1586 state = modest_mail_operation_clone_state (self);
1590 /* Start notifying progress */
1591 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
1593 g_slice_free (ModestMailOperationState, state);
1595 /* Get all folders and continue in the callback */
1596 folders = tny_simple_list_new ();
1597 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1599 recurse_folders_async_cb,
1604 * Used to notify the queue from the main
1605 * loop. We call it inside an idle call to achieve that
1608 idle_notify_queue (gpointer data)
1610 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1612 gdk_threads_enter ();
1613 modest_mail_operation_notify_end (mail_op);
1614 gdk_threads_leave ();
1615 g_object_unref (mail_op);
1621 compare_headers_by_date (gconstpointer a,
1624 TnyHeader **header1, **header2;
1625 time_t sent1, sent2;
1627 header1 = (TnyHeader **) a;
1628 header2 = (TnyHeader **) b;
1630 sent1 = tny_header_get_date_sent (*header1);
1631 sent2 = tny_header_get_date_sent (*header2);
1633 /* We want the most recent ones (greater time_t) at the
1642 /* ******************************************************************* */
1643 /* ************************** STORE ACTIONS ************************* */
1644 /* ******************************************************************* */
1647 ModestMailOperation *mail_op;
1648 CreateFolderUserCallback callback;
1654 create_folder_cb (TnyFolderStore *parent_folder,
1656 TnyFolder *new_folder,
1660 ModestMailOperationPrivate *priv;
1661 CreateFolderInfo *info;
1663 info = (CreateFolderInfo *) user_data;
1664 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1666 if (canceled || err) {
1667 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1669 priv->error = g_error_copy (err);
1671 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1672 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1675 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1678 /* The user will unref the new_folder */
1680 info->callback (info->mail_op, parent_folder,
1681 new_folder, info->user_data);
1683 /* Notify about operation end */
1684 modest_mail_operation_notify_end (info->mail_op);
1687 g_object_unref (info->mail_op);
1688 g_slice_free (CreateFolderInfo, info);
1692 modest_mail_operation_create_folder (ModestMailOperation *self,
1693 TnyFolderStore *parent,
1695 CreateFolderUserCallback callback,
1698 ModestMailOperationPrivate *priv;
1700 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1701 g_return_if_fail (name);
1703 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1704 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1705 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1706 g_object_ref (parent) :
1707 modest_tny_folder_get_account (TNY_FOLDER (parent));
1709 /* Check for already existing folder */
1710 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1711 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1712 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1713 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1714 _CS("ckdg_ib_folder_already_exists"));
1718 if (TNY_IS_FOLDER (parent)) {
1719 /* Check folder rules */
1720 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1721 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1722 /* Set status failed and set an error */
1723 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1724 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1725 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1726 _("mail_in_ui_folder_create_error"));
1730 if (!strcmp (name, " ") || strchr (name, '/')) {
1731 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1732 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1733 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1734 _("mail_in_ui_folder_create_error"));
1738 CreateFolderInfo *info;
1740 info = g_slice_new0 (CreateFolderInfo);
1741 info->mail_op = g_object_ref (self);
1742 info->callback = callback;
1743 info->user_data = user_data;
1745 modest_mail_operation_notify_start (self);
1747 /* Create the folder */
1748 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1751 /* Call the user callback anyway */
1753 callback (self, parent, NULL, user_data);
1754 /* Notify about operation end */
1755 modest_mail_operation_notify_end (self);
1760 modest_mail_operation_remove_folder (ModestMailOperation *self,
1762 gboolean remove_to_trash)
1764 TnyAccount *account;
1765 ModestMailOperationPrivate *priv;
1766 ModestTnyFolderRules rules;
1768 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1769 g_return_if_fail (TNY_IS_FOLDER (folder));
1771 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1773 /* Check folder rules */
1774 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1775 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1776 /* Set status failed and set an error */
1777 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1778 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1779 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1780 _("mail_in_ui_folder_delete_error"));
1784 /* Get the account */
1785 account = modest_tny_folder_get_account (folder);
1786 priv->account = g_object_ref(account);
1787 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1789 /* Delete folder or move to trash */
1790 if (remove_to_trash) {
1791 TnyFolder *trash_folder = NULL;
1792 trash_folder = modest_tny_account_get_special_folder (account,
1793 TNY_FOLDER_TYPE_TRASH);
1794 /* TODO: error_handling */
1796 modest_mail_operation_notify_start (self);
1797 modest_mail_operation_xfer_folder (self, folder,
1798 TNY_FOLDER_STORE (trash_folder),
1800 g_object_unref (trash_folder);
1802 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1805 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1807 modest_mail_operation_notify_start (self);
1808 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1809 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1812 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1814 g_object_unref (parent);
1816 g_warning ("%s: could not get parent folder", __FUNCTION__);
1818 g_object_unref (G_OBJECT (account));
1821 /* Notify about operation end */
1822 modest_mail_operation_notify_end (self);
1826 transfer_folder_status_cb (GObject *obj,
1830 ModestMailOperation *self;
1831 ModestMailOperationPrivate *priv;
1832 ModestMailOperationState *state;
1833 XFerFolderAsyncHelper *helper;
1835 g_return_if_fail (status != NULL);
1836 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1838 helper = (XFerFolderAsyncHelper *) user_data;
1839 g_return_if_fail (helper != NULL);
1841 self = helper->mail_op;
1842 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1844 priv->done = status->position;
1845 priv->total = status->of_total;
1847 state = modest_mail_operation_clone_state (self);
1849 /* This is not a GDK lock because we are a Tinymail callback
1850 * which is already GDK locked by Tinymail */
1852 /* no gdk_threads_enter (), CHECKED */
1854 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1856 /* no gdk_threads_leave (), CHECKED */
1858 g_slice_free (ModestMailOperationState, state);
1863 transfer_folder_cb (TnyFolder *folder,
1865 TnyFolderStore *into,
1866 TnyFolder *new_folder,
1870 XFerFolderAsyncHelper *helper;
1871 ModestMailOperation *self = NULL;
1872 ModestMailOperationPrivate *priv = NULL;
1874 helper = (XFerFolderAsyncHelper *) user_data;
1875 g_return_if_fail (helper != NULL);
1877 self = helper->mail_op;
1878 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1881 priv->error = g_error_copy (err);
1883 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1884 } else if (cancelled) {
1885 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1886 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1887 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1888 _("Transference of %s was cancelled."),
1889 tny_folder_get_name (folder));
1892 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1895 /* Notify about operation end */
1896 modest_mail_operation_notify_end (self);
1898 /* If user defined callback function was defined, call it */
1899 if (helper->user_callback) {
1901 /* This is not a GDK lock because we are a Tinymail callback
1902 * which is already GDK locked by Tinymail */
1904 /* no gdk_threads_enter (), CHECKED */
1905 helper->user_callback (self, new_folder, helper->user_data);
1906 /* no gdk_threads_leave () , CHECKED */
1910 g_object_unref (helper->mail_op);
1911 g_slice_free (XFerFolderAsyncHelper, helper);
1916 * This function checks if the new name is a valid name for our local
1917 * folders account. The new name could not be the same than then name
1918 * of any of the mandatory local folders
1920 * We can not rely on tinymail because tinymail does not check the
1921 * name of the virtual folders that the account could have in the case
1922 * that we're doing a rename (because it directly calls Camel which
1923 * knows nothing about our virtual folders).
1925 * In the case of an actual copy/move (i.e. move/copy a folder between
1926 * accounts) tinymail uses the tny_folder_store_create_account which
1927 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1928 * checks the new name of the folder, so this call in that case
1929 * wouldn't be needed. *But* NOTE that if tinymail changes its
1930 * implementation (if folder transfers within the same account is no
1931 * longer implemented as a rename) this call will allow Modest to work
1934 * If the new name is not valid, this function will set the status to
1935 * failed and will set also an error in the mail operation
1938 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1939 TnyFolderStore *into,
1940 const gchar *new_name)
1942 if (TNY_IS_ACCOUNT (into) &&
1943 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1944 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1946 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1947 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1948 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1949 _CS("ckdg_ib_folder_already_exists"));
1956 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1958 TnyFolderStore *parent,
1959 gboolean delete_original,
1960 XferFolderAsyncUserCallback user_callback,
1963 ModestMailOperationPrivate *priv = NULL;
1964 ModestTnyFolderRules parent_rules = 0, rules;
1965 XFerFolderAsyncHelper *helper = NULL;
1966 const gchar *folder_name = NULL;
1967 const gchar *error_msg;
1969 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1970 g_return_if_fail (TNY_IS_FOLDER (folder));
1971 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1973 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1974 folder_name = tny_folder_get_name (folder);
1976 /* Set the error msg */
1977 error_msg = _("mail_in_ui_folder_move_target_error");
1979 /* Get account and set it into mail_operation */
1980 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1981 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1982 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1984 /* Get folder rules */
1985 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1986 if (TNY_IS_FOLDER (parent))
1987 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1989 /* Apply operation constraints */
1990 if ((gpointer) parent == (gpointer) folder ||
1991 (!TNY_IS_FOLDER_STORE (parent)) ||
1992 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1995 } else if (TNY_IS_FOLDER (parent) &&
1996 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2000 } else if (TNY_IS_FOLDER (parent) &&
2001 TNY_IS_FOLDER_STORE (folder) &&
2002 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2003 TNY_FOLDER_STORE (folder))) {
2004 /* Do not move a parent into a child */
2006 } else if (TNY_IS_FOLDER_STORE (parent) &&
2007 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2008 /* Check that the new folder name is not used by any
2011 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2012 /* Check that the new folder name is not used by any
2013 special local folder */
2016 /* Create the helper */
2017 helper = g_slice_new0 (XFerFolderAsyncHelper);
2018 helper->mail_op = g_object_ref (self);
2019 helper->user_callback = user_callback;
2020 helper->user_data = user_data;
2022 /* Move/Copy folder */
2023 modest_mail_operation_notify_start (self);
2024 tny_folder_copy_async (folder,
2026 tny_folder_get_name (folder),
2029 transfer_folder_status_cb,
2035 /* Set status failed and set an error */
2036 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2037 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2038 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2041 /* Call the user callback if exists */
2043 user_callback (self, NULL, user_data);
2045 /* Notify the queue */
2046 modest_mail_operation_notify_end (self);
2050 modest_mail_operation_rename_folder (ModestMailOperation *self,
2053 XferFolderAsyncUserCallback user_callback,
2056 ModestMailOperationPrivate *priv;
2057 ModestTnyFolderRules rules;
2058 XFerFolderAsyncHelper *helper;
2060 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2061 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2062 g_return_if_fail (name);
2064 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2066 /* Get account and set it into mail_operation */
2067 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2068 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2070 /* Check folder rules */
2071 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2072 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2074 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2077 TnyFolderStore *into;
2079 into = tny_folder_get_folder_store (folder);
2081 /* Check that the new folder name is not used by any
2082 special local folder */
2083 if (new_name_valid_if_local_account (priv, into, name)) {
2084 /* Create the helper */
2085 helper = g_slice_new0 (XFerFolderAsyncHelper);
2086 helper->mail_op = g_object_ref(self);
2087 helper->user_callback = user_callback;
2088 helper->user_data = user_data;
2090 /* Rename. Camel handles folder subscription/unsubscription */
2091 modest_mail_operation_notify_start (self);
2092 tny_folder_copy_async (folder, into, name, TRUE,
2094 transfer_folder_status_cb,
2099 g_object_unref (into);
2104 /* Set status failed and set an error */
2105 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2106 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2107 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2108 _("FIXME: unable to rename"));
2111 user_callback (self, NULL, user_data);
2113 /* Notify about operation end */
2114 modest_mail_operation_notify_end (self);
2117 /* ******************************************************************* */
2118 /* ************************** MSG ACTIONS ************************* */
2119 /* ******************************************************************* */
2122 modest_mail_operation_get_msg (ModestMailOperation *self,
2124 GetMsgAsyncUserCallback user_callback,
2127 GetMsgInfo *helper = NULL;
2129 ModestMailOperationPrivate *priv;
2131 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2132 g_return_if_fail (TNY_IS_HEADER (header));
2134 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2135 folder = tny_header_get_folder (header);
2137 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2141 /* Get account and set it into mail_operation */
2142 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2144 /* Check for cached messages */
2145 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2146 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2148 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2150 /* Create the helper */
2151 helper = g_slice_new0 (GetMsgInfo);
2152 helper->header = g_object_ref (header);
2153 helper->mail_op = g_object_ref (self);
2154 helper->user_callback = user_callback;
2155 helper->user_data = user_data;
2156 helper->destroy_notify = NULL;
2157 helper->last_total_bytes = 0;
2158 helper->sum_total_bytes = 0;
2159 helper->total_bytes = tny_header_get_message_size (header);
2161 modest_mail_operation_notify_start (self);
2163 /* notify about the start of the operation */
2164 ModestMailOperationState *state;
2165 state = modest_mail_operation_clone_state (self);
2168 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2171 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2173 g_object_unref (G_OBJECT (folder));
2177 get_msg_status_cb (GObject *obj,
2181 GetMsgInfo *helper = NULL;
2183 g_return_if_fail (status != NULL);
2184 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2186 helper = (GetMsgInfo *) user_data;
2187 g_return_if_fail (helper != NULL);
2189 /* Notify progress */
2190 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2191 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2195 get_msg_async_cb (TnyFolder *folder,
2201 GetMsgInfo *info = NULL;
2202 ModestMailOperationPrivate *priv = NULL;
2205 info = (GetMsgInfo *) user_data;
2207 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2209 finished = (priv->done == priv->total) ? TRUE : FALSE;
2212 if (canceled || err) {
2213 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2215 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2216 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2219 /* Set the success status before calling the user callback */
2220 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2221 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2225 /* Call the user callback */
2226 if (info->user_callback)
2227 info->user_callback (info->mail_op, info->header, canceled,
2228 msg, err, info->user_data);
2230 /* Notify about operation end if this is the last callback */
2232 /* Free user data */
2233 if (info->destroy_notify)
2234 info->destroy_notify (info->user_data);
2236 /* Notify about operation end */
2237 modest_mail_operation_notify_end (info->mail_op);
2241 g_object_unref (info->header);
2242 g_object_unref (info->mail_op);
2243 g_slice_free (GetMsgInfo, info);
2247 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2248 TnyList *header_list,
2249 GetMsgAsyncUserCallback user_callback,
2251 GDestroyNotify notify)
2253 ModestMailOperationPrivate *priv = NULL;
2255 TnyIterator *iter = NULL;
2257 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2259 /* Init mail operation */
2260 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2261 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2262 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2264 priv->total = tny_list_get_length(header_list);
2266 /* Get account and set it into mail_operation */
2267 if (tny_list_get_length (header_list) >= 1) {
2268 iter = tny_list_create_iterator (header_list);
2269 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2271 TnyFolder *folder = tny_header_get_folder (header);
2273 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2274 g_object_unref (folder);
2276 g_object_unref (header);
2279 if (tny_list_get_length (header_list) == 1) {
2280 g_object_unref (iter);
2285 msg_list_size = compute_message_list_size (header_list);
2287 modest_mail_operation_notify_start (self);
2288 iter = tny_list_create_iterator (header_list);
2289 while (!tny_iterator_is_done (iter)) {
2290 /* notify about the start of the operation */
2291 ModestMailOperationState *state;
2292 state = modest_mail_operation_clone_state (self);
2295 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2298 GetMsgInfo *msg_info = NULL;
2299 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2300 TnyFolder *folder = tny_header_get_folder (header);
2302 /* Create the message info */
2303 msg_info = g_slice_new0 (GetMsgInfo);
2304 msg_info->mail_op = g_object_ref (self);
2305 msg_info->header = g_object_ref (header);
2306 msg_info->user_callback = user_callback;
2307 msg_info->user_data = user_data;
2308 msg_info->destroy_notify = notify;
2309 msg_info->last_total_bytes = 0;
2310 msg_info->sum_total_bytes = 0;
2311 msg_info->total_bytes = msg_list_size;
2313 /* The callback will call it per each header */
2314 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2316 /* Free and go on */
2317 g_object_unref (header);
2318 g_object_unref (folder);
2319 tny_iterator_next (iter);
2321 g_object_unref (iter);
2326 modest_mail_operation_remove_msg (ModestMailOperation *self,
2328 gboolean remove_to_trash /*ignored*/)
2331 ModestMailOperationPrivate *priv;
2333 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2334 g_return_if_fail (TNY_IS_HEADER (header));
2336 if (remove_to_trash)
2337 g_warning ("remove to trash is not implemented");
2339 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2340 folder = tny_header_get_folder (header);
2342 /* Get account and set it into mail_operation */
2343 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2344 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2345 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2347 /* remove message from folder */
2348 tny_folder_remove_msg (folder, header, &(priv->error));
2350 gboolean expunge, leave_on_server;
2351 const gchar *account_name;
2352 TnyAccount *account;
2353 ModestTransportStoreProtocol account_proto;
2355 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2356 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2358 modest_mail_operation_notify_start (self);
2360 /* Get leave on server setting */
2361 account = tny_folder_get_account (folder);
2362 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2364 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2367 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2369 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2370 modest_tny_folder_is_remote_folder (folder) == FALSE)
2376 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2379 g_object_unref (account);
2385 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2387 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2390 g_object_unref (G_OBJECT (folder));
2392 /* Notify about operation end */
2393 modest_mail_operation_notify_end (self);
2397 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2399 gboolean remove_to_trash /*ignored*/)
2401 TnyFolder *folder = NULL;
2402 ModestMailOperationPrivate *priv;
2403 TnyIterator *iter = NULL;
2404 TnyHeader *header = NULL;
2405 TnyList *remove_headers = NULL;
2406 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2408 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2409 g_return_if_fail (TNY_IS_LIST (headers));
2411 if (remove_to_trash)
2412 g_warning ("remove to trash is not implemented");
2414 if (tny_list_get_length(headers) == 0) {
2415 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2416 goto cleanup; /* nothing to do */
2419 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2420 remove_headers = g_object_ref(headers);
2422 /* Get folder from first header and sync it */
2423 iter = tny_list_create_iterator (headers);
2424 header = TNY_HEADER (tny_iterator_get_current (iter));
2426 folder = tny_header_get_folder (header);
2427 if (!TNY_IS_FOLDER(folder)) {
2428 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2432 /* Don't remove messages that are being sent */
2433 if (modest_tny_folder_is_local_folder (folder)) {
2434 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2436 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2437 TnyTransportAccount *traccount = NULL;
2438 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2439 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2441 ModestTnySendQueueStatus status;
2442 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2443 TnyIterator *iter = tny_list_create_iterator(headers);
2444 g_object_unref(remove_headers);
2445 remove_headers = TNY_LIST(tny_simple_list_new());
2446 while (!tny_iterator_is_done(iter)) {
2448 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2449 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2450 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2451 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2452 tny_list_append(remove_headers, G_OBJECT(hdr));
2454 g_object_unref(hdr);
2456 tny_iterator_next(iter);
2458 g_object_unref(iter);
2459 g_object_unref(traccount);
2463 /* Get account and set it into mail_operation */
2464 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2465 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2466 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2468 /* remove message from folder */
2469 modest_mail_operation_notify_start (self);
2471 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2473 gboolean expunge, leave_on_server;
2474 const gchar *account_name;
2476 TnyAccount *account;
2477 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2479 account = tny_folder_get_account (folder);
2480 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2482 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2485 proto = tny_account_get_proto (account);
2487 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2490 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2491 modest_tny_folder_is_remote_folder (folder) == FALSE)
2497 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2499 g_object_unref (account);
2505 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2507 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2512 g_object_unref (remove_headers);
2514 g_object_unref (header);
2516 g_object_unref (iter);
2518 g_object_unref (folder);
2520 /* Notify about operation end */
2521 modest_mail_operation_notify_end (self);
2525 notify_progress_of_multiple_messages (ModestMailOperation *self,
2527 gint *last_total_bytes,
2528 gint *sum_total_bytes,
2530 gboolean increment_done)
2532 ModestMailOperationPrivate *priv;
2533 ModestMailOperationState *state;
2534 gboolean is_num_bytes = FALSE;
2536 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2538 /* We know that tinymail sends us information about
2539 * transferred bytes with this particular message
2541 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2542 * I just added the 'if' so we don't get runtime warning)
2544 if (status->message)
2545 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2547 state = modest_mail_operation_clone_state (self);
2548 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2549 /* We know that we're in a different message when the
2550 total number of bytes to transfer is different. Of
2551 course it could fail if we're transferring messages
2552 of the same size, but this is a workarround */
2553 if (status->of_total != *last_total_bytes) {
2554 /* We need to increment the done when there is
2555 no information about each individual
2556 message, we need to do this in message
2557 transfers, and we don't do it for getting
2561 *sum_total_bytes += *last_total_bytes;
2562 *last_total_bytes = status->of_total;
2564 state->bytes_done += status->position + *sum_total_bytes;
2565 state->bytes_total = total_bytes;
2567 /* Notify the status change. Only notify about changes
2568 referred to bytes */
2569 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2573 g_slice_free (ModestMailOperationState, state);
2577 transfer_msgs_status_cb (GObject *obj,
2581 XFerMsgsAsyncHelper *helper;
2583 g_return_if_fail (status != NULL);
2584 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2586 helper = (XFerMsgsAsyncHelper *) user_data;
2587 g_return_if_fail (helper != NULL);
2589 /* Notify progress */
2590 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2591 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2596 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2598 XFerMsgsAsyncHelper *helper;
2599 ModestMailOperation *self;
2600 ModestMailOperationPrivate *priv;
2601 TnyIterator *iter = NULL;
2602 TnyHeader *header = NULL;
2604 helper = (XFerMsgsAsyncHelper *) user_data;
2605 self = helper->mail_op;
2607 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2610 priv->error = g_error_copy (err);
2612 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2613 } else if (cancelled) {
2614 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2615 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2616 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2617 _("Error trying to refresh the contents of %s"),
2618 tny_folder_get_name (folder));
2621 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2623 /* Update folder counts */
2624 tny_folder_poke_status (folder);
2625 tny_folder_poke_status (helper->dest_folder);
2629 /* Mark headers as deleted and seen */
2630 if ((helper->delete) &&
2631 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2632 iter = tny_list_create_iterator (helper->headers);
2633 while (!tny_iterator_is_done (iter)) {
2634 header = TNY_HEADER (tny_iterator_get_current (iter));
2635 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2636 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2637 g_object_unref (header);
2639 tny_iterator_next (iter);
2644 /* Notify about operation end */
2645 modest_mail_operation_notify_end (self);
2647 /* If user defined callback function was defined, call it */
2648 if (helper->user_callback) {
2649 /* This is not a GDK lock because we are a Tinymail callback and
2650 * Tinymail already acquires the Gdk lock */
2652 /* no gdk_threads_enter (), CHECKED */
2653 helper->user_callback (self, helper->user_data);
2654 /* no gdk_threads_leave (), CHECKED */
2658 if (helper->headers)
2659 g_object_unref (helper->headers);
2660 if (helper->dest_folder)
2661 g_object_unref (helper->dest_folder);
2662 if (helper->mail_op)
2663 g_object_unref (helper->mail_op);
2665 g_object_unref (folder);
2667 g_object_unref (iter);
2668 g_slice_free (XFerMsgsAsyncHelper, helper);
2672 compute_message_list_size (TnyList *headers)
2677 iter = tny_list_create_iterator (headers);
2678 while (!tny_iterator_is_done (iter)) {
2679 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2680 size += tny_header_get_message_size (header);
2681 g_object_unref (header);
2682 tny_iterator_next (iter);
2684 g_object_unref (iter);
2690 compute_message_array_size (GPtrArray *headers)
2695 for (i = 0; i < headers->len; i++) {
2696 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2697 size += tny_header_get_message_size (header);
2705 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2708 gboolean delete_original,
2709 XferMsgsAsyncUserCallback user_callback,
2712 ModestMailOperationPrivate *priv = NULL;
2713 TnyIterator *iter = NULL;
2714 TnyFolder *src_folder = NULL;
2715 XFerMsgsAsyncHelper *helper = NULL;
2716 TnyHeader *header = NULL;
2717 ModestTnyFolderRules rules = 0;
2719 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2720 g_return_if_fail (headers && TNY_IS_LIST (headers));
2721 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2723 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2724 priv->total = tny_list_get_length (headers);
2726 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2727 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2729 /* Apply folder rules */
2730 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2731 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2732 /* Set status failed and set an error */
2733 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2734 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2735 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2736 _CS("ckct_ib_unable_to_paste_here"));
2737 /* Notify the queue */
2738 modest_mail_operation_notify_end (self);
2742 /* Get source folder */
2743 iter = tny_list_create_iterator (headers);
2744 header = TNY_HEADER (tny_iterator_get_current (iter));
2746 src_folder = tny_header_get_folder (header);
2747 g_object_unref (header);
2749 g_object_unref (iter);
2751 if (src_folder == NULL) {
2752 /* Notify the queue */
2753 modest_mail_operation_notify_end (self);
2755 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2760 /* Check folder source and destination */
2761 if (src_folder == folder) {
2762 /* Set status failed and set an error */
2763 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2764 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2765 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2766 _("mail_in_ui_folder_copy_target_error"));
2768 /* Notify the queue */
2769 modest_mail_operation_notify_end (self);
2772 g_object_unref (src_folder);
2776 /* Create the helper */
2777 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2778 helper->mail_op = g_object_ref(self);
2779 helper->dest_folder = g_object_ref(folder);
2780 helper->headers = g_object_ref(headers);
2781 helper->user_callback = user_callback;
2782 helper->user_data = user_data;
2783 helper->delete = delete_original;
2784 helper->last_total_bytes = 0;
2785 helper->sum_total_bytes = 0;
2786 helper->total_bytes = compute_message_list_size (headers);
2788 /* Get account and set it into mail_operation */
2789 priv->account = modest_tny_folder_get_account (src_folder);
2791 /* Transfer messages */
2792 modest_mail_operation_notify_start (self);
2793 tny_folder_transfer_msgs_async (src_folder,
2798 transfer_msgs_status_cb,
2804 on_refresh_folder (TnyFolder *folder,
2809 RefreshAsyncHelper *helper = NULL;
2810 ModestMailOperation *self = NULL;
2811 ModestMailOperationPrivate *priv = NULL;
2813 helper = (RefreshAsyncHelper *) user_data;
2814 self = helper->mail_op;
2815 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2817 g_return_if_fail(priv!=NULL);
2820 priv->error = g_error_copy (error);
2821 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2826 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2827 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2828 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2829 _("Error trying to refresh the contents of %s"),
2830 tny_folder_get_name (folder));
2834 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2837 /* Call user defined callback, if it exists */
2838 if (helper->user_callback) {
2840 /* This is not a GDK lock because we are a Tinymail callback and
2841 * Tinymail already acquires the Gdk lock */
2842 helper->user_callback (self, folder, helper->user_data);
2846 g_slice_free (RefreshAsyncHelper, helper);
2848 /* Notify about operation end */
2849 modest_mail_operation_notify_end (self);
2850 g_object_unref(self);
2854 on_refresh_folder_status_update (GObject *obj,
2858 RefreshAsyncHelper *helper = NULL;
2859 ModestMailOperation *self = NULL;
2860 ModestMailOperationPrivate *priv = NULL;
2861 ModestMailOperationState *state;
2863 g_return_if_fail (user_data != NULL);
2864 g_return_if_fail (status != NULL);
2865 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2867 helper = (RefreshAsyncHelper *) user_data;
2868 self = helper->mail_op;
2869 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2871 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2873 priv->done = status->position;
2874 priv->total = status->of_total;
2876 state = modest_mail_operation_clone_state (self);
2878 /* This is not a GDK lock because we are a Tinymail callback and
2879 * Tinymail already acquires the Gdk lock */
2880 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2882 g_slice_free (ModestMailOperationState, state);
2886 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2888 RefreshAsyncUserCallback user_callback,
2891 ModestMailOperationPrivate *priv = NULL;
2892 RefreshAsyncHelper *helper = NULL;
2894 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2896 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2898 /* Get account and set it into mail_operation */
2899 priv->account = modest_tny_folder_get_account (folder);
2900 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2902 /* Create the helper */
2903 helper = g_slice_new0 (RefreshAsyncHelper);
2904 helper->mail_op = g_object_ref(self);
2905 helper->user_callback = user_callback;
2906 helper->user_data = user_data;
2908 /* Refresh the folder. TODO: tinymail could issue a status
2909 updates before the callback call then this could happen. We
2910 must review the design */
2911 modest_mail_operation_notify_start (self);
2913 /* notify that the operation was started */
2914 ModestMailOperationState *state;
2915 state = modest_mail_operation_clone_state (self);
2918 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2921 tny_folder_refresh_async (folder,
2923 on_refresh_folder_status_update,
2929 modest_mail_operation_notify_start (ModestMailOperation *self)
2931 ModestMailOperationPrivate *priv = NULL;
2933 g_return_if_fail (self);
2935 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2937 /* Ensure that all the fields are filled correctly */
2938 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2940 /* Notify the observers about the mail operation. We do not
2941 wrapp this emission because we assume that this function is
2942 always called from within the main lock */
2943 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2948 * It's used by the mail operation queue to notify the observers
2949 * attached to that signal that the operation finished. We need to use
2950 * that because tinymail does not give us the progress of a given
2951 * operation when it finishes (it directly calls the operation
2955 modest_mail_operation_notify_end (ModestMailOperation *self)
2957 ModestMailOperationPrivate *priv = NULL;
2959 g_return_if_fail (self);
2961 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2963 /* Notify the observers about the mail operation end. We do
2964 not wrapp this emission because we assume that this
2965 function is always called from within the main lock */
2966 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2968 /* Remove the error user data */
2969 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2970 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2974 modest_mail_operation_get_account (ModestMailOperation *self)
2976 ModestMailOperationPrivate *priv = NULL;
2978 g_return_val_if_fail (self, NULL);
2980 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2982 return (priv->account) ? g_object_ref (priv->account) : NULL;
2986 modest_mail_operation_noop (ModestMailOperation *self)
2988 ModestMailOperationPrivate *priv = NULL;
2990 g_return_if_fail (self);
2992 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2993 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2994 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2998 /* This mail operation does nothing actually */
2999 modest_mail_operation_notify_start (self);
3000 modest_mail_operation_notify_end (self);
3005 modest_mail_operation_to_string (ModestMailOperation *self)
3007 const gchar *type, *status, *account_id;
3008 ModestMailOperationPrivate *priv = NULL;
3010 g_return_val_if_fail (self, NULL);
3012 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3014 /* new operations don't have anything interesting */
3015 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3016 return g_strdup_printf ("%p <new operation>", self);
3018 switch (priv->op_type) {
3019 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3020 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3021 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3022 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3023 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3024 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3025 default: type = "UNEXPECTED"; break;
3028 switch (priv->status) {
3029 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3030 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3031 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3032 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3033 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3034 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3035 default: status= "UNEXPECTED"; break;
3038 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3040 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3041 priv->done, priv->total,
3042 priv->error && priv->error->message ? priv->error->message : "");