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 */
109 /* last was send receive operation?*/
110 gboolean requested_send_receive;
113 #define MODEST_TNY_SEND_QUEUE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
114 MODEST_TYPE_TNY_SEND_QUEUE, \
115 ModestTnySendQueuePrivate))
118 static TnyCamelSendQueueClass *parent_class = NULL;
120 /* uncomment the following if you have defined any signals */
121 static guint signals[LAST_SIGNAL] = {0};
124 * this thread actually tries to send all the mails in the outbox and keeps
125 * track of their state.
129 on_modest_tny_send_queue_compare_id (gconstpointer info, gconstpointer msg_id)
131 g_return_val_if_fail (info && ((SendInfo*)info)->msg_id && msg_id, -1);
133 return strcmp( ((SendInfo*)info)->msg_id, msg_id);
137 modest_tny_send_queue_info_free (SendInfo *info)
139 g_free(info->msg_id);
140 g_slice_free(SendInfo, info);
144 modest_tny_send_queue_lookup_info (ModestTnySendQueue *self, const gchar *msg_id)
146 ModestTnySendQueuePrivate *priv;
147 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
149 return g_queue_find_custom (priv->queue, msg_id, on_modest_tny_send_queue_compare_id);
154 queue_item_to_string (gpointer data, gchar **user_data)
156 SendInfo *info = (SendInfo*)data;
160 if (!(user_data && *user_data))
163 switch (info->status) {
164 case MODEST_TNY_SEND_QUEUE_UNKNOWN: status = "UNKNOWN"; break;
165 case MODEST_TNY_SEND_QUEUE_WAITING: status = "WAITING"; break;
166 case MODEST_TNY_SEND_QUEUE_SUSPENDED: status = "SUSPENDED"; break;
167 case MODEST_TNY_SEND_QUEUE_SENDING: status = "SENDING"; break;
168 case MODEST_TNY_SEND_QUEUE_FAILED: status = "FAILED"; break;
169 default: status= "UNEXPECTED"; break;
172 tmp = g_strdup_printf ("%s\"%s\" => [%s]\n",
173 *user_data, info->msg_id, status);
179 modest_tny_send_queue_to_string (ModestTnySendQueue *self)
182 ModestTnySendQueuePrivate *priv;
184 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), NULL);
185 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
187 str = g_strdup_printf ("items in the send queue: %d\n",
188 g_queue_get_length (priv->queue));
190 g_queue_foreach (priv->queue, (GFunc)queue_item_to_string, &str);
196 TnySendQueueAddCallback callback;
201 _on_added_to_outbox (TnySendQueue *self,
207 ModestTnySendQueuePrivate *priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE(self);
208 TnyHeader *header = NULL;
209 SendInfo *info = NULL;
210 GList* existing = NULL;
211 gchar* msg_id = NULL;
212 AddAsyncHelper *helper;
214 g_return_if_fail (TNY_IS_SEND_QUEUE(self));
215 g_return_if_fail (TNY_IS_CAMEL_MSG(msg));
217 header = tny_msg_get_header (msg);
218 msg_id = modest_tny_send_queue_get_msg_id (header);
220 g_warning ("%s: No msg_id returned for header", __FUNCTION__);
224 /* Put newly added message in WAITING state */
225 existing = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE(self), msg_id);
226 if(existing != NULL) {
227 info = existing->data;
228 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
230 info = g_slice_new (SendInfo);
231 info->msg_id = msg_id;
232 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
233 g_queue_push_tail (priv->queue, info);
236 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
239 g_object_unref (G_OBJECT(header));
241 /* Call the user callback */
242 helper = (AddAsyncHelper *) user_data;
243 if (helper->callback)
244 helper->callback (self, cancelled, msg, err, helper->user_data);
245 g_slice_free (AddAsyncHelper, helper);
249 _add_message (ModestTnySendQueue *self, TnyHeader *header)
251 ModestWindowMgr *mgr = NULL;
252 ModestTnySendQueuePrivate *priv;
253 SendInfo *info = NULL;
254 GList* existing = NULL;
255 gchar* msg_uid = NULL;
256 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
257 gboolean editing = FALSE;
259 g_return_if_fail (TNY_IS_SEND_QUEUE(self));
260 g_return_if_fail (TNY_IS_HEADER(header));
261 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
263 /* Check whether the mail is already in the queue */
264 msg_uid = modest_tny_send_queue_get_msg_id (header);
265 status = modest_tny_send_queue_get_msg_status (self, msg_uid);
267 case MODEST_TNY_SEND_QUEUE_UNKNOWN:
268 case MODEST_TNY_SEND_QUEUE_SUSPENDED:
269 case MODEST_TNY_SEND_QUEUE_FAILED:
271 /* Check if it already exists on queue */
272 existing = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE(self), msg_uid);
276 /* Check if its being edited */
277 mgr = modest_runtime_get_window_mgr ();
278 editing = modest_window_mgr_find_registered_header (mgr, header, NULL);
282 /* Add new meesage info */
283 info = g_slice_new0 (SendInfo);
284 info->msg_id = strdup(msg_uid);
285 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
286 g_queue_push_tail (priv->queue, info);
297 modest_tny_send_queue_add_async (TnySendQueue *self,
299 TnySendQueueAddCallback callback,
300 TnyStatusCallback status_callback,
303 AddAsyncHelper *helper = g_slice_new0 (AddAsyncHelper);
304 helper->callback = callback;
305 helper->user_data = user_data;
307 /* Call the superclass passing our own callback */
308 TNY_CAMEL_SEND_QUEUE_CLASS(parent_class)->add_async (self, msg,
316 modest_tny_send_queue_get_sentbox (TnySendQueue *self)
318 ModestTnySendQueuePrivate *priv;
320 g_return_val_if_fail (self, NULL);
322 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
324 return g_object_ref (priv->sentbox);
329 modest_tny_send_queue_get_outbox (TnySendQueue *self)
331 ModestTnySendQueuePrivate *priv;
333 g_return_val_if_fail (self, NULL);
335 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
337 return g_object_ref (priv->outbox);
341 modest_tny_send_queue_get_type (void)
343 static GType my_type = 0;
346 static const GTypeInfo my_info = {
347 sizeof(ModestTnySendQueueClass),
348 NULL, /* base init */
349 NULL, /* base finalize */
350 (GClassInitFunc) modest_tny_send_queue_class_init,
351 NULL, /* class finalize */
352 NULL, /* class data */
353 sizeof(ModestTnySendQueue),
355 (GInstanceInitFunc) modest_tny_send_queue_instance_init,
359 my_type = g_type_register_static (TNY_TYPE_CAMEL_SEND_QUEUE,
360 "ModestTnySendQueue",
368 modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass)
370 GObjectClass *gobject_class;
372 gobject_class = (GObjectClass*) klass;
374 parent_class = g_type_class_peek_parent (klass);
375 gobject_class->finalize = modest_tny_send_queue_finalize;
377 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->add_async = modest_tny_send_queue_add_async;
378 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_outbox = modest_tny_send_queue_get_outbox;
379 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_sentbox = modest_tny_send_queue_get_sentbox;
380 klass->status_changed = NULL;
382 signals[STATUS_CHANGED_SIGNAL] =
383 g_signal_new ("status_changed",
384 G_TYPE_FROM_CLASS (gobject_class),
386 G_STRUCT_OFFSET (ModestTnySendQueueClass, status_changed),
388 modest_marshal_VOID__STRING_INT,
389 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
391 g_type_class_add_private (gobject_class, sizeof(ModestTnySendQueuePrivate));
395 modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class)
397 ModestTnySendQueuePrivate *priv;
399 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (instance);
400 priv->queue = g_queue_new();
401 priv->current = NULL;
405 modest_tny_send_queue_finalize (GObject *obj)
407 ModestTnySendQueuePrivate *priv;
409 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj);
411 g_queue_foreach (priv->queue, (GFunc)modest_tny_send_queue_info_free, NULL);
412 g_queue_free (priv->queue);
414 g_object_unref (priv->outbox);
415 g_object_unref (priv->sentbox);
417 G_OBJECT_CLASS(parent_class)->finalize (obj);
421 TnyCamelTransportAccount *account;
422 ModestTnySendQueue *queue;
426 new_queue_get_headers_async_cb (TnyFolder *folder,
432 ModestTnySendQueue *self;
434 GetHeadersInfo *info;
436 info = (GetHeadersInfo *) user_data;
437 self = MODEST_TNY_SEND_QUEUE (info->queue);
439 /* In case of error set the transport account anyway */
440 if (cancelled || err)
443 /* Add messages to our internal queue */
444 iter = tny_list_create_iterator (headers);
445 while (!tny_iterator_is_done (iter)) {
446 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
447 _add_message (self, header);
448 g_object_unref (header);
449 tny_iterator_next (iter);
452 /* Reenable suspended items */
453 modest_tny_send_queue_wakeup (self);
456 g_object_unref (iter);
457 g_object_unref (headers);
460 /* Do this at the end, because it'll call tny_send_queue_flush
461 which will call tny_send_queue_get_outbox and
462 tny_send_queue_get_sentbox */
463 tny_camel_send_queue_set_transport_account (TNY_CAMEL_SEND_QUEUE(self),
467 g_object_unref (info->account);
468 g_object_unref (info->queue);
469 g_slice_free (GetHeadersInfo, info);
473 modest_tny_send_queue_new (TnyCamelTransportAccount *account)
475 ModestTnySendQueue *self = NULL;
476 ModestTnySendQueuePrivate *priv = NULL;
477 TnyList *headers = NULL;
478 GetHeadersInfo *info;
480 g_return_val_if_fail (TNY_IS_CAMEL_TRANSPORT_ACCOUNT(account), NULL);
482 self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
484 /* Set outbox and sentbox */
485 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
486 priv->outbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
487 TNY_FOLDER_TYPE_OUTBOX);
488 priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
489 TNY_FOLDER_TYPE_SENT);
491 /* NOTE that this could happen if there was not enough disk
492 space when the account was created */
493 if (!priv->outbox || !priv->sentbox) {
494 g_object_unref (self);
498 /* Connect signals to control when a msg is being or has been sent */
499 g_signal_connect (G_OBJECT(self), "msg-sending",
500 G_CALLBACK(_on_msg_start_sending),
502 g_signal_connect (G_OBJECT(self), "msg-sent",
503 G_CALLBACK(_on_msg_has_been_sent),
505 g_signal_connect (G_OBJECT(self), "error-happened",
506 G_CALLBACK(_on_msg_error_happened),
508 g_signal_connect (G_OBJECT (self), "queue-start",
509 G_CALLBACK (_on_queue_start),
513 priv->requested_send_receive = FALSE;
515 headers = tny_simple_list_new ();
516 info = g_slice_new0 (GetHeadersInfo);
517 info->account = g_object_ref (account);
518 info->queue = g_object_ref (self);
519 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
520 new_queue_get_headers_async_cb,
527 modest_tny_send_queue_msg_is_being_sent (ModestTnySendQueue* self,
530 ModestTnySendQueueStatus status;
532 g_return_val_if_fail (msg_id != NULL, FALSE);
534 status = modest_tny_send_queue_get_msg_status (self, msg_id);
535 return status == MODEST_TNY_SEND_QUEUE_SENDING;
539 modest_tny_send_queue_sending_in_progress (ModestTnySendQueue* self)
541 ModestTnySendQueuePrivate *priv;
543 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), FALSE);
545 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
547 return priv->current != NULL;
550 ModestTnySendQueueStatus
551 modest_tny_send_queue_get_msg_status (ModestTnySendQueue *self, const gchar *msg_id)
555 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), MODEST_TNY_SEND_QUEUE_UNKNOWN);
556 g_return_val_if_fail (msg_id, MODEST_TNY_SEND_QUEUE_UNKNOWN);
558 item = modest_tny_send_queue_lookup_info (self, msg_id);
560 return MODEST_TNY_SEND_QUEUE_UNKNOWN;
562 return ((SendInfo*)item->data)->status;
566 modest_tny_send_queue_get_msg_id (TnyHeader *header)
568 gchar* msg_uid = NULL;
570 time_t date_received;
572 g_return_val_if_fail (header && TNY_IS_HEADER(header), NULL);
574 /* Get message uid */
575 subject = tny_header_dup_subject (header);
576 date_received = tny_header_get_date_received (header);
578 msg_uid = g_strdup_printf ("%s %d", subject, (int) date_received);
586 _on_msg_start_sending (TnySendQueue *self, TnyHeader *header,
587 TnyMsg *msg, int done, int total, gpointer user_data)
589 ModestTnySendQueuePrivate *priv = NULL;
591 SendInfo *info = NULL;
592 gchar *msg_id = NULL;
594 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
596 /* Get message uid */
597 msg_id = modest_tny_send_queue_get_msg_id (header);
599 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
601 g_warning ("%s: could not get msg-id for header", __FUNCTION__);
604 /* Set current status item */
606 info->status = MODEST_TNY_SEND_QUEUE_SENDING;
607 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
608 priv->current = item;
610 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_id);
617 _on_msg_has_been_sent (TnySendQueue *self,
624 ModestTnySendQueuePrivate *priv;
625 gchar *msg_id = NULL;
628 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
630 /* Get message uid */
631 msg_id = modest_tny_send_queue_get_msg_id (header);
633 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
635 tny_folder_sync_async (priv->sentbox, FALSE, NULL, NULL, NULL);
637 /* Get status info */
638 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
641 /* TODO: note that item=NULL must not happen, but I found that
642 tinymail is issuing the message-sent signal twice, because
643 tny_camel_send_queue_update is called twice for each
644 message sent. This must be fixed in tinymail. Sergio */
646 /* Remove status info */
647 modest_tny_send_queue_info_free (item->data);
648 g_queue_delete_link (priv->queue, item);
649 priv->current = NULL;
651 modest_platform_information_banner (NULL, NULL, _("mcen_ib_message_sent"));
659 _on_msg_error_happened (TnySendQueue *self,
665 ModestTnySendQueuePrivate *priv = NULL;
667 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
669 /* Note that header could be NULL. Tinymail notifies about
670 generic send queue errors with this signal as well, and
671 those notifications are not bound to any particular header
673 if (header && TNY_IS_HEADER (header)) {
674 SendInfo *info = NULL;
676 gchar* msg_uid = NULL;
678 /* Get sending info (create new if it doesn not exist) */
679 msg_uid = modest_tny_send_queue_get_msg_id (header);
680 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self),
683 /* TODO: this should not happen (but it does), so the
684 problem should be located in the way we generate
687 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_uid);
694 /* Keep in queue so that we remember that the opertion has failed */
695 /* and was not just cancelled */
696 if (err->code == TNY_SYSTEM_ERROR_CANCEL) {
697 info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED;
699 if (err->code == TNY_SERVICE_ERROR_CONNECT) {
700 TnyCamelTransportAccount* transport;
702 transport = tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
705 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
706 tny_account_get_hostname (TNY_ACCOUNT (transport)));
707 modest_platform_run_alert_dialog (message, FALSE);
709 g_object_unref (transport);
712 info->status = MODEST_TNY_SEND_QUEUE_FAILED;
714 priv->current = NULL;
716 /* Notify status has changed */
717 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
725 _on_queue_start (TnySendQueue *self,
728 ModestMailOperation *mail_op;
730 mail_op = modest_mail_operation_new (NULL);
731 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
733 modest_mail_operation_run_queue (mail_op, MODEST_TNY_SEND_QUEUE (self));
734 g_object_unref (mail_op);
738 fill_list_of_caches (gpointer key, gpointer value, gpointer userdata)
740 GSList **send_queues = (GSList **) userdata;
741 *send_queues = g_slist_prepend (*send_queues, value);
744 /* This function shouldn't be here. Move it to another place. Sergio */
745 ModestTnySendQueueStatus
746 modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
748 ModestCacheMgr *cache_mgr = NULL;
749 GHashTable *send_queue_cache = NULL;
750 ModestTnyAccountStore *accounts_store = NULL;
751 TnyList *accounts = NULL;
752 TnyIterator *iter = NULL;
753 TnyTransportAccount *account = NULL;
754 GSList *send_queues = NULL, *node;
755 /* get_msg_status returns suspended by default, so we want to detect changes */
756 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
757 ModestTnySendQueueStatus queue_status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
758 gchar *msg_uid = NULL;
759 ModestTnySendQueue *send_queue = NULL;
761 g_return_val_if_fail (TNY_IS_HEADER(header), MODEST_TNY_SEND_QUEUE_UNKNOWN);
763 msg_uid = modest_tny_send_queue_get_msg_id (header);
764 cache_mgr = modest_runtime_get_cache_mgr ();
765 send_queue_cache = modest_cache_mgr_get_cache (cache_mgr,
766 MODEST_CACHE_MGR_CACHE_TYPE_SEND_QUEUE);
768 g_hash_table_foreach (send_queue_cache, (GHFunc) fill_list_of_caches, &send_queues);
769 if (send_queues == NULL) {
770 accounts = tny_simple_list_new ();
771 accounts_store = modest_runtime_get_account_store ();
772 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(accounts_store),
774 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
776 iter = tny_list_create_iterator (accounts);
777 while (!tny_iterator_is_done (iter)) {
778 account = TNY_TRANSPORT_ACCOUNT(tny_iterator_get_current (iter));
779 send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account), TRUE);
780 g_object_unref(account);
781 if (TNY_IS_SEND_QUEUE (send_queue)) {
782 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
783 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
784 status = queue_status;
788 tny_iterator_next (iter);
790 g_object_unref (iter);
791 g_object_unref (accounts);
794 for (node = send_queues; node != NULL; node = g_slist_next (node)) {
795 send_queue = MODEST_TNY_SEND_QUEUE (node->data);
797 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
798 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
799 status = queue_status;
806 g_slist_free (send_queues);
811 wakeup_get_headers_async_cb (TnyFolder *folder,
817 ModestTnySendQueue *self;
818 ModestTnySendQueuePrivate *priv;
821 self = MODEST_TNY_SEND_QUEUE (user_data);
822 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
824 if (cancelled || err) {
825 g_debug ("Failed to wake up the headers of the send queue");
826 g_object_unref (self);
830 /* Wake up every single suspended header */
831 iter = tny_list_create_iterator (headers);
832 while (!tny_iterator_is_done (iter)) {
833 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
835 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_SUSPENDED) {
840 /* Unset the suspended flag */
841 tny_header_unset_flag (header, TNY_HEADER_FLAG_SUSPENDED);
844 msg_id = modest_tny_send_queue_get_msg_id (header);
845 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
846 info = (SendInfo *) item->data;
847 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
848 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
855 g_object_unref (header);
856 tny_iterator_next (iter);
859 /* Make changes persistent on disk */
860 tny_folder_sync_async (priv->outbox, FALSE, NULL, NULL, NULL);
863 g_object_unref (iter);
864 g_object_unref (headers);
865 g_object_unref (self);
870 modest_tny_send_queue_wakeup (ModestTnySendQueue *self)
872 ModestTnySendQueuePrivate *priv;
875 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
877 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
879 headers = tny_simple_list_new ();
880 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
881 wakeup_get_headers_async_cb,
882 NULL, g_object_ref (self));
886 modest_tny_send_queue_get_requested_send_receive (ModestTnySendQueue *self)
888 ModestTnySendQueuePrivate *priv;
890 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE (self), FALSE);
891 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
893 return priv->requested_send_receive;
897 modest_tny_send_queue_set_requested_send_receive (ModestTnySendQueue *self, gboolean requested_send_receive)
899 ModestTnySendQueuePrivate *priv;
901 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
902 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
904 priv->requested_send_receive = requested_send_receive;