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;
403 priv->sentbox = NULL;
407 modest_tny_send_queue_finalize (GObject *obj)
409 ModestTnySendQueuePrivate *priv;
411 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj);
413 g_queue_foreach (priv->queue, (GFunc)modest_tny_send_queue_info_free, NULL);
414 g_queue_free (priv->queue);
416 G_OBJECT_CLASS(parent_class)->finalize (obj);
417 g_object_unref (priv->outbox);
418 g_object_unref (priv->sentbox);
422 TnyCamelTransportAccount *account;
423 ModestTnySendQueue *queue;
427 new_queue_get_headers_async_cb (TnyFolder *folder,
433 ModestTnySendQueue *self;
435 GetHeadersInfo *info;
437 info = (GetHeadersInfo *) user_data;
438 self = MODEST_TNY_SEND_QUEUE (info->queue);
440 /* In case of error set the transport account anyway */
441 if (cancelled || err)
444 /* Add messages to our internal queue */
445 iter = tny_list_create_iterator (headers);
446 while (!tny_iterator_is_done (iter)) {
447 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
448 _add_message (self, header);
449 g_object_unref (header);
450 tny_iterator_next (iter);
453 /* Reenable suspended items */
454 modest_tny_send_queue_wakeup (self);
457 g_object_unref (iter);
458 g_object_unref (headers);
461 /* Do this at the end, because it'll call tny_send_queue_flush
462 which will call tny_send_queue_get_outbox and
463 tny_send_queue_get_sentbox */
464 tny_camel_send_queue_set_transport_account (TNY_CAMEL_SEND_QUEUE(self),
468 g_object_unref (info->account);
469 g_object_unref (info->queue);
470 g_slice_free (GetHeadersInfo, info);
474 modest_tny_send_queue_new (TnyCamelTransportAccount *account)
476 ModestTnySendQueue *self = NULL;
477 ModestTnySendQueuePrivate *priv = NULL;
478 TnyList *headers = NULL;
479 GetHeadersInfo *info;
481 g_return_val_if_fail (TNY_IS_CAMEL_TRANSPORT_ACCOUNT(account), NULL);
483 self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
485 /* Set outbox and sentbox */
486 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
487 priv->outbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
488 TNY_FOLDER_TYPE_OUTBOX);
489 priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
490 TNY_FOLDER_TYPE_SENT);
492 /* NOTE that this could happen if there was not enough disk
493 space when the account was created */
494 if (!priv->outbox || !priv->sentbox) {
495 g_object_unref (self);
499 /* Connect signals to control when a msg is being or has been sent */
500 g_signal_connect (G_OBJECT(self), "msg-sending",
501 G_CALLBACK(_on_msg_start_sending),
503 g_signal_connect (G_OBJECT(self), "msg-sent",
504 G_CALLBACK(_on_msg_has_been_sent),
506 g_signal_connect (G_OBJECT(self), "error-happened",
507 G_CALLBACK(_on_msg_error_happened),
509 g_signal_connect (G_OBJECT (self), "queue-start",
510 G_CALLBACK (_on_queue_start),
514 priv->requested_send_receive = FALSE;
516 headers = tny_simple_list_new ();
517 info = g_slice_new0 (GetHeadersInfo);
518 info->account = g_object_ref (account);
519 info->queue = g_object_ref (self);
520 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
521 new_queue_get_headers_async_cb,
528 modest_tny_send_queue_msg_is_being_sent (ModestTnySendQueue* self,
531 ModestTnySendQueueStatus status;
533 g_return_val_if_fail (msg_id != NULL, FALSE);
535 status = modest_tny_send_queue_get_msg_status (self, msg_id);
536 return status == MODEST_TNY_SEND_QUEUE_SENDING;
540 modest_tny_send_queue_sending_in_progress (ModestTnySendQueue* self)
542 ModestTnySendQueuePrivate *priv;
544 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), FALSE);
546 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
548 return priv->current != NULL;
551 ModestTnySendQueueStatus
552 modest_tny_send_queue_get_msg_status (ModestTnySendQueue *self, const gchar *msg_id)
556 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), MODEST_TNY_SEND_QUEUE_UNKNOWN);
557 g_return_val_if_fail (msg_id, MODEST_TNY_SEND_QUEUE_UNKNOWN);
559 item = modest_tny_send_queue_lookup_info (self, msg_id);
561 return MODEST_TNY_SEND_QUEUE_UNKNOWN;
563 return ((SendInfo*)item->data)->status;
567 modest_tny_send_queue_get_msg_id (TnyHeader *header)
569 gchar* msg_uid = NULL;
571 time_t date_received;
573 g_return_val_if_fail (header && TNY_IS_HEADER(header), NULL);
575 /* Get message uid */
576 subject = tny_header_dup_subject (header);
577 date_received = tny_header_get_date_received (header);
579 msg_uid = g_strdup_printf ("%s %d", subject, (int) date_received);
587 _on_msg_start_sending (TnySendQueue *self, TnyHeader *header,
588 TnyMsg *msg, int done, int total, gpointer user_data)
590 ModestTnySendQueuePrivate *priv = NULL;
592 SendInfo *info = NULL;
593 gchar *msg_id = NULL;
595 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
597 /* Get message uid */
598 msg_id = modest_tny_send_queue_get_msg_id (header);
600 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
602 g_warning ("%s: could not get msg-id for header", __FUNCTION__);
605 /* Set current status item */
607 info->status = MODEST_TNY_SEND_QUEUE_SENDING;
608 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
609 priv->current = item;
611 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_id);
618 _on_msg_has_been_sent (TnySendQueue *self,
625 ModestTnySendQueuePrivate *priv;
626 gchar *msg_id = NULL;
629 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
631 /* Get message uid */
632 msg_id = modest_tny_send_queue_get_msg_id (header);
634 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
636 tny_folder_sync_async (priv->sentbox, FALSE, NULL, NULL, NULL);
638 /* Get status info */
639 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
642 /* TODO: note that item=NULL must not happen, but I found that
643 tinymail is issuing the message-sent signal twice, because
644 tny_camel_send_queue_update is called twice for each
645 message sent. This must be fixed in tinymail. Sergio */
647 /* Remove status info */
648 modest_tny_send_queue_info_free (item->data);
649 g_queue_delete_link (priv->queue, item);
650 priv->current = NULL;
652 modest_platform_information_banner (NULL, NULL, _("mcen_ib_message_sent"));
660 _on_msg_error_happened (TnySendQueue *self,
666 ModestTnySendQueuePrivate *priv = NULL;
668 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
670 /* Note that header could be NULL. Tinymail notifies about
671 generic send queue errors with this signal as well, and
672 those notifications are not bound to any particular header
674 if (header && TNY_IS_HEADER (header)) {
675 SendInfo *info = NULL;
677 gchar* msg_uid = NULL;
679 /* Get sending info (create new if it doesn not exist) */
680 msg_uid = modest_tny_send_queue_get_msg_id (header);
681 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self),
684 /* TODO: this should not happen (but it does), so the
685 problem should be located in the way we generate
688 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_uid);
695 /* Keep in queue so that we remember that the opertion has failed */
696 /* and was not just cancelled */
697 if (err->code == TNY_SYSTEM_ERROR_CANCEL) {
698 info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED;
700 if (err->code == TNY_SERVICE_ERROR_CONNECT) {
701 TnyCamelTransportAccount* transport;
702 TnyTransportAccount *conn_specific;
704 transport = tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
707 ModestTnyAccountStore *acc_store;
708 const gchar *acc_name;
710 acc_store = modest_runtime_get_account_store();
711 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
712 conn_specific = (TnyTransportAccount *)
713 modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
715 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
716 tny_account_get_hostname (TNY_ACCOUNT (conn_specific)));
717 g_object_unref (conn_specific);
719 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
720 tny_account_get_hostname (TNY_ACCOUNT (transport)));
722 modest_platform_run_alert_dialog (message, FALSE);
724 g_object_unref (transport);
727 info->status = MODEST_TNY_SEND_QUEUE_FAILED;
729 priv->current = NULL;
731 /* Notify status has changed */
732 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
740 _on_queue_start (TnySendQueue *self,
743 ModestMailOperation *mail_op;
745 mail_op = modest_mail_operation_new (NULL);
746 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
748 modest_mail_operation_run_queue (mail_op, MODEST_TNY_SEND_QUEUE (self));
749 g_object_unref (mail_op);
753 fill_list_of_caches (gpointer key, gpointer value, gpointer userdata)
755 GSList **send_queues = (GSList **) userdata;
756 *send_queues = g_slist_prepend (*send_queues, value);
759 /* This function shouldn't be here. Move it to another place. Sergio */
760 ModestTnySendQueueStatus
761 modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
763 ModestCacheMgr *cache_mgr = NULL;
764 GHashTable *send_queue_cache = NULL;
765 ModestTnyAccountStore *accounts_store = NULL;
766 TnyList *accounts = NULL;
767 TnyIterator *iter = NULL;
768 TnyTransportAccount *account = NULL;
769 GSList *send_queues = NULL, *node;
770 /* get_msg_status returns suspended by default, so we want to detect changes */
771 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
772 ModestTnySendQueueStatus queue_status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
773 gchar *msg_uid = NULL;
774 ModestTnySendQueue *send_queue = NULL;
776 g_return_val_if_fail (TNY_IS_HEADER(header), MODEST_TNY_SEND_QUEUE_UNKNOWN);
778 msg_uid = modest_tny_send_queue_get_msg_id (header);
779 cache_mgr = modest_runtime_get_cache_mgr ();
780 send_queue_cache = modest_cache_mgr_get_cache (cache_mgr,
781 MODEST_CACHE_MGR_CACHE_TYPE_SEND_QUEUE);
783 g_hash_table_foreach (send_queue_cache, (GHFunc) fill_list_of_caches, &send_queues);
784 if (send_queues == NULL) {
785 accounts = tny_simple_list_new ();
786 accounts_store = modest_runtime_get_account_store ();
787 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(accounts_store),
789 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
791 iter = tny_list_create_iterator (accounts);
792 while (!tny_iterator_is_done (iter)) {
793 account = TNY_TRANSPORT_ACCOUNT(tny_iterator_get_current (iter));
794 send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account), TRUE);
795 g_object_unref(account);
796 if (TNY_IS_SEND_QUEUE (send_queue)) {
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;
803 tny_iterator_next (iter);
805 g_object_unref (iter);
806 g_object_unref (accounts);
809 for (node = send_queues; node != NULL; node = g_slist_next (node)) {
810 send_queue = MODEST_TNY_SEND_QUEUE (node->data);
812 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
813 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
814 status = queue_status;
821 g_slist_free (send_queues);
826 wakeup_get_headers_async_cb (TnyFolder *folder,
832 ModestTnySendQueue *self;
833 ModestTnySendQueuePrivate *priv;
836 self = MODEST_TNY_SEND_QUEUE (user_data);
837 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
839 if (cancelled || err) {
840 g_debug ("Failed to wake up the headers of the send queue");
841 g_object_unref (self);
845 /* Wake up every single suspended header */
846 iter = tny_list_create_iterator (headers);
847 while (!tny_iterator_is_done (iter)) {
848 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
850 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_SUSPENDED) {
855 /* Unset the suspended flag */
856 tny_header_unset_flag (header, TNY_HEADER_FLAG_SUSPENDED);
859 msg_id = modest_tny_send_queue_get_msg_id (header);
860 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
862 info = g_slice_new (SendInfo);
863 info->msg_id = msg_id;
864 g_queue_push_tail (priv->queue, info);
866 info = (SendInfo *) item->data;
869 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
870 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
874 g_object_unref (header);
875 tny_iterator_next (iter);
878 /* Make changes persistent on disk */
879 tny_folder_sync_async (priv->outbox, FALSE, NULL, NULL, NULL);
882 g_object_unref (iter);
883 g_object_unref (headers);
884 g_object_unref (self);
889 modest_tny_send_queue_wakeup (ModestTnySendQueue *self)
891 ModestTnySendQueuePrivate *priv;
894 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
896 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
898 headers = tny_simple_list_new ();
899 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
900 wakeup_get_headers_async_cb,
901 NULL, g_object_ref (self));
905 modest_tny_send_queue_get_requested_send_receive (ModestTnySendQueue *self)
907 ModestTnySendQueuePrivate *priv;
909 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE (self), FALSE);
910 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
912 return priv->requested_send_receive;
916 modest_tny_send_queue_set_requested_send_receive (ModestTnySendQueue *self, gboolean requested_send_receive)
918 ModestTnySendQueuePrivate *priv;
920 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
921 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
923 priv->requested_send_receive = requested_send_receive;