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.
31 #include <modest-tny-send-queue.h>
32 #include <tny-simple-list.h>
33 #include <tny-iterator.h>
34 #include <tny-folder.h>
35 #include <tny-error.h>
36 #include <tny-camel-msg.h>
37 #include <tny-folder-change.h>
38 #include <tny-folder-observer.h>
39 #include <modest-tny-account.h>
40 #include <modest-runtime.h>
41 #include <modest-platform.h>
42 #include <widgets/modest-window-mgr.h>
43 #include <modest-marshal.h>
44 #include <modest-debug.h>
45 #include <string.h> /* strcmp */
47 /* 'private'/'protected' functions */
48 static void modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass);
49 static void modest_tny_send_queue_finalize (GObject *obj);
50 static void modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class);
53 static void _on_msg_start_sending (TnySendQueue *self,
60 static void _on_msg_has_been_sent (TnySendQueue *self,
67 static void _on_msg_error_happened (TnySendQueue *self,
73 static void _on_queue_start (TnySendQueue *self,
76 static void modest_tny_send_queue_add_async (TnySendQueue *self,
78 TnySendQueueAddCallback callback,
79 TnyStatusCallback status_callback,
82 static TnyFolder* modest_tny_send_queue_get_outbox (TnySendQueue *self);
83 static TnyFolder* modest_tny_send_queue_get_sentbox (TnySendQueue *self);
87 STATUS_CHANGED_SIGNAL,
91 typedef struct _SendInfo SendInfo;
94 ModestTnySendQueueStatus status;
97 typedef struct _ModestTnySendQueuePrivate ModestTnySendQueuePrivate;
98 struct _ModestTnySendQueuePrivate {
102 /* The info that is currently being sent */
105 /* Special folders */
110 #define MODEST_TNY_SEND_QUEUE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
111 MODEST_TYPE_TNY_SEND_QUEUE, \
112 ModestTnySendQueuePrivate))
115 static TnyCamelSendQueueClass *parent_class = NULL;
117 /* uncomment the following if you have defined any signals */
118 static guint signals[LAST_SIGNAL] = {0};
121 * this thread actually tries to send all the mails in the outbox and keeps
122 * track of their state.
126 on_modest_tny_send_queue_compare_id (gconstpointer info, gconstpointer msg_id)
128 g_return_val_if_fail (info && ((SendInfo*)info)->msg_id && msg_id, -1);
130 return strcmp( ((SendInfo*)info)->msg_id, msg_id);
134 modest_tny_send_queue_info_free (SendInfo *info)
136 g_free(info->msg_id);
137 g_slice_free(SendInfo, info);
141 modest_tny_send_queue_lookup_info (ModestTnySendQueue *self, const gchar *msg_id)
143 ModestTnySendQueuePrivate *priv;
144 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
146 return g_queue_find_custom (priv->queue, msg_id, on_modest_tny_send_queue_compare_id);
151 queue_item_to_string (gpointer data, gchar **user_data)
153 SendInfo *info = (SendInfo*)data;
157 if (!(user_data && *user_data))
160 switch (info->status) {
161 case MODEST_TNY_SEND_QUEUE_UNKNOWN: status = "UNKNOWN"; break;
162 case MODEST_TNY_SEND_QUEUE_WAITING: status = "WAITING"; break;
163 case MODEST_TNY_SEND_QUEUE_SUSPENDED: status = "SUSPENDED"; break;
164 case MODEST_TNY_SEND_QUEUE_SENDING: status = "SENDING"; break;
165 case MODEST_TNY_SEND_QUEUE_FAILED: status = "FAILED"; break;
166 default: status= "UNEXPECTED"; break;
169 tmp = g_strdup_printf ("%s\"%s\" => [%s]\n",
170 *user_data, info->msg_id, status);
176 modest_tny_send_queue_to_string (ModestTnySendQueue *self)
179 ModestTnySendQueuePrivate *priv;
181 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), NULL);
182 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
184 str = g_strdup_printf ("items in the send queue: %d\n",
185 g_queue_get_length (priv->queue));
187 g_queue_foreach (priv->queue, (GFunc)queue_item_to_string, &str);
193 _on_added_to_outbox (TnySendQueue *self,
199 ModestTnySendQueuePrivate *priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE(self);
200 TnyHeader *header = NULL;
201 SendInfo *info = NULL;
202 GList* existing = NULL;
203 gchar* msg_id = NULL;
205 g_return_if_fail (TNY_IS_SEND_QUEUE(self));
206 g_return_if_fail (TNY_IS_CAMEL_MSG(msg));
208 header = tny_msg_get_header (msg);
209 msg_id = modest_tny_send_queue_get_msg_id (header);
210 g_return_if_fail(msg_id != NULL);
212 /* Put newly added message in WAITING state */
213 existing = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE(self), msg_id);
214 if(existing != NULL) {
215 info = existing->data;
216 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
218 info = g_slice_new (SendInfo);
219 info->msg_id = msg_id;
220 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
221 g_queue_push_tail (priv->queue, info);
224 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
226 g_object_unref(G_OBJECT(header));
230 _add_message (ModestTnySendQueue *self, TnyHeader *header)
232 ModestWindowMgr *mgr = NULL;
233 ModestTnySendQueuePrivate *priv;
234 SendInfo *info = NULL;
235 GList* existing = NULL;
236 gchar* msg_uid = NULL;
237 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
238 gboolean editing = FALSE;
240 g_return_if_fail (TNY_IS_SEND_QUEUE(self));
241 g_return_if_fail (TNY_IS_HEADER(header));
242 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
244 /* Check whether the mail is already in the queue */
245 msg_uid = modest_tny_send_queue_get_msg_id (header);
246 status = modest_tny_send_queue_get_msg_status (self, msg_uid);
248 case MODEST_TNY_SEND_QUEUE_UNKNOWN:
249 case MODEST_TNY_SEND_QUEUE_SUSPENDED:
250 case MODEST_TNY_SEND_QUEUE_FAILED:
252 /* Check if it already exists on queue */
253 existing = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE(self), msg_uid);
257 /* Check if its being edited */
258 mgr = modest_runtime_get_window_mgr ();
259 editing = modest_window_mgr_find_registered_header (mgr, header, NULL);
263 /* Add new meesage info */
264 info = g_slice_new (SendInfo);
265 info->msg_id = strdup(msg_uid);
266 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
267 g_queue_push_tail (priv->queue, info);
278 modest_tny_send_queue_add_async (TnySendQueue *self,
280 TnySendQueueAddCallback callback,
281 TnyStatusCallback status_callback,
284 /* Call the superclass passing our own callback */
285 TNY_CAMEL_SEND_QUEUE_CLASS(parent_class)->add_async (self, msg, _on_added_to_outbox, NULL, NULL);
290 modest_tny_send_queue_get_sentbox (TnySendQueue *self)
292 ModestTnySendQueuePrivate *priv;
294 g_return_val_if_fail (self, NULL);
296 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
298 return g_object_ref (priv->sentbox);
303 modest_tny_send_queue_get_outbox (TnySendQueue *self)
305 ModestTnySendQueuePrivate *priv;
307 g_return_val_if_fail (self, NULL);
309 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
311 return g_object_ref (priv->outbox);
315 modest_tny_send_queue_get_type (void)
317 static GType my_type = 0;
320 static const GTypeInfo my_info = {
321 sizeof(ModestTnySendQueueClass),
322 NULL, /* base init */
323 NULL, /* base finalize */
324 (GClassInitFunc) modest_tny_send_queue_class_init,
325 NULL, /* class finalize */
326 NULL, /* class data */
327 sizeof(ModestTnySendQueue),
329 (GInstanceInitFunc) modest_tny_send_queue_instance_init,
333 my_type = g_type_register_static (TNY_TYPE_CAMEL_SEND_QUEUE,
334 "ModestTnySendQueue",
342 modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass)
344 GObjectClass *gobject_class;
346 gobject_class = (GObjectClass*) klass;
348 parent_class = g_type_class_peek_parent (klass);
349 gobject_class->finalize = modest_tny_send_queue_finalize;
351 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->add_async = modest_tny_send_queue_add_async;
352 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_outbox = modest_tny_send_queue_get_outbox;
353 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_sentbox = modest_tny_send_queue_get_sentbox;
354 klass->status_changed = NULL;
356 signals[STATUS_CHANGED_SIGNAL] =
357 g_signal_new ("status_changed",
358 G_TYPE_FROM_CLASS (gobject_class),
360 G_STRUCT_OFFSET (ModestTnySendQueueClass, status_changed),
362 modest_marshal_VOID__STRING_INT,
363 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
365 g_type_class_add_private (gobject_class, sizeof(ModestTnySendQueuePrivate));
369 modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class)
371 ModestTnySendQueuePrivate *priv;
373 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (instance);
374 priv->queue = g_queue_new();
375 priv->current = NULL;
379 modest_tny_send_queue_finalize (GObject *obj)
381 ModestTnySendQueuePrivate *priv;
383 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj);
385 g_queue_foreach (priv->queue, (GFunc)modest_tny_send_queue_info_free, NULL);
386 g_queue_free (priv->queue);
388 g_object_unref (priv->outbox);
389 g_object_unref (priv->sentbox);
391 G_OBJECT_CLASS(parent_class)->finalize (obj);
395 modest_tny_send_queue_new (TnyCamelTransportAccount *account)
397 ModestTnySendQueue *self = NULL;
398 ModestTnySendQueuePrivate *priv = NULL;
399 TnyIterator *iter = NULL;
400 TnyList *headers = NULL;
402 g_return_val_if_fail (TNY_IS_CAMEL_TRANSPORT_ACCOUNT(account), NULL);
404 self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
406 /* Connect signals to control when a msg is being or has been sent */
407 g_signal_connect (G_OBJECT(self), "msg-sending",
408 G_CALLBACK(_on_msg_start_sending),
410 g_signal_connect (G_OBJECT(self), "msg-sent",
411 G_CALLBACK(_on_msg_has_been_sent),
413 g_signal_connect (G_OBJECT(self), "error-happened",
414 G_CALLBACK(_on_msg_error_happened),
416 g_signal_connect (G_OBJECT (self), "queue-start",
417 G_CALLBACK (_on_queue_start),
420 /* Set outbox and sentbox */
421 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
422 priv->outbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
423 TNY_FOLDER_TYPE_OUTBOX);
424 priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
425 TNY_FOLDER_TYPE_SENT);
428 headers = tny_simple_list_new ();
429 tny_folder_get_headers (priv->outbox, headers, TRUE, NULL);
431 /* Add messages to our internal queue */
432 iter = tny_list_create_iterator (headers);
433 while (!tny_iterator_is_done (iter)) {
434 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
435 _add_message (self, header);
436 g_object_unref (header);
438 tny_iterator_next (iter);
441 /* Reenable suspended items */
442 modest_tny_send_queue_wakeup (self);
445 g_object_unref (headers);
446 g_object_unref (iter);
448 /* Do this at the end, because it'll call tny_send_queue_flush
449 which will call tny_send_queue_get_outbox and
450 tny_send_queue_get_sentbox */
451 tny_camel_send_queue_set_transport_account (TNY_CAMEL_SEND_QUEUE(self),
458 modest_tny_send_queue_msg_is_being_sent (ModestTnySendQueue* self,
461 ModestTnySendQueueStatus status;
463 g_return_val_if_fail (msg_id != NULL, FALSE);
465 status = modest_tny_send_queue_get_msg_status (self, msg_id);
466 return status == MODEST_TNY_SEND_QUEUE_SENDING;
470 modest_tny_send_queue_sending_in_progress (ModestTnySendQueue* self)
472 ModestTnySendQueuePrivate *priv;
474 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), FALSE);
476 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
478 return priv->current != NULL;
481 ModestTnySendQueueStatus
482 modest_tny_send_queue_get_msg_status (ModestTnySendQueue *self, const gchar *msg_id)
486 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), MODEST_TNY_SEND_QUEUE_UNKNOWN);
487 g_return_val_if_fail (msg_id, MODEST_TNY_SEND_QUEUE_UNKNOWN);
489 item = modest_tny_send_queue_lookup_info (self, msg_id);
491 return MODEST_TNY_SEND_QUEUE_UNKNOWN;
493 return ((SendInfo*)item->data)->status;
497 modest_tny_send_queue_get_msg_id (TnyHeader *header)
499 gchar* msg_uid = NULL;
500 const gchar *subject;
501 time_t date_received;
503 g_return_val_if_fail (header && TNY_IS_HEADER(header), NULL);
505 /* Get message uid */
506 subject = tny_header_get_subject (header);
507 date_received = tny_header_get_date_received (header);
509 msg_uid = g_strdup_printf ("%s %d", subject, (int) date_received);
516 _on_msg_start_sending (TnySendQueue *self, TnyHeader *header,
517 TnyMsg *msg, int done, int total, gpointer user_data)
519 ModestTnySendQueuePrivate *priv = NULL;
521 SendInfo *info = NULL;
522 gchar *msg_id = NULL;
524 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
526 /* Get message uid */
527 msg_id = modest_tny_send_queue_get_msg_id (header);
529 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
531 g_warning ("%s: could not get msg-id for header", __FUNCTION__);
534 /* Set current status item */
536 info->status = MODEST_TNY_SEND_QUEUE_SENDING;
537 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
538 priv->current = item;
540 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_id);
547 _on_msg_has_been_sent (TnySendQueue *self,
554 ModestTnySendQueuePrivate *priv;
555 gchar *msg_id = NULL;
558 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
560 /* Get message uid */
561 msg_id = modest_tny_send_queue_get_msg_id (header);
563 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
565 /* Get status info */
566 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
569 /* TODO: note that item=NULL must not happen, but I found that
570 tinymail is issuing the message-sent signal twice, because
571 tny_camel_send_queue_update is called twice for each
572 message sent. This must be fixed in tinymail. Sergio */
574 /* Remove status info */
575 modest_tny_send_queue_info_free (item->data);
576 g_queue_delete_link (priv->queue, item);
577 priv->current = NULL;
579 modest_platform_information_banner (NULL, NULL, _("mcen_ib_message_sent"));
587 _on_msg_error_happened (TnySendQueue *self,
593 ModestTnySendQueuePrivate *priv = NULL;
595 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
597 /* Keep in queue so that we remember that the opertion has failed */
598 /* and was not just cancelled */
599 if (err->code == TNY_SYSTEM_ERROR_CANCEL)
600 info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED;
602 info->status = MODEST_TNY_SEND_QUEUE_FAILED;
603 priv->current = NULL;
605 /* Note that header could be NULL. Tinymail notifies about
606 generic send queue errors with this signal as well, and
607 those notifications are not bound to any particular header
610 SendInfo *info = NULL;
612 gchar* msg_uid = NULL;
614 /* Get sending info (create new if it doesn not exist) */
615 msg_uid = modest_tny_send_queue_get_msg_id (header);
616 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self),
621 /* Notify status has changed */
622 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
630 _on_queue_start (TnySendQueue *self,
633 ModestMailOperation *mail_op;
635 mail_op = modest_mail_operation_new (NULL);
636 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
638 modest_mail_operation_run_queue (mail_op, MODEST_TNY_SEND_QUEUE (self));
639 g_object_unref (mail_op);
643 fill_list_of_caches (gpointer key, gpointer value, gpointer userdata)
645 GSList **send_queues = (GSList **) userdata;
646 *send_queues = g_slist_prepend (*send_queues, value);
649 /* This function shouldn't be here. Move it to another place. Sergio */
650 ModestTnySendQueueStatus
651 modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
653 ModestCacheMgr *cache_mgr = NULL;
654 GHashTable *send_queue_cache = NULL;
655 ModestTnyAccountStore *accounts_store = NULL;
656 TnyList *accounts = NULL;
657 TnyIterator *iter = NULL;
658 TnyTransportAccount *account = NULL;
659 GSList *send_queues = NULL, *node;
660 /* get_msg_status returns suspended by default, so we want to detect changes */
661 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
662 ModestTnySendQueueStatus queue_status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
663 gchar *msg_uid = NULL;
664 ModestTnySendQueue *send_queue = NULL;
666 g_return_val_if_fail (TNY_IS_HEADER(header), MODEST_TNY_SEND_QUEUE_UNKNOWN);
668 msg_uid = modest_tny_send_queue_get_msg_id (header);
669 cache_mgr = modest_runtime_get_cache_mgr ();
670 send_queue_cache = modest_cache_mgr_get_cache (cache_mgr,
671 MODEST_CACHE_MGR_CACHE_TYPE_SEND_QUEUE);
673 g_hash_table_foreach (send_queue_cache, (GHFunc) fill_list_of_caches, &send_queues);
674 if (send_queues == NULL) {
675 accounts = tny_simple_list_new ();
676 accounts_store = modest_runtime_get_account_store ();
677 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(accounts_store),
679 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
681 iter = tny_list_create_iterator (accounts);
682 while (!tny_iterator_is_done (iter)) {
683 account = TNY_TRANSPORT_ACCOUNT(tny_iterator_get_current (iter));
684 send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account));
685 g_object_unref(account);
687 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
688 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
689 status = queue_status;
692 tny_iterator_next (iter);
694 g_object_unref (iter);
695 g_object_unref (accounts);
698 for (node = send_queues; node != NULL; node = g_slist_next (node)) {
699 send_queue = MODEST_TNY_SEND_QUEUE (node->data);
701 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
702 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
703 status = queue_status;
710 g_slist_free (send_queues);
715 modest_tny_send_queue_wakeup (ModestTnySendQueue *self)
717 ModestTnySendQueuePrivate *priv;
721 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
723 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
725 headers = tny_simple_list_new ();
726 tny_folder_get_headers (priv->outbox, headers, TRUE, NULL);
728 /* Wake up every single suspended header */
729 iter = tny_list_create_iterator (headers);
730 while (!tny_iterator_is_done (iter)) {
731 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
733 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_SUSPENDED) {
738 /* Unset the suspended flag */
739 tny_header_unset_flag (header, TNY_HEADER_FLAG_SUSPENDED);
742 msg_id = modest_tny_send_queue_get_msg_id (header);
743 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
744 info = (SendInfo *) item->data;
745 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
746 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
753 g_object_unref (header);
754 tny_iterator_next (iter);
757 /* Make changes persistent on disk */
758 tny_folder_sync_async (priv->outbox, FALSE, NULL, NULL, NULL);
761 g_object_unref (iter);
762 g_object_unref (G_OBJECT (headers));