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_CLASS(parent_class)->finalize (obj);
415 g_object_unref (priv->outbox);
416 g_object_unref (priv->sentbox);
420 TnyCamelTransportAccount *account;
421 ModestTnySendQueue *queue;
425 new_queue_get_headers_async_cb (TnyFolder *folder,
431 ModestTnySendQueue *self;
433 GetHeadersInfo *info;
435 info = (GetHeadersInfo *) user_data;
436 self = MODEST_TNY_SEND_QUEUE (info->queue);
438 /* In case of error set the transport account anyway */
439 if (cancelled || err)
442 /* Add messages to our internal queue */
443 iter = tny_list_create_iterator (headers);
444 while (!tny_iterator_is_done (iter)) {
445 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
446 _add_message (self, header);
447 g_object_unref (header);
448 tny_iterator_next (iter);
451 /* Reenable suspended items */
452 modest_tny_send_queue_wakeup (self);
455 g_object_unref (iter);
456 g_object_unref (headers);
459 /* Do this at the end, because it'll call tny_send_queue_flush
460 which will call tny_send_queue_get_outbox and
461 tny_send_queue_get_sentbox */
462 tny_camel_send_queue_set_transport_account (TNY_CAMEL_SEND_QUEUE(self),
466 g_object_unref (info->account);
467 g_object_unref (info->queue);
468 g_slice_free (GetHeadersInfo, info);
472 modest_tny_send_queue_new (TnyCamelTransportAccount *account)
474 ModestTnySendQueue *self = NULL;
475 ModestTnySendQueuePrivate *priv = NULL;
476 TnyList *headers = NULL;
477 GetHeadersInfo *info;
479 g_return_val_if_fail (TNY_IS_CAMEL_TRANSPORT_ACCOUNT(account), NULL);
481 self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
483 /* Set outbox and sentbox */
484 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
485 priv->outbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
486 TNY_FOLDER_TYPE_OUTBOX);
487 priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
488 TNY_FOLDER_TYPE_SENT);
490 /* NOTE that this could happen if there was not enough disk
491 space when the account was created */
492 if (!priv->outbox || !priv->sentbox) {
493 g_object_unref (self);
497 /* Connect signals to control when a msg is being or has been sent */
498 g_signal_connect (G_OBJECT(self), "msg-sending",
499 G_CALLBACK(_on_msg_start_sending),
501 g_signal_connect (G_OBJECT(self), "msg-sent",
502 G_CALLBACK(_on_msg_has_been_sent),
504 g_signal_connect (G_OBJECT(self), "error-happened",
505 G_CALLBACK(_on_msg_error_happened),
507 g_signal_connect (G_OBJECT (self), "queue-start",
508 G_CALLBACK (_on_queue_start),
512 priv->requested_send_receive = FALSE;
514 headers = tny_simple_list_new ();
515 info = g_slice_new0 (GetHeadersInfo);
516 info->account = g_object_ref (account);
517 info->queue = g_object_ref (self);
518 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
519 new_queue_get_headers_async_cb,
526 modest_tny_send_queue_msg_is_being_sent (ModestTnySendQueue* self,
529 ModestTnySendQueueStatus status;
531 g_return_val_if_fail (msg_id != NULL, FALSE);
533 status = modest_tny_send_queue_get_msg_status (self, msg_id);
534 return status == MODEST_TNY_SEND_QUEUE_SENDING;
538 modest_tny_send_queue_sending_in_progress (ModestTnySendQueue* self)
540 ModestTnySendQueuePrivate *priv;
542 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), FALSE);
544 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
546 return priv->current != NULL;
549 ModestTnySendQueueStatus
550 modest_tny_send_queue_get_msg_status (ModestTnySendQueue *self, const gchar *msg_id)
554 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), MODEST_TNY_SEND_QUEUE_UNKNOWN);
555 g_return_val_if_fail (msg_id, MODEST_TNY_SEND_QUEUE_UNKNOWN);
557 item = modest_tny_send_queue_lookup_info (self, msg_id);
559 return MODEST_TNY_SEND_QUEUE_UNKNOWN;
561 return ((SendInfo*)item->data)->status;
565 modest_tny_send_queue_get_msg_id (TnyHeader *header)
567 gchar* msg_uid = NULL;
569 time_t date_received;
571 g_return_val_if_fail (header && TNY_IS_HEADER(header), NULL);
573 /* Get message uid */
574 subject = tny_header_dup_subject (header);
575 date_received = tny_header_get_date_received (header);
577 msg_uid = g_strdup_printf ("%s %d", subject, (int) date_received);
585 _on_msg_start_sending (TnySendQueue *self, TnyHeader *header,
586 TnyMsg *msg, int done, int total, gpointer user_data)
588 ModestTnySendQueuePrivate *priv = NULL;
590 SendInfo *info = NULL;
591 gchar *msg_id = NULL;
593 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
595 /* Get message uid */
596 msg_id = modest_tny_send_queue_get_msg_id (header);
598 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
600 g_warning ("%s: could not get msg-id for header", __FUNCTION__);
603 /* Set current status item */
605 info->status = MODEST_TNY_SEND_QUEUE_SENDING;
606 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
607 priv->current = item;
609 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_id);
616 _on_msg_has_been_sent (TnySendQueue *self,
623 ModestTnySendQueuePrivate *priv;
624 gchar *msg_id = NULL;
627 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
629 /* Get message uid */
630 msg_id = modest_tny_send_queue_get_msg_id (header);
632 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
634 tny_folder_sync_async (priv->sentbox, FALSE, NULL, NULL, NULL);
636 /* Get status info */
637 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
640 /* TODO: note that item=NULL must not happen, but I found that
641 tinymail is issuing the message-sent signal twice, because
642 tny_camel_send_queue_update is called twice for each
643 message sent. This must be fixed in tinymail. Sergio */
645 /* Remove status info */
646 modest_tny_send_queue_info_free (item->data);
647 g_queue_delete_link (priv->queue, item);
648 priv->current = NULL;
650 modest_platform_information_banner (NULL, NULL, _("mcen_ib_message_sent"));
658 _on_msg_error_happened (TnySendQueue *self,
664 ModestTnySendQueuePrivate *priv = NULL;
666 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
668 /* Note that header could be NULL. Tinymail notifies about
669 generic send queue errors with this signal as well, and
670 those notifications are not bound to any particular header
672 if (header && TNY_IS_HEADER (header)) {
673 SendInfo *info = NULL;
675 gchar* msg_uid = NULL;
677 /* Get sending info (create new if it doesn not exist) */
678 msg_uid = modest_tny_send_queue_get_msg_id (header);
679 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self),
682 /* TODO: this should not happen (but it does), so the
683 problem should be located in the way we generate
686 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_uid);
693 /* Keep in queue so that we remember that the opertion has failed */
694 /* and was not just cancelled */
695 if (err->code == TNY_SYSTEM_ERROR_CANCEL) {
696 info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED;
698 if (err->code == TNY_SERVICE_ERROR_CONNECT) {
699 TnyCamelTransportAccount* transport;
700 TnyTransportAccount *conn_specific;
702 transport = tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
705 ModestTnyAccountStore *acc_store;
706 const gchar *acc_name;
708 acc_store = modest_runtime_get_account_store();
709 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
710 conn_specific = (TnyTransportAccount *)
711 modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
713 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
714 tny_account_get_hostname (TNY_ACCOUNT (conn_specific)));
715 g_object_unref (conn_specific);
717 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
718 tny_account_get_hostname (TNY_ACCOUNT (transport)));
720 modest_platform_run_alert_dialog (message, FALSE);
722 g_object_unref (transport);
725 info->status = MODEST_TNY_SEND_QUEUE_FAILED;
727 priv->current = NULL;
729 /* Notify status has changed */
730 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
738 _on_queue_start (TnySendQueue *self,
741 ModestMailOperation *mail_op;
743 mail_op = modest_mail_operation_new (NULL);
744 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
746 modest_mail_operation_run_queue (mail_op, MODEST_TNY_SEND_QUEUE (self));
747 g_object_unref (mail_op);
751 fill_list_of_caches (gpointer key, gpointer value, gpointer userdata)
753 GSList **send_queues = (GSList **) userdata;
754 *send_queues = g_slist_prepend (*send_queues, value);
757 /* This function shouldn't be here. Move it to another place. Sergio */
758 ModestTnySendQueueStatus
759 modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
761 ModestCacheMgr *cache_mgr = NULL;
762 GHashTable *send_queue_cache = NULL;
763 ModestTnyAccountStore *accounts_store = NULL;
764 TnyList *accounts = NULL;
765 TnyIterator *iter = NULL;
766 TnyTransportAccount *account = NULL;
767 GSList *send_queues = NULL, *node;
768 /* get_msg_status returns suspended by default, so we want to detect changes */
769 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
770 ModestTnySendQueueStatus queue_status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
771 gchar *msg_uid = NULL;
772 ModestTnySendQueue *send_queue = NULL;
774 g_return_val_if_fail (TNY_IS_HEADER(header), MODEST_TNY_SEND_QUEUE_UNKNOWN);
776 msg_uid = modest_tny_send_queue_get_msg_id (header);
777 cache_mgr = modest_runtime_get_cache_mgr ();
778 send_queue_cache = modest_cache_mgr_get_cache (cache_mgr,
779 MODEST_CACHE_MGR_CACHE_TYPE_SEND_QUEUE);
781 g_hash_table_foreach (send_queue_cache, (GHFunc) fill_list_of_caches, &send_queues);
782 if (send_queues == NULL) {
783 accounts = tny_simple_list_new ();
784 accounts_store = modest_runtime_get_account_store ();
785 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(accounts_store),
787 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
789 iter = tny_list_create_iterator (accounts);
790 while (!tny_iterator_is_done (iter)) {
791 account = TNY_TRANSPORT_ACCOUNT(tny_iterator_get_current (iter));
792 send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account), TRUE);
793 g_object_unref(account);
794 if (TNY_IS_SEND_QUEUE (send_queue)) {
795 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
796 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
797 status = queue_status;
801 tny_iterator_next (iter);
803 g_object_unref (iter);
804 g_object_unref (accounts);
807 for (node = send_queues; node != NULL; node = g_slist_next (node)) {
808 send_queue = MODEST_TNY_SEND_QUEUE (node->data);
810 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
811 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
812 status = queue_status;
819 g_slist_free (send_queues);
824 wakeup_get_headers_async_cb (TnyFolder *folder,
830 ModestTnySendQueue *self;
831 ModestTnySendQueuePrivate *priv;
834 self = MODEST_TNY_SEND_QUEUE (user_data);
835 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
837 if (cancelled || err) {
838 g_debug ("Failed to wake up the headers of the send queue");
839 g_object_unref (self);
843 /* Wake up every single suspended header */
844 iter = tny_list_create_iterator (headers);
845 while (!tny_iterator_is_done (iter)) {
846 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
848 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_SUSPENDED) {
853 /* Unset the suspended flag */
854 tny_header_unset_flag (header, TNY_HEADER_FLAG_SUSPENDED);
857 msg_id = modest_tny_send_queue_get_msg_id (header);
858 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
859 info = (SendInfo *) item->data;
860 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
861 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
868 g_object_unref (header);
869 tny_iterator_next (iter);
872 /* Make changes persistent on disk */
873 tny_folder_sync_async (priv->outbox, FALSE, NULL, NULL, NULL);
876 g_object_unref (iter);
877 g_object_unref (headers);
878 g_object_unref (self);
883 modest_tny_send_queue_wakeup (ModestTnySendQueue *self)
885 ModestTnySendQueuePrivate *priv;
888 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
890 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
892 headers = tny_simple_list_new ();
893 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
894 wakeup_get_headers_async_cb,
895 NULL, g_object_ref (self));
899 modest_tny_send_queue_get_requested_send_receive (ModestTnySendQueue *self)
901 ModestTnySendQueuePrivate *priv;
903 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE (self), FALSE);
904 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
906 return priv->requested_send_receive;
910 modest_tny_send_queue_set_requested_send_receive (ModestTnySendQueue *self, gboolean requested_send_receive)
912 ModestTnySendQueuePrivate *priv;
914 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
915 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
917 priv->requested_send_receive = requested_send_receive;