1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <tny-mime-part.h>
33 #include <tny-store-account.h>
34 #include <tny-folder-store.h>
35 #include <tny-folder-store-query.h>
36 #include <tny-camel-stream.h>
37 #include <tny-camel-pop-store-account.h>
38 #include <tny-camel-pop-folder.h>
39 #include <tny-camel-imap-folder.h>
40 #include <tny-camel-mem-stream.h>
41 #include <tny-simple-list.h>
42 #include <tny-send-queue.h>
43 #include <tny-status.h>
44 #include <tny-folder-observer.h>
45 #include <camel/camel-stream-mem.h>
46 #include <glib/gi18n.h>
47 #include "modest-platform.h"
48 #include "modest-account-mgr-helpers.h"
49 #include <modest-tny-account.h>
50 #include <modest-tny-send-queue.h>
51 #include <modest-runtime.h>
52 #include "modest-text-utils.h"
53 #include "modest-tny-msg.h"
54 #include "modest-tny-folder.h"
55 #include "modest-tny-account-store.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-marshal.h"
58 #include "modest-error.h"
59 #include "modest-mail-operation.h"
64 * Remove all these #ifdef stuff when the tinymail's idle calls become
67 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
69 /* 'private'/'protected' functions */
70 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
71 static void modest_mail_operation_init (ModestMailOperation *obj);
72 static void modest_mail_operation_finalize (GObject *obj);
74 static void get_msg_async_cb (TnyFolder *folder,
80 static void get_msg_status_cb (GObject *obj,
84 static void modest_mail_operation_notify_start (ModestMailOperation *self);
85 static void modest_mail_operation_notify_end (ModestMailOperation *self);
87 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
89 gint *last_total_bytes,
90 gint *sum_total_bytes,
92 gboolean increment_done);
94 static guint compute_message_list_size (TnyList *headers);
96 static guint compute_message_array_size (GPtrArray *headers);
98 static int compare_headers_by_date (gconstpointer a,
101 enum _ModestMailOperationSignals
103 PROGRESS_CHANGED_SIGNAL,
104 OPERATION_STARTED_SIGNAL,
105 OPERATION_FINISHED_SIGNAL,
109 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
110 struct _ModestMailOperationPrivate {
116 ErrorCheckingUserCallback error_checking;
117 gpointer error_checking_user_data;
118 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
119 ModestMailOperationStatus status;
120 ModestMailOperationTypeOperation op_type;
123 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
124 MODEST_TYPE_MAIL_OPERATION, \
125 ModestMailOperationPrivate))
127 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
128 priv->status = new_status;\
133 GetMsgAsyncUserCallback user_callback;
136 ModestMailOperation *mail_op;
137 GDestroyNotify destroy_notify;
138 gint last_total_bytes;
139 gint sum_total_bytes;
144 ModestMailOperation *mail_op;
146 gulong msg_sent_handler;
147 gulong error_happened_handler;
150 static void send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
151 guint nth, guint total, gpointer userdata);
152 static void send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
153 GError *error, gpointer userdata);
154 static void common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
157 typedef struct _RefreshAsyncHelper {
158 ModestMailOperation *mail_op;
159 RefreshAsyncUserCallback user_callback;
161 } RefreshAsyncHelper;
163 typedef struct _XFerMsgAsyncHelper
165 ModestMailOperation *mail_op;
167 TnyFolder *dest_folder;
168 XferAsyncUserCallback user_callback;
171 gint last_total_bytes;
172 gint sum_total_bytes;
174 } XFerMsgAsyncHelper;
176 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
180 static void modest_mail_operation_create_msg (ModestMailOperation *self,
181 const gchar *from, const gchar *to,
182 const gchar *cc, const gchar *bcc,
183 const gchar *subject, const gchar *plain_body,
184 const gchar *html_body, const GList *attachments_list,
185 const GList *images_list,
186 TnyHeaderFlags priority_flags,
187 ModestMailOperationCreateMsgCallback callback,
190 static gboolean idle_notify_queue (gpointer data);
193 ModestMailOperation *mail_op;
201 GList *attachments_list;
203 TnyHeaderFlags priority_flags;
204 ModestMailOperationCreateMsgCallback callback;
210 ModestMailOperation *mail_op;
212 ModestMailOperationCreateMsgCallback callback;
217 static GObjectClass *parent_class = NULL;
219 static guint signals[NUM_SIGNALS] = {0};
222 modest_mail_operation_get_type (void)
224 static GType my_type = 0;
226 static const GTypeInfo my_info = {
227 sizeof(ModestMailOperationClass),
228 NULL, /* base init */
229 NULL, /* base finalize */
230 (GClassInitFunc) modest_mail_operation_class_init,
231 NULL, /* class finalize */
232 NULL, /* class data */
233 sizeof(ModestMailOperation),
235 (GInstanceInitFunc) modest_mail_operation_init,
238 my_type = g_type_register_static (G_TYPE_OBJECT,
239 "ModestMailOperation",
246 modest_mail_operation_class_init (ModestMailOperationClass *klass)
248 GObjectClass *gobject_class;
249 gobject_class = (GObjectClass*) klass;
251 parent_class = g_type_class_peek_parent (klass);
252 gobject_class->finalize = modest_mail_operation_finalize;
254 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
257 * ModestMailOperation::progress-changed
258 * @self: the #MailOperation that emits the signal
259 * @user_data: user data set when the signal handler was connected
261 * Emitted when the progress of a mail operation changes
263 signals[PROGRESS_CHANGED_SIGNAL] =
264 g_signal_new ("progress-changed",
265 G_TYPE_FROM_CLASS (gobject_class),
267 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
269 g_cclosure_marshal_VOID__POINTER,
270 G_TYPE_NONE, 1, G_TYPE_POINTER);
274 * This signal is issued whenever a mail operation starts, and
275 * starts mean when the tinymail operation is issued. This
276 * means that it could happen that something wrong happens and
277 * the tinymail function is never called. In this situation a
278 * operation-finished will be issued without any
281 signals[OPERATION_STARTED_SIGNAL] =
282 g_signal_new ("operation-started",
283 G_TYPE_FROM_CLASS (gobject_class),
285 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
287 g_cclosure_marshal_VOID__VOID,
292 * This signal is issued whenever a mail operation
293 * finishes. Note that this signal could be issued without any
294 * previous "operation-started" signal, because this last one
295 * is only issued when the tinymail operation is successfully
298 signals[OPERATION_FINISHED_SIGNAL] =
299 g_signal_new ("operation-finished",
300 G_TYPE_FROM_CLASS (gobject_class),
302 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
304 g_cclosure_marshal_VOID__VOID,
309 modest_mail_operation_init (ModestMailOperation *obj)
311 ModestMailOperationPrivate *priv;
313 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
315 priv->account = NULL;
316 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
317 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
322 priv->error_checking = NULL;
323 priv->error_checking_user_data = NULL;
327 modest_mail_operation_finalize (GObject *obj)
329 ModestMailOperationPrivate *priv;
331 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
336 g_error_free (priv->error);
340 g_object_unref (priv->source);
344 g_object_unref (priv->account);
345 priv->account = NULL;
349 G_OBJECT_CLASS(parent_class)->finalize (obj);
353 modest_mail_operation_new (GObject *source)
355 ModestMailOperation *obj;
356 ModestMailOperationPrivate *priv;
358 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
359 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
362 priv->source = g_object_ref(source);
368 modest_mail_operation_new_with_error_handling (GObject *source,
369 ErrorCheckingUserCallback error_handler,
371 ErrorCheckingUserDataDestroyer error_handler_destroyer)
373 ModestMailOperation *obj;
374 ModestMailOperationPrivate *priv;
376 obj = modest_mail_operation_new (source);
377 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
379 g_return_val_if_fail (error_handler != NULL, obj);
380 priv->error_checking = error_handler;
381 priv->error_checking_user_data = user_data;
382 priv->error_checking_user_data_destroyer = error_handler_destroyer;
388 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
390 ModestMailOperationPrivate *priv;
392 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
394 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
395 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
397 /* Call the user callback */
398 if (priv->error_checking != NULL)
399 priv->error_checking (self, priv->error_checking_user_data);
403 ModestMailOperationTypeOperation
404 modest_mail_operation_get_type_operation (ModestMailOperation *self)
406 ModestMailOperationPrivate *priv;
408 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
409 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
411 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
413 return priv->op_type;
417 modest_mail_operation_is_mine (ModestMailOperation *self,
420 ModestMailOperationPrivate *priv;
422 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
425 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
426 if (priv->source == NULL) return FALSE;
428 return priv->source == me;
432 modest_mail_operation_get_source (ModestMailOperation *self)
434 ModestMailOperationPrivate *priv;
436 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
439 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
441 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
445 return (priv->source) ? g_object_ref (priv->source) : NULL;
448 ModestMailOperationStatus
449 modest_mail_operation_get_status (ModestMailOperation *self)
451 ModestMailOperationPrivate *priv;
453 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
454 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
455 MODEST_MAIL_OPERATION_STATUS_INVALID);
457 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
459 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
460 return MODEST_MAIL_OPERATION_STATUS_INVALID;
467 modest_mail_operation_get_error (ModestMailOperation *self)
469 ModestMailOperationPrivate *priv;
471 g_return_val_if_fail (self, NULL);
472 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
474 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
477 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
485 modest_mail_operation_cancel (ModestMailOperation *self)
487 ModestMailOperationPrivate *priv;
488 gboolean canceled = FALSE;
490 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
492 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
494 /* Note that if we call cancel with an already canceled mail
495 operation the progress changed signal won't be emitted */
496 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
500 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
502 /* Cancel the mail operation. We need to wrap it between this
503 start/stop operations to allow following calls to the
505 g_return_val_if_fail (priv->account, FALSE);
507 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
508 ModestTnySendQueue *queue;
509 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
510 /* Cancel sending without removing the item */
511 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), FALSE, NULL);
513 /* Cancel operation */
514 tny_account_cancel (priv->account);
521 modest_mail_operation_get_task_done (ModestMailOperation *self)
523 ModestMailOperationPrivate *priv;
525 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
528 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
533 modest_mail_operation_get_task_total (ModestMailOperation *self)
535 ModestMailOperationPrivate *priv;
537 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
540 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
545 modest_mail_operation_is_finished (ModestMailOperation *self)
547 ModestMailOperationPrivate *priv;
548 gboolean retval = FALSE;
550 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
553 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
555 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
556 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
557 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
558 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
568 * Creates an image of the current state of a mail operation, the
569 * caller must free it
571 static ModestMailOperationState *
572 modest_mail_operation_clone_state (ModestMailOperation *self)
574 ModestMailOperationState *state;
575 ModestMailOperationPrivate *priv;
577 /* FIXME: this should be fixed properly
579 * in some cases, priv was NULL, so checking here to
582 g_return_val_if_fail (self, NULL);
583 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
584 g_return_val_if_fail (priv, NULL);
589 state = g_slice_new (ModestMailOperationState);
591 state->status = priv->status;
592 state->op_type = priv->op_type;
593 state->done = priv->done;
594 state->total = priv->total;
595 state->finished = modest_mail_operation_is_finished (self);
596 state->bytes_done = 0;
597 state->bytes_total = 0;
602 /* ******************************************************************* */
603 /* ************************** SEND ACTIONS ************************* */
604 /* ******************************************************************* */
607 modest_mail_operation_send_mail (ModestMailOperation *self,
608 TnyTransportAccount *transport_account,
611 TnySendQueue *send_queue = NULL;
612 ModestMailOperationPrivate *priv;
615 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
616 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
617 g_return_if_fail (msg && TNY_IS_MSG (msg));
619 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
621 /* Get account and set it into mail_operation */
622 priv->account = g_object_ref (transport_account);
623 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
627 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
628 if (!TNY_IS_SEND_QUEUE(send_queue)) {
629 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
630 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
631 "modest: could not find send queue for account\n");
632 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
633 modest_mail_operation_notify_end (self);
636 /* Add the msg to the queue */
637 modest_mail_operation_notify_start (self);
639 info = g_slice_new0 (SendMsgInfo);
641 info->mail_op = g_object_ref (self);
642 info->msg = g_object_ref (msg);
643 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
644 G_CALLBACK (send_mail_msg_sent_handler), info);
645 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
646 G_CALLBACK (send_mail_error_happened_handler), info);
648 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
652 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
658 common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
661 g_signal_handler_disconnect (queue, info->msg_sent_handler);
662 g_signal_handler_disconnect (queue, info->error_happened_handler);
664 g_object_unref (info->msg);
665 modest_mail_operation_notify_end (info->mail_op);
666 g_object_unref (info->mail_op);
668 g_slice_free (SendMsgInfo, info);
672 send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
673 guint nth, guint total, gpointer userdata)
675 SendMsgInfo *info = (SendMsgInfo *) userdata;
676 TnyHeader *hdr1, *hdr2;
677 const char *msgid1, *msgid2;
678 hdr1 = tny_msg_get_header(msg);
679 hdr2 = tny_msg_get_header(info->msg);
680 msgid1 = tny_header_get_message_id(hdr1);
681 msgid2 = tny_header_get_message_id(hdr2);
682 if (msgid1 == NULL) msgid1 = "(null)";
683 if (msgid2 == NULL) msgid2 = "(null)";
685 if (!strcmp (msgid1, msgid2)) {
686 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
687 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
689 common_send_mail_operation_end (queue, msg, info);
691 g_object_unref(G_OBJECT(hdr1));
692 g_object_unref(G_OBJECT(hdr2));
696 send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
697 GError *error, gpointer userdata)
699 SendMsgInfo *info = (SendMsgInfo *) userdata;
700 TnyHeader *hdr1, *hdr2;
701 const char *msgid1, *msgid2;
703 hdr1 = tny_msg_get_header(msg);
704 hdr2 = tny_msg_get_header(info->msg);
705 msgid1 = tny_header_get_message_id(hdr1);
706 msgid2 = tny_header_get_message_id(hdr2);
707 if (msgid1 == NULL) msgid1 = "(null)";
708 if (msgid2 == NULL) msgid2 = "(null)";
710 if (!strcmp (msgid1, msgid2)) {
712 g_warning ("%s: %s\n", __FUNCTION__, error->message);
713 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
714 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
715 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
716 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
717 "modest: send mail failed\n");
719 common_send_mail_operation_end (queue, msg, info);
721 g_object_unref(G_OBJECT(hdr1));
722 g_object_unref(G_OBJECT(hdr2));
727 idle_create_msg_cb (gpointer idle_data)
729 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
731 /* This is a GDK lock because we are an idle callback and
732 * info->callback can contain Gtk+ code */
734 gdk_threads_enter (); /* CHECKED */
735 info->callback (info->mail_op, info->msg, info->userdata);
737 g_object_unref (info->mail_op);
739 g_object_unref (info->msg);
740 g_slice_free (CreateMsgIdleInfo, info);
741 gdk_threads_leave (); /* CHECKED */
747 create_msg_thread (gpointer thread_data)
749 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
750 TnyMsg *new_msg = NULL;
751 ModestMailOperationPrivate *priv;
753 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
754 if (info->html_body == NULL) {
755 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
756 info->bcc, info->subject, info->plain_body,
757 info->attachments_list);
759 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
760 info->bcc, info->subject, info->html_body,
761 info->plain_body, info->attachments_list,
768 /* Set priority flags in message */
769 header = tny_msg_get_header (new_msg);
770 tny_header_set_flag (header, info->priority_flags);
772 /* Set attachment flags in message */
773 if (info->attachments_list != NULL)
774 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
776 g_object_unref (G_OBJECT(header));
778 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
779 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
780 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
781 "modest: failed to create a new msg\n");
789 g_free (info->plain_body);
790 g_free (info->html_body);
791 g_free (info->subject);
792 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
793 g_list_free (info->attachments_list);
794 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
795 g_list_free (info->images_list);
797 if (info->callback) {
798 CreateMsgIdleInfo *idle_info;
799 idle_info = g_slice_new0 (CreateMsgIdleInfo);
800 idle_info->mail_op = g_object_ref (info->mail_op);
801 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
802 idle_info->callback = info->callback;
803 idle_info->userdata = info->userdata;
804 g_idle_add (idle_create_msg_cb, idle_info);
806 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
809 g_object_unref (info->mail_op);
810 g_slice_free (CreateMsgInfo, info);
811 if (new_msg) g_object_unref(new_msg);
816 modest_mail_operation_create_msg (ModestMailOperation *self,
817 const gchar *from, const gchar *to,
818 const gchar *cc, const gchar *bcc,
819 const gchar *subject, const gchar *plain_body,
820 const gchar *html_body,
821 const GList *attachments_list,
822 const GList *images_list,
823 TnyHeaderFlags priority_flags,
824 ModestMailOperationCreateMsgCallback callback,
827 CreateMsgInfo *info = NULL;
829 info = g_slice_new0 (CreateMsgInfo);
830 info->mail_op = g_object_ref (self);
832 info->from = g_strdup (from);
833 info->to = g_strdup (to);
834 info->cc = g_strdup (cc);
835 info->bcc = g_strdup (bcc);
836 info->subject = g_strdup (subject);
837 info->plain_body = g_strdup (plain_body);
838 info->html_body = g_strdup (html_body);
839 info->attachments_list = g_list_copy ((GList *) attachments_list);
840 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
841 info->images_list = g_list_copy ((GList *) images_list);
842 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
843 info->priority_flags = priority_flags;
845 info->callback = callback;
846 info->userdata = userdata;
848 g_thread_create (create_msg_thread, info, FALSE, NULL);
853 TnyTransportAccount *transport_account;
858 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
862 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
863 TnyFolder *draft_folder = NULL;
864 TnyFolder *outbox_folder = NULL;
872 /* Call mail operation */
873 modest_mail_operation_send_mail (self, info->transport_account, msg);
875 /* Remove old mail from its source folder */
876 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
877 TNY_FOLDER_TYPE_DRAFTS);
879 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder", __FUNCTION__);
882 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
883 TNY_FOLDER_TYPE_OUTBOX);
884 if (!outbox_folder) {
885 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder", __FUNCTION__);
888 if (info->draft_msg != NULL) {
889 TnyFolder *folder = NULL;
890 TnyFolder *src_folder = NULL;
891 TnyFolderType folder_type;
892 folder = tny_msg_get_folder (info->draft_msg);
893 if (folder == NULL) goto end;
894 folder_type = modest_tny_folder_guess_folder_type (folder);
896 if (folder_type == TNY_FOLDER_TYPE_INVALID)
897 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
899 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
900 src_folder = outbox_folder;
902 src_folder = draft_folder;
904 /* Note: This can fail (with a warning) if the message is not really already in a folder,
905 * because this function requires it to have a UID. */
906 header = tny_msg_get_header (info->draft_msg);
907 tny_folder_remove_msg (src_folder, header, NULL);
909 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
910 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
912 g_object_unref (header);
913 g_object_unref (folder);
920 g_object_unref (info->draft_msg);
922 g_object_unref (draft_folder);
924 g_object_unref (outbox_folder);
925 if (info->transport_account)
926 g_object_unref (info->transport_account);
927 g_slice_free (SendNewMailInfo, info);
931 modest_mail_operation_send_new_mail (ModestMailOperation *self,
932 TnyTransportAccount *transport_account,
934 const gchar *from, const gchar *to,
935 const gchar *cc, const gchar *bcc,
936 const gchar *subject, const gchar *plain_body,
937 const gchar *html_body,
938 const GList *attachments_list,
939 const GList *images_list,
940 TnyHeaderFlags priority_flags)
942 ModestMailOperationPrivate *priv = NULL;
943 SendNewMailInfo *info;
945 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
946 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
948 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
949 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
950 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
951 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
953 /* Check parametters */
955 /* Set status failed and set an error */
956 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
957 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
958 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
959 _("Error trying to send a mail. You need to set at least one recipient"));
962 info = g_slice_new0 (SendNewMailInfo);
963 info->transport_account = transport_account;
964 if (transport_account)
965 g_object_ref (transport_account);
966 info->draft_msg = draft_msg;
968 g_object_ref (draft_msg);
971 modest_mail_operation_notify_start (self);
972 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
973 attachments_list, images_list, priority_flags,
974 modest_mail_operation_send_new_mail_cb, info);
980 TnyTransportAccount *transport_account;
982 SaveToDraftstCallback callback;
986 ModestMailOperation *mailop;
987 } SaveToDraftsAddMsgInfo;
990 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
995 ModestMailOperationPrivate *priv = NULL;
996 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
998 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1001 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1002 g_error_free(priv->error);
1005 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1007 if ((!priv->error) && (info->draft_msg != NULL)) {
1008 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1009 TnyFolder *src_folder = tny_header_get_folder (header);
1011 /* Remove the old draft */
1012 tny_folder_remove_msg (src_folder, header, NULL);
1014 /* Synchronize to expunge and to update the msg counts */
1015 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1016 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1018 g_object_unref (G_OBJECT(header));
1019 g_object_unref (G_OBJECT(src_folder));
1023 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1025 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1027 /* Call the user callback */
1029 info->callback (info->mailop, info->msg, info->user_data);
1031 if (info->transport_account)
1032 g_object_unref (G_OBJECT(info->transport_account));
1033 if (info->draft_msg)
1034 g_object_unref (G_OBJECT (info->draft_msg));
1036 g_object_unref (G_OBJECT(info->drafts));
1038 g_object_unref (G_OBJECT (info->msg));
1039 g_slice_free (SaveToDraftsAddMsgInfo, info);
1041 modest_mail_operation_notify_end (info->mailop);
1042 g_object_unref(info->mailop);
1047 TnyTransportAccount *transport_account;
1049 SaveToDraftstCallback callback;
1054 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1058 TnyFolder *drafts = NULL;
1059 ModestMailOperationPrivate *priv = NULL;
1060 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1062 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1065 if (!(priv->error)) {
1066 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1067 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1068 "modest: failed to create a new msg\n");
1071 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1072 TNY_FOLDER_TYPE_DRAFTS);
1073 if (!drafts && !(priv->error)) {
1074 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1075 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1076 "modest: failed to create a new msg\n");
1081 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1082 cb_info->transport_account = g_object_ref(info->transport_account);
1083 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1084 cb_info->callback = info->callback;
1085 cb_info->user_data = info->user_data;
1086 cb_info->drafts = g_object_ref(drafts);
1087 cb_info->msg = g_object_ref(msg);
1088 cb_info->mailop = g_object_ref(self);
1089 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1092 /* Call the user callback */
1093 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1095 info->callback (self, msg, info->user_data);
1096 modest_mail_operation_notify_end (self);
1100 g_object_unref (G_OBJECT(drafts));
1101 if (info->draft_msg)
1102 g_object_unref (G_OBJECT (info->draft_msg));
1103 if (info->transport_account)
1104 g_object_unref (G_OBJECT(info->transport_account));
1105 g_slice_free (SaveToDraftsInfo, info);
1109 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1110 TnyTransportAccount *transport_account,
1112 const gchar *from, const gchar *to,
1113 const gchar *cc, const gchar *bcc,
1114 const gchar *subject, const gchar *plain_body,
1115 const gchar *html_body,
1116 const GList *attachments_list,
1117 const GList *images_list,
1118 TnyHeaderFlags priority_flags,
1119 SaveToDraftstCallback callback,
1122 ModestMailOperationPrivate *priv = NULL;
1123 SaveToDraftsInfo *info = NULL;
1125 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1126 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1128 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1130 /* Get account and set it into mail_operation */
1131 priv->account = g_object_ref (transport_account);
1132 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1134 info = g_slice_new0 (SaveToDraftsInfo);
1135 info->transport_account = g_object_ref (transport_account);
1136 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1137 info->callback = callback;
1138 info->user_data = user_data;
1140 modest_mail_operation_notify_start (self);
1141 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1142 attachments_list, images_list, priority_flags,
1143 modest_mail_operation_save_to_drafts_cb, info);
1148 ModestMailOperation *mail_op;
1149 TnyMimePart *mime_part;
1151 GetMimePartSizeCallback callback;
1153 } GetMimePartSizeInfo;
1155 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1156 /* We use this folder observer to track the headers that have been
1157 * added to a folder */
1160 TnyList *new_headers;
1161 } InternalFolderObserver;
1164 GObjectClass parent;
1165 } InternalFolderObserverClass;
1167 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1169 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1170 internal_folder_observer,
1172 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1176 foreach_add_item (gpointer header, gpointer user_data)
1178 tny_list_prepend (TNY_LIST (user_data),
1179 g_object_ref (G_OBJECT (header)));
1182 /* This is the method that looks for new messages in a folder */
1184 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1186 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1188 TnyFolderChangeChanged changed;
1190 changed = tny_folder_change_get_changed (change);
1192 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1195 /* Get added headers */
1196 list = tny_simple_list_new ();
1197 tny_folder_change_get_added_headers (change, list);
1199 /* Add them to the folder observer */
1200 tny_list_foreach (list, foreach_add_item,
1201 derived->new_headers);
1203 g_object_unref (G_OBJECT (list));
1208 internal_folder_observer_init (InternalFolderObserver *self)
1210 self->new_headers = tny_simple_list_new ();
1213 internal_folder_observer_finalize (GObject *object)
1215 InternalFolderObserver *self;
1217 self = (InternalFolderObserver *) object;
1218 g_object_unref (self->new_headers);
1220 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1223 tny_folder_observer_init (TnyFolderObserverIface *iface)
1225 iface->update_func = internal_folder_observer_update;
1228 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1230 GObjectClass *object_class;
1232 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1233 object_class = (GObjectClass*) klass;
1234 object_class->finalize = internal_folder_observer_finalize;
1239 ModestMailOperation *mail_op;
1240 gchar *account_name;
1241 UpdateAccountCallback callback;
1246 TnyFolderObserver *inbox_observer;
1247 RetrieveAllCallback retrieve_all_cb;
1248 } UpdateAccountInfo;
1252 destroy_update_account_info (UpdateAccountInfo *info)
1254 g_free (info->account_name);
1255 g_object_unref (info->folders);
1256 g_object_unref (info->mail_op);
1257 g_slice_free (UpdateAccountInfo, info);
1261 update_account_get_msg_async_cb (TnyFolder *folder,
1267 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1269 /* Just delete the helper. Don't do anything with the new
1270 msg. There is also no need to check for errors */
1271 g_object_unref (msg_info->mail_op);
1272 g_object_unref (msg_info->header);
1273 g_slice_free (GetMsgInfo, msg_info);
1278 inbox_refreshed_cb (TnyFolder *inbox,
1283 UpdateAccountInfo *info;
1284 ModestMailOperationPrivate *priv;
1285 TnyIterator *new_headers_iter;
1286 GPtrArray *new_headers_array = NULL;
1287 gint max_size, retrieve_limit, i;
1288 ModestAccountMgr *mgr;
1289 ModestAccountRetrieveType retrieve_type;
1290 TnyList *new_headers = NULL;
1291 gboolean headers_only, ignore_limit;
1292 TnyTransportAccount *transport_account;
1293 ModestTnySendQueue *send_queue;
1295 info = (UpdateAccountInfo *) user_data;
1296 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1297 mgr = modest_runtime_get_account_mgr ();
1299 if (canceled || err || !inbox) {
1300 /* Try to send anyway */
1304 /* Get the message max size */
1305 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1306 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1308 max_size = G_MAXINT;
1310 max_size = max_size * KB;
1312 /* Create the new headers array. We need it to sort the
1313 new headers by date */
1314 new_headers_array = g_ptr_array_new ();
1315 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1316 while (!tny_iterator_is_done (new_headers_iter)) {
1317 TnyHeader *header = NULL;
1319 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1320 /* Apply per-message size limits */
1321 if (tny_header_get_message_size (header) < max_size)
1322 g_ptr_array_add (new_headers_array, g_object_ref (header));
1324 g_object_unref (header);
1325 tny_iterator_next (new_headers_iter);
1327 g_object_unref (new_headers_iter);
1328 tny_folder_remove_observer (inbox, info->inbox_observer);
1329 g_object_unref (info->inbox_observer);
1330 info->inbox_observer = NULL;
1332 /* Update the last updated key, even if we don't have to get new headers */
1333 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1335 if (new_headers_array->len == 0)
1338 /* Get per-account message amount retrieval limit */
1339 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1340 if (retrieve_limit == 0)
1341 retrieve_limit = G_MAXINT;
1343 /* Get per-account retrieval type */
1344 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1345 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1348 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1350 /* Ask the users if they want to retrieve all the messages
1351 even though the limit was exceeded */
1352 ignore_limit = FALSE;
1353 if (new_headers_array->len > retrieve_limit) {
1354 /* Ask the user if a callback has been specified and
1355 if the mail operation has a source (this means that
1356 was invoked by the user and not automatically by a
1358 if (info->retrieve_all_cb && priv->source)
1359 ignore_limit = info->retrieve_all_cb (priv->source,
1360 new_headers_array->len,
1364 if (!headers_only) {
1366 const gint msg_list_size = compute_message_array_size (new_headers_array);
1370 priv->total = new_headers_array->len;
1372 priv->total = MIN (new_headers_array->len, retrieve_limit);
1373 while (msg_num < priv->total) {
1374 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1375 TnyFolder *folder = tny_header_get_folder (header);
1376 GetMsgInfo *msg_info;
1378 /* Create the message info */
1379 msg_info = g_slice_new0 (GetMsgInfo);
1380 msg_info->mail_op = g_object_ref (info->mail_op);
1381 msg_info->header = g_object_ref (header);
1382 msg_info->total_bytes = msg_list_size;
1384 /* Get message in an async way */
1385 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1386 get_msg_status_cb, msg_info);
1388 g_object_unref (folder);
1394 /* Copy the headers to a list and free the array */
1395 new_headers = tny_simple_list_new ();
1396 for (i=0; i < new_headers_array->len; i++) {
1397 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1398 tny_list_append (new_headers, G_OBJECT (header));
1400 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1401 g_ptr_array_free (new_headers_array, FALSE);
1408 /* Get the transport account */
1409 transport_account = (TnyTransportAccount *)
1410 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1411 info->account_name);
1414 send_queue = modest_runtime_get_send_queue (transport_account);
1415 modest_tny_send_queue_try_to_send (send_queue);
1417 /* Check if the operation was a success */
1419 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1421 /* Set the account back to not busy */
1422 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1424 /* Call the user callback */
1426 info->callback (info->mail_op, new_headers, info->user_data);
1428 /* Notify about operation end */
1429 modest_mail_operation_notify_end (info->mail_op);
1433 g_object_unref (new_headers);
1434 destroy_update_account_info (info);
1438 recurse_folders_async_cb (TnyFolderStore *folder_store,
1444 UpdateAccountInfo *info;
1445 ModestMailOperationPrivate *priv;
1447 info = (UpdateAccountInfo *) user_data;
1448 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1450 if (err || canceled) {
1451 /* Try to continue anyway */
1453 TnyIterator *iter = tny_list_create_iterator (list);
1454 while (!tny_iterator_is_done (iter)) {
1455 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1456 TnyList *folders = tny_simple_list_new ();
1458 /* Add to the list of all folders */
1459 tny_list_append (info->folders, (GObject *) folder);
1461 /* Add pending call */
1462 info->pending_calls++;
1464 tny_folder_store_get_folders_async (folder, folders, NULL,
1465 recurse_folders_async_cb,
1468 g_object_unref (G_OBJECT (folder));
1470 tny_iterator_next (iter);
1472 g_object_unref (G_OBJECT (iter));
1473 g_object_unref (G_OBJECT (list));
1476 /* Remove my own pending call */
1477 info->pending_calls--;
1479 /* This means that we have all the folders */
1480 if (info->pending_calls == 0) {
1481 TnyIterator *iter_all_folders;
1482 TnyFolder *inbox = NULL;
1484 iter_all_folders = tny_list_create_iterator (info->folders);
1486 /* Do a poke status over all folders */
1487 while (!tny_iterator_is_done (iter_all_folders) &&
1488 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1489 TnyFolder *folder = NULL;
1491 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1493 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1494 /* Get a reference to the INBOX */
1495 inbox = g_object_ref (folder);
1497 /* Issue a poke status over the folder */
1499 tny_folder_poke_status (folder);
1502 /* Free and go to next */
1503 g_object_unref (folder);
1504 tny_iterator_next (iter_all_folders);
1506 g_object_unref (iter_all_folders);
1508 /* Refresh the INBOX */
1510 /* Refresh the folder. Our observer receives
1511 * the new emails during folder refreshes, so
1512 * we can use observer->new_headers
1514 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1515 tny_folder_add_observer (inbox, info->inbox_observer);
1517 /* Refresh the INBOX */
1518 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1519 g_object_unref (inbox);
1521 /* We could not perform the inbox refresh but
1522 we'll try to send mails anyway */
1523 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1529 modest_mail_operation_update_account (ModestMailOperation *self,
1530 const gchar *account_name,
1532 RetrieveAllCallback retrieve_all_cb,
1533 UpdateAccountCallback callback,
1536 UpdateAccountInfo *info = NULL;
1537 ModestMailOperationPrivate *priv = NULL;
1538 ModestTnyAccountStore *account_store = NULL;
1539 TnyStoreAccount *store_account = NULL;
1542 /* Init mail operation */
1543 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1546 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1547 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1549 /* Get the store account */
1550 account_store = modest_runtime_get_account_store ();
1551 store_account = (TnyStoreAccount *)
1552 modest_tny_account_store_get_server_account (account_store,
1554 TNY_ACCOUNT_TYPE_STORE);
1555 priv->account = g_object_ref (store_account);
1557 /* Create the helper object */
1558 info = g_slice_new0 (UpdateAccountInfo);
1559 info->pending_calls = 1;
1560 info->folders = tny_simple_list_new ();
1561 info->mail_op = g_object_ref (self);
1562 info->poke_all = poke_all;
1563 info->account_name = g_strdup (account_name);
1564 info->callback = callback;
1565 info->user_data = user_data;
1566 info->retrieve_all_cb = retrieve_all_cb;
1568 /* Set account busy */
1569 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1570 modest_mail_operation_notify_start (self);
1572 /* notify about the start of the operation */
1573 ModestMailOperationState *state;
1574 state = modest_mail_operation_clone_state (self);
1578 /* Start notifying progress */
1579 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
1581 g_slice_free (ModestMailOperationState, state);
1583 /* Get all folders and continue in the callback */
1584 folders = tny_simple_list_new ();
1585 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1587 recurse_folders_async_cb,
1592 * Used to notify the queue from the main
1593 * loop. We call it inside an idle call to achieve that
1596 idle_notify_queue (gpointer data)
1598 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1600 gdk_threads_enter ();
1601 modest_mail_operation_notify_end (mail_op);
1602 gdk_threads_leave ();
1603 g_object_unref (mail_op);
1609 compare_headers_by_date (gconstpointer a,
1612 TnyHeader **header1, **header2;
1613 time_t sent1, sent2;
1615 header1 = (TnyHeader **) a;
1616 header2 = (TnyHeader **) b;
1618 sent1 = tny_header_get_date_sent (*header1);
1619 sent2 = tny_header_get_date_sent (*header2);
1621 /* We want the most recent ones (greater time_t) at the
1630 /* ******************************************************************* */
1631 /* ************************** STORE ACTIONS ************************* */
1632 /* ******************************************************************* */
1635 ModestMailOperation *mail_op;
1636 CreateFolderUserCallback callback;
1642 create_folder_cb (TnyFolderStore *parent_folder,
1644 TnyFolder *new_folder,
1648 ModestMailOperationPrivate *priv;
1649 CreateFolderInfo *info;
1651 info = (CreateFolderInfo *) user_data;
1652 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1654 if (canceled || err) {
1655 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1657 priv->error = g_error_copy (err);
1659 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1660 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1663 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1666 /* The user will unref the new_folder */
1668 info->callback (info->mail_op, parent_folder,
1669 new_folder, info->user_data);
1671 /* Notify about operation end */
1672 modest_mail_operation_notify_end (info->mail_op);
1675 g_object_unref (info->mail_op);
1676 g_slice_free (CreateFolderInfo, info);
1680 modest_mail_operation_create_folder (ModestMailOperation *self,
1681 TnyFolderStore *parent,
1683 CreateFolderUserCallback callback,
1686 ModestMailOperationPrivate *priv;
1688 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1689 g_return_if_fail (name);
1691 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1692 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1693 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1694 g_object_ref (parent) :
1695 modest_tny_folder_get_account (TNY_FOLDER (parent));
1697 /* Check for already existing folder */
1698 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1699 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1700 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1701 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1702 _CS("ckdg_ib_folder_already_exists"));
1706 if (TNY_IS_FOLDER (parent)) {
1707 /* Check folder rules */
1708 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1709 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1710 /* Set status failed and set an error */
1711 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1712 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1713 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1714 _("mail_in_ui_folder_create_error"));
1718 if (!strcmp (name, " ") || strchr (name, '/')) {
1719 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1720 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1721 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1722 _("mail_in_ui_folder_create_error"));
1726 CreateFolderInfo *info;
1728 info = g_slice_new0 (CreateFolderInfo);
1729 info->mail_op = g_object_ref (self);
1730 info->callback = callback;
1731 info->user_data = user_data;
1733 modest_mail_operation_notify_start (self);
1735 /* Create the folder */
1736 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1739 /* Call the user callback anyway */
1741 callback (self, parent, NULL, user_data);
1742 /* Notify about operation end */
1743 modest_mail_operation_notify_end (self);
1748 modest_mail_operation_remove_folder (ModestMailOperation *self,
1750 gboolean remove_to_trash)
1752 TnyAccount *account;
1753 ModestMailOperationPrivate *priv;
1754 ModestTnyFolderRules rules;
1756 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1757 g_return_if_fail (TNY_IS_FOLDER (folder));
1759 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1761 /* Check folder rules */
1762 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1763 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1764 /* Set status failed and set an error */
1765 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1766 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1767 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1768 _("mail_in_ui_folder_delete_error"));
1772 /* Get the account */
1773 account = modest_tny_folder_get_account (folder);
1774 priv->account = g_object_ref(account);
1775 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1777 /* Delete folder or move to trash */
1778 if (remove_to_trash) {
1779 TnyFolder *trash_folder = NULL;
1780 trash_folder = modest_tny_account_get_special_folder (account,
1781 TNY_FOLDER_TYPE_TRASH);
1782 /* TODO: error_handling */
1784 modest_mail_operation_notify_start (self);
1785 modest_mail_operation_xfer_folder (self, folder,
1786 TNY_FOLDER_STORE (trash_folder),
1788 g_object_unref (trash_folder);
1790 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1793 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1795 modest_mail_operation_notify_start (self);
1796 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1797 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1800 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1802 g_object_unref (parent);
1804 g_warning ("%s: could not get parent folder", __FUNCTION__);
1806 g_object_unref (G_OBJECT (account));
1809 /* Notify about operation end */
1810 modest_mail_operation_notify_end (self);
1814 transfer_folder_status_cb (GObject *obj,
1818 ModestMailOperation *self;
1819 ModestMailOperationPrivate *priv;
1820 ModestMailOperationState *state;
1821 XFerMsgAsyncHelper *helper;
1823 g_return_if_fail (status != NULL);
1824 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1826 helper = (XFerMsgAsyncHelper *) user_data;
1827 g_return_if_fail (helper != NULL);
1829 self = helper->mail_op;
1830 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1832 priv->done = status->position;
1833 priv->total = status->of_total;
1835 state = modest_mail_operation_clone_state (self);
1837 /* This is not a GDK lock because we are a Tinymail callback
1838 * which is already GDK locked by Tinymail */
1840 /* no gdk_threads_enter (), CHECKED */
1842 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1844 /* no gdk_threads_leave (), CHECKED */
1846 g_slice_free (ModestMailOperationState, state);
1851 transfer_folder_cb (TnyFolder *folder,
1853 TnyFolderStore *into,
1854 TnyFolder *new_folder,
1858 XFerMsgAsyncHelper *helper;
1859 ModestMailOperation *self = NULL;
1860 ModestMailOperationPrivate *priv = NULL;
1862 helper = (XFerMsgAsyncHelper *) user_data;
1863 g_return_if_fail (helper != NULL);
1865 self = helper->mail_op;
1866 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1869 priv->error = g_error_copy (err);
1871 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1872 } else if (cancelled) {
1873 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1874 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1875 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1876 _("Transference of %s was cancelled."),
1877 tny_folder_get_name (folder));
1880 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1883 /* Notify about operation end */
1884 modest_mail_operation_notify_end (self);
1886 /* If user defined callback function was defined, call it */
1887 if (helper->user_callback) {
1889 /* This is not a GDK lock because we are a Tinymail callback
1890 * which is already GDK locked by Tinymail */
1892 /* no gdk_threads_enter (), CHECKED */
1893 helper->user_callback (self, helper->user_data);
1894 /* no gdk_threads_leave () , CHECKED */
1898 g_object_unref (helper->mail_op);
1899 g_slice_free (XFerMsgAsyncHelper, helper);
1904 * This function checks if the new name is a valid name for our local
1905 * folders account. The new name could not be the same than then name
1906 * of any of the mandatory local folders
1908 * We can not rely on tinymail because tinymail does not check the
1909 * name of the virtual folders that the account could have in the case
1910 * that we're doing a rename (because it directly calls Camel which
1911 * knows nothing about our virtual folders).
1913 * In the case of an actual copy/move (i.e. move/copy a folder between
1914 * accounts) tinymail uses the tny_folder_store_create_account which
1915 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1916 * checks the new name of the folder, so this call in that case
1917 * wouldn't be needed. *But* NOTE that if tinymail changes its
1918 * implementation (if folder transfers within the same account is no
1919 * longer implemented as a rename) this call will allow Modest to work
1922 * If the new name is not valid, this function will set the status to
1923 * failed and will set also an error in the mail operation
1926 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1927 TnyFolderStore *into,
1928 const gchar *new_name)
1930 if (TNY_IS_ACCOUNT (into) &&
1931 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1932 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1934 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1935 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1936 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1937 _CS("ckdg_ib_folder_already_exists"));
1944 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1946 TnyFolderStore *parent,
1947 gboolean delete_original,
1948 XferAsyncUserCallback user_callback,
1951 ModestMailOperationPrivate *priv = NULL;
1952 ModestTnyFolderRules parent_rules = 0, rules;
1953 XFerMsgAsyncHelper *helper = NULL;
1954 const gchar *folder_name = NULL;
1955 const gchar *error_msg;
1957 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1958 g_return_if_fail (TNY_IS_FOLDER (folder));
1959 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1961 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1962 folder_name = tny_folder_get_name (folder);
1964 /* Set the error msg */
1965 error_msg = _("mail_in_ui_folder_move_target_error");
1967 /* Get account and set it into mail_operation */
1968 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1969 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1970 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1972 /* Get folder rules */
1973 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1974 if (TNY_IS_FOLDER (parent))
1975 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1977 /* Apply operation constraints */
1978 if ((gpointer) parent == (gpointer) folder ||
1979 (!TNY_IS_FOLDER_STORE (parent)) ||
1980 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1983 } else if (TNY_IS_FOLDER (parent) &&
1984 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1988 } else if (TNY_IS_FOLDER (parent) &&
1989 TNY_IS_FOLDER_STORE (folder) &&
1990 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1991 TNY_FOLDER_STORE (folder))) {
1992 /* Do not move a parent into a child */
1994 } else if (TNY_IS_FOLDER_STORE (parent) &&
1995 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1996 /* Check that the new folder name is not used by any
1999 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2000 /* Check that the new folder name is not used by any
2001 special local folder */
2004 /* Create the helper */
2005 helper = g_slice_new0 (XFerMsgAsyncHelper);
2006 helper->mail_op = g_object_ref (self);
2007 helper->dest_folder = NULL;
2008 helper->headers = NULL;
2009 helper->user_callback = user_callback;
2010 helper->user_data = user_data;
2012 /* Move/Copy folder */
2013 modest_mail_operation_notify_start (self);
2014 tny_folder_copy_async (folder,
2016 tny_folder_get_name (folder),
2019 transfer_folder_status_cb,
2025 /* Set status failed and set an error */
2026 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2027 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2028 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2031 /* Call the user callback if exists */
2033 user_callback (self, user_data);
2035 /* Notify the queue */
2036 modest_mail_operation_notify_end (self);
2040 modest_mail_operation_rename_folder (ModestMailOperation *self,
2044 ModestMailOperationPrivate *priv;
2045 ModestTnyFolderRules rules;
2046 XFerMsgAsyncHelper *helper;
2048 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2049 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2050 g_return_if_fail (name);
2052 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2054 /* Get account and set it into mail_operation */
2055 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2056 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2058 /* Check folder rules */
2059 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2060 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2061 /* Set status failed and set an error */
2062 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2063 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2064 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2065 _("FIXME: unable to rename"));
2067 /* Notify about operation end */
2068 modest_mail_operation_notify_end (self);
2069 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2070 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2071 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2072 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2073 _("FIXME: unable to rename"));
2074 /* Notify about operation end */
2075 modest_mail_operation_notify_end (self);
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 (XFerMsgAsyncHelper);
2086 helper->mail_op = g_object_ref(self);
2087 helper->dest_folder = NULL;
2088 helper->headers = NULL;
2089 helper->user_callback = NULL;
2090 helper->user_data = NULL;
2092 /* Rename. Camel handles folder subscription/unsubscription */
2093 modest_mail_operation_notify_start (self);
2094 tny_folder_copy_async (folder, into, name, TRUE,
2096 transfer_folder_status_cb,
2099 modest_mail_operation_notify_end (self);
2101 g_object_unref (into);
2105 /* ******************************************************************* */
2106 /* ************************** MSG ACTIONS ************************* */
2107 /* ******************************************************************* */
2110 modest_mail_operation_get_msg (ModestMailOperation *self,
2112 GetMsgAsyncUserCallback user_callback,
2115 GetMsgInfo *helper = NULL;
2117 ModestMailOperationPrivate *priv;
2119 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2120 g_return_if_fail (TNY_IS_HEADER (header));
2122 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2123 folder = tny_header_get_folder (header);
2125 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2129 /* Get account and set it into mail_operation */
2130 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2132 /* Check for cached messages */
2133 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2134 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2136 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2138 /* Create the helper */
2139 helper = g_slice_new0 (GetMsgInfo);
2140 helper->header = g_object_ref (header);
2141 helper->mail_op = g_object_ref (self);
2142 helper->user_callback = user_callback;
2143 helper->user_data = user_data;
2144 helper->destroy_notify = NULL;
2145 helper->last_total_bytes = 0;
2146 helper->sum_total_bytes = 0;
2147 helper->total_bytes = tny_header_get_message_size (header);
2149 modest_mail_operation_notify_start (self);
2151 /* notify about the start of the operation */
2152 ModestMailOperationState *state;
2153 state = modest_mail_operation_clone_state (self);
2156 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2159 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2161 g_object_unref (G_OBJECT (folder));
2165 get_msg_status_cb (GObject *obj,
2169 GetMsgInfo *helper = NULL;
2171 g_return_if_fail (status != NULL);
2172 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2174 helper = (GetMsgInfo *) user_data;
2175 g_return_if_fail (helper != NULL);
2177 /* Notify progress */
2178 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2179 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2183 get_msg_async_cb (TnyFolder *folder,
2189 GetMsgInfo *info = NULL;
2190 ModestMailOperationPrivate *priv = NULL;
2193 info = (GetMsgInfo *) user_data;
2195 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2197 finished = (priv->done == priv->total) ? TRUE : FALSE;
2200 if (canceled || err) {
2201 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2203 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2204 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2207 /* Set the success status before calling the user callback */
2208 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2209 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2213 /* Call the user callback */
2214 if (info->user_callback)
2215 info->user_callback (info->mail_op, info->header, canceled,
2216 msg, err, info->user_data);
2218 /* Notify about operation end if this is the last callback */
2220 /* Free user data */
2221 if (info->destroy_notify)
2222 info->destroy_notify (info->user_data);
2224 /* Notify about operation end */
2225 modest_mail_operation_notify_end (info->mail_op);
2229 g_object_unref (info->header);
2230 g_object_unref (info->mail_op);
2231 g_slice_free (GetMsgInfo, info);
2235 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2236 TnyList *header_list,
2237 GetMsgAsyncUserCallback user_callback,
2239 GDestroyNotify notify)
2241 ModestMailOperationPrivate *priv = NULL;
2242 gboolean size_ok = TRUE;
2244 TnyIterator *iter = NULL;
2246 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2248 /* Init mail operation */
2249 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2250 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2251 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2253 priv->total = tny_list_get_length(header_list);
2255 /* Get account and set it into mail_operation */
2256 if (tny_list_get_length (header_list) >= 1) {
2257 iter = tny_list_create_iterator (header_list);
2258 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2260 TnyFolder *folder = tny_header_get_folder (header);
2262 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2263 g_object_unref (folder);
2265 g_object_unref (header);
2268 if (tny_list_get_length (header_list) == 1) {
2269 g_object_unref (iter);
2274 /* Get msg size limit */
2275 max_size = modest_conf_get_int (modest_runtime_get_conf (),
2276 MODEST_CONF_MSG_SIZE_LIMIT,
2279 g_clear_error (&(priv->error));
2280 max_size = G_MAXINT;
2282 max_size = max_size * KB;
2285 /* Check message size limits. If there is only one message
2286 always retrieve it */
2288 while (!tny_iterator_is_done (iter) && size_ok) {
2289 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2291 if (tny_header_get_message_size (header) >= max_size)
2293 g_object_unref (header);
2296 tny_iterator_next (iter);
2298 g_object_unref (iter);
2302 const gint msg_list_size = compute_message_list_size (header_list);
2304 modest_mail_operation_notify_start (self);
2305 iter = tny_list_create_iterator (header_list);
2306 while (!tny_iterator_is_done (iter)) {
2307 /* notify about the start of the operation */
2308 ModestMailOperationState *state;
2309 state = modest_mail_operation_clone_state (self);
2312 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2315 GetMsgInfo *msg_info = NULL;
2316 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2317 TnyFolder *folder = tny_header_get_folder (header);
2319 /* Create the message info */
2320 msg_info = g_slice_new0 (GetMsgInfo);
2321 msg_info->mail_op = g_object_ref (self);
2322 msg_info->header = g_object_ref (header);
2323 msg_info->user_callback = user_callback;
2324 msg_info->user_data = user_data;
2325 msg_info->destroy_notify = notify;
2326 msg_info->last_total_bytes = 0;
2327 msg_info->sum_total_bytes = 0;
2328 msg_info->total_bytes = msg_list_size;
2330 /* The callback will call it per each header */
2331 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2333 /* Free and go on */
2334 g_object_unref (header);
2335 g_object_unref (folder);
2336 tny_iterator_next (iter);
2338 g_object_unref (iter);
2340 /* Set status failed and set an error */
2341 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2342 /* FIXME: the error msg is different for pop */
2343 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2344 MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
2345 _("emev_ni_ui_imap_msg_size_exceed_error"));
2346 /* Remove from queue and free resources */
2347 modest_mail_operation_notify_end (self);
2356 modest_mail_operation_remove_msg (ModestMailOperation *self,
2358 gboolean remove_to_trash /*ignored*/)
2361 ModestMailOperationPrivate *priv;
2363 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2364 g_return_if_fail (TNY_IS_HEADER (header));
2366 if (remove_to_trash)
2367 g_warning ("remove to trash is not implemented");
2369 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2370 folder = tny_header_get_folder (header);
2372 /* Get account and set it into mail_operation */
2373 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2374 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2375 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2377 /* remove message from folder */
2378 tny_folder_remove_msg (folder, header, &(priv->error));
2380 gboolean expunge, leave_on_server;
2381 const gchar *account_name;
2382 TnyAccount *account;
2383 ModestTransportStoreProtocol account_proto;
2385 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2386 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2388 modest_mail_operation_notify_start (self);
2390 /* Get leave on server setting */
2391 account = tny_folder_get_account (folder);
2392 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2394 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2397 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2399 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2400 modest_tny_folder_is_remote_folder (folder) == FALSE)
2406 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2409 g_object_unref (account);
2415 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2417 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2420 g_object_unref (G_OBJECT (folder));
2422 /* Notify about operation end */
2423 modest_mail_operation_notify_end (self);
2427 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2429 gboolean remove_to_trash /*ignored*/)
2432 ModestMailOperationPrivate *priv;
2433 TnyIterator *iter = NULL;
2434 TnyHeader *header = NULL;
2435 TnyList *remove_headers = NULL;
2436 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2438 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2439 g_return_if_fail (TNY_IS_LIST (headers));
2441 if (remove_to_trash)
2442 g_warning ("remove to trash is not implemented");
2444 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2446 remove_headers = g_object_ref(headers);
2448 /* Get folder from first header and sync it */
2449 iter = tny_list_create_iterator (headers);
2450 header = TNY_HEADER (tny_iterator_get_current (iter));
2451 folder = tny_header_get_folder (header);
2453 /* Don't remove messages that are being sent */
2454 if (modest_tny_folder_is_local_folder (folder)) {
2455 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2457 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2458 TnyTransportAccount *traccount = NULL;
2459 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2460 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2462 ModestTnySendQueueStatus status;
2463 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2464 TnyIterator *iter = tny_list_create_iterator(headers);
2465 g_object_unref(remove_headers);
2466 remove_headers = TNY_LIST(tny_simple_list_new());
2467 while (!tny_iterator_is_done(iter)) {
2469 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2470 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2471 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2472 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2473 tny_list_append(remove_headers, G_OBJECT(hdr));
2475 g_object_unref(hdr);
2477 tny_iterator_next(iter);
2479 g_object_unref(iter);
2480 g_object_unref(traccount);
2484 /* Get account and set it into mail_operation */
2485 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2486 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2487 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2489 /* remove message from folder */
2490 modest_mail_operation_notify_start (self);
2492 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2494 gboolean expunge, leave_on_server;
2495 const gchar *account_name;
2497 TnyAccount *account;
2498 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2500 account = tny_folder_get_account (folder);
2501 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2503 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2506 proto = tny_account_get_proto (account);
2508 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2511 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2512 modest_tny_folder_is_remote_folder (folder) == FALSE)
2518 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2520 g_object_unref (account);
2526 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2528 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2531 g_object_unref (remove_headers);
2532 g_object_unref (header);
2533 g_object_unref (iter);
2534 g_object_unref (G_OBJECT (folder));
2536 /* Notify about operation end */
2537 modest_mail_operation_notify_end (self);
2541 notify_progress_of_multiple_messages (ModestMailOperation *self,
2543 gint *last_total_bytes,
2544 gint *sum_total_bytes,
2546 gboolean increment_done)
2548 ModestMailOperationPrivate *priv;
2549 ModestMailOperationState *state;
2550 gboolean is_num_bytes = FALSE;
2552 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2554 /* We know that tinymail sends us information about
2555 * transferred bytes with this particular message
2557 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2558 * I just added the 'if' so we don't get runtime warning)
2560 if (status->message)
2561 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2563 state = modest_mail_operation_clone_state (self);
2564 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2565 /* We know that we're in a different message when the
2566 total number of bytes to transfer is different. Of
2567 course it could fail if we're transferring messages
2568 of the same size, but this is a workarround */
2569 if (status->of_total != *last_total_bytes) {
2570 /* We need to increment the done when there is
2571 no information about each individual
2572 message, we need to do this in message
2573 transfers, and we don't do it for getting
2577 *sum_total_bytes += *last_total_bytes;
2578 *last_total_bytes = status->of_total;
2580 state->bytes_done += status->position + *sum_total_bytes;
2581 state->bytes_total = total_bytes;
2583 /* Notify the status change. Only notify about changes
2584 referred to bytes */
2585 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2589 g_slice_free (ModestMailOperationState, state);
2593 transfer_msgs_status_cb (GObject *obj,
2597 XFerMsgAsyncHelper *helper;
2599 g_return_if_fail (status != NULL);
2600 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2602 helper = (XFerMsgAsyncHelper *) user_data;
2603 g_return_if_fail (helper != NULL);
2605 /* Notify progress */
2606 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2607 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2612 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2614 XFerMsgAsyncHelper *helper;
2615 ModestMailOperation *self;
2616 ModestMailOperationPrivate *priv;
2617 TnyIterator *iter = NULL;
2618 TnyHeader *header = NULL;
2620 helper = (XFerMsgAsyncHelper *) user_data;
2621 self = helper->mail_op;
2623 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2626 priv->error = g_error_copy (err);
2628 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2629 } else if (cancelled) {
2630 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2631 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2632 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2633 _("Error trying to refresh the contents of %s"),
2634 tny_folder_get_name (folder));
2637 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2639 /* Update folder counts */
2640 tny_folder_poke_status (folder);
2641 tny_folder_poke_status (helper->dest_folder);
2645 /* Mark headers as deleted and seen */
2646 if ((helper->delete) &&
2647 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2648 iter = tny_list_create_iterator (helper->headers);
2649 while (!tny_iterator_is_done (iter)) {
2650 header = TNY_HEADER (tny_iterator_get_current (iter));
2651 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2652 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2653 g_object_unref (header);
2655 tny_iterator_next (iter);
2660 /* Notify about operation end */
2661 modest_mail_operation_notify_end (self);
2663 /* If user defined callback function was defined, call it */
2664 if (helper->user_callback) {
2665 /* This is not a GDK lock because we are a Tinymail callback and
2666 * Tinymail already acquires the Gdk lock */
2668 /* no gdk_threads_enter (), CHECKED */
2669 helper->user_callback (self, helper->user_data);
2670 /* no gdk_threads_leave (), CHECKED */
2674 if (helper->headers)
2675 g_object_unref (helper->headers);
2676 if (helper->dest_folder)
2677 g_object_unref (helper->dest_folder);
2678 if (helper->mail_op)
2679 g_object_unref (helper->mail_op);
2681 g_object_unref (folder);
2683 g_object_unref (iter);
2684 g_slice_free (XFerMsgAsyncHelper, helper);
2688 compute_message_list_size (TnyList *headers)
2693 iter = tny_list_create_iterator (headers);
2694 while (!tny_iterator_is_done (iter)) {
2695 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2696 size += tny_header_get_message_size (header);
2697 g_object_unref (header);
2698 tny_iterator_next (iter);
2700 g_object_unref (iter);
2706 compute_message_array_size (GPtrArray *headers)
2711 for (i = 0; i < headers->len; i++) {
2712 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2713 size += tny_header_get_message_size (header);
2721 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2724 gboolean delete_original,
2725 XferAsyncUserCallback user_callback,
2728 ModestMailOperationPrivate *priv = NULL;
2729 TnyIterator *iter = NULL;
2730 TnyFolder *src_folder = NULL;
2731 XFerMsgAsyncHelper *helper = NULL;
2732 TnyHeader *header = NULL;
2733 ModestTnyFolderRules rules = 0;
2735 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2736 g_return_if_fail (headers && TNY_IS_LIST (headers));
2737 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2739 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2740 priv->total = tny_list_get_length (headers);
2742 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2743 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2745 /* Apply folder rules */
2746 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2747 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2748 /* Set status failed and set an error */
2749 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2750 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2751 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2752 _CS("ckct_ib_unable_to_paste_here"));
2753 /* Notify the queue */
2754 modest_mail_operation_notify_end (self);
2758 /* Get source folder */
2759 iter = tny_list_create_iterator (headers);
2760 header = TNY_HEADER (tny_iterator_get_current (iter));
2762 src_folder = tny_header_get_folder (header);
2763 g_object_unref (header);
2765 g_object_unref (iter);
2767 if (src_folder == NULL) {
2768 /* Notify the queue */
2769 modest_mail_operation_notify_end (self);
2771 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2776 /* Check folder source and destination */
2777 if (src_folder == folder) {
2778 /* Set status failed and set an error */
2779 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2780 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2781 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2782 _("mail_in_ui_folder_copy_target_error"));
2784 /* Notify the queue */
2785 modest_mail_operation_notify_end (self);
2788 g_object_unref (src_folder);
2792 /* Create the helper */
2793 helper = g_slice_new0 (XFerMsgAsyncHelper);
2794 helper->mail_op = g_object_ref(self);
2795 helper->dest_folder = g_object_ref(folder);
2796 helper->headers = g_object_ref(headers);
2797 helper->user_callback = user_callback;
2798 helper->user_data = user_data;
2799 helper->delete = delete_original;
2800 helper->last_total_bytes = 0;
2801 helper->sum_total_bytes = 0;
2802 helper->total_bytes = compute_message_list_size (headers);
2804 /* Get account and set it into mail_operation */
2805 priv->account = modest_tny_folder_get_account (src_folder);
2807 /* Transfer messages */
2808 modest_mail_operation_notify_start (self);
2809 tny_folder_transfer_msgs_async (src_folder,
2814 transfer_msgs_status_cb,
2820 on_refresh_folder (TnyFolder *folder,
2825 RefreshAsyncHelper *helper = NULL;
2826 ModestMailOperation *self = NULL;
2827 ModestMailOperationPrivate *priv = NULL;
2829 helper = (RefreshAsyncHelper *) user_data;
2830 self = helper->mail_op;
2831 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2833 g_return_if_fail(priv!=NULL);
2836 priv->error = g_error_copy (error);
2837 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2842 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2843 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2844 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2845 _("Error trying to refresh the contents of %s"),
2846 tny_folder_get_name (folder));
2850 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2853 /* Call user defined callback, if it exists */
2854 if (helper->user_callback) {
2856 /* This is not a GDK lock because we are a Tinymail callback and
2857 * Tinymail already acquires the Gdk lock */
2858 helper->user_callback (self, folder, helper->user_data);
2862 g_slice_free (RefreshAsyncHelper, helper);
2864 /* Notify about operation end */
2865 modest_mail_operation_notify_end (self);
2866 g_object_unref(self);
2870 on_refresh_folder_status_update (GObject *obj,
2874 RefreshAsyncHelper *helper = NULL;
2875 ModestMailOperation *self = NULL;
2876 ModestMailOperationPrivate *priv = NULL;
2877 ModestMailOperationState *state;
2879 g_return_if_fail (user_data != NULL);
2880 g_return_if_fail (status != NULL);
2881 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2883 helper = (RefreshAsyncHelper *) user_data;
2884 self = helper->mail_op;
2885 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2887 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2889 priv->done = status->position;
2890 priv->total = status->of_total;
2892 state = modest_mail_operation_clone_state (self);
2894 /* This is not a GDK lock because we are a Tinymail callback and
2895 * Tinymail already acquires the Gdk lock */
2896 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2898 g_slice_free (ModestMailOperationState, state);
2902 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2904 RefreshAsyncUserCallback user_callback,
2907 ModestMailOperationPrivate *priv = NULL;
2908 RefreshAsyncHelper *helper = NULL;
2910 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2912 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2914 /* Get account and set it into mail_operation */
2915 priv->account = modest_tny_folder_get_account (folder);
2916 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2918 /* Create the helper */
2919 helper = g_slice_new0 (RefreshAsyncHelper);
2920 helper->mail_op = g_object_ref(self);
2921 helper->user_callback = user_callback;
2922 helper->user_data = user_data;
2924 /* Refresh the folder. TODO: tinymail could issue a status
2925 updates before the callback call then this could happen. We
2926 must review the design */
2927 modest_mail_operation_notify_start (self);
2929 /* notify that the operation was started */
2930 ModestMailOperationState *state;
2931 state = modest_mail_operation_clone_state (self);
2934 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2937 tny_folder_refresh_async (folder,
2939 on_refresh_folder_status_update,
2945 modest_mail_operation_notify_start (ModestMailOperation *self)
2947 ModestMailOperationPrivate *priv = NULL;
2949 g_return_if_fail (self);
2951 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2953 /* Ensure that all the fields are filled correctly */
2954 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2956 /* Notify the observers about the mail operation. We do not
2957 wrapp this emission because we assume that this function is
2958 always called from within the main lock */
2959 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2964 * It's used by the mail operation queue to notify the observers
2965 * attached to that signal that the operation finished. We need to use
2966 * that because tinymail does not give us the progress of a given
2967 * operation when it finishes (it directly calls the operation
2971 modest_mail_operation_notify_end (ModestMailOperation *self)
2973 ModestMailOperationPrivate *priv = NULL;
2975 g_return_if_fail (self);
2977 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2979 /* Notify the observers about the mail operation end. We do
2980 not wrapp this emission because we assume that this
2981 function is always called from within the main lock */
2982 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2984 /* Remove the error user data */
2985 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2986 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2990 modest_mail_operation_get_account (ModestMailOperation *self)
2992 ModestMailOperationPrivate *priv = NULL;
2994 g_return_val_if_fail (self, NULL);
2996 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2998 return (priv->account) ? g_object_ref (priv->account) : NULL;
3002 modest_mail_operation_noop (ModestMailOperation *self)
3004 ModestMailOperationPrivate *priv = NULL;
3006 g_return_if_fail (self);
3008 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3009 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3010 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3014 /* This mail operation does nothing actually */
3015 modest_mail_operation_notify_start (self);
3016 modest_mail_operation_notify_end (self);
3021 modest_mail_operation_to_string (ModestMailOperation *self)
3023 const gchar *type, *status, *account_id;
3024 ModestMailOperationPrivate *priv = NULL;
3026 g_return_val_if_fail (self, NULL);
3028 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3030 /* new operations don't have anything interesting */
3031 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3032 return g_strdup_printf ("%p <new operation>", self);
3034 switch (priv->op_type) {
3035 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3036 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3037 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3038 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3039 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3040 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3041 default: type = "UNEXPECTED"; break;
3044 switch (priv->status) {
3045 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3046 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3047 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3048 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3049 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3050 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3051 default: status= "UNEXPECTED"; break;
3054 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3056 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3057 priv->done, priv->total,
3058 priv->error && priv->error->message ? priv->error->message : "");