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 _on_queue_stop (TnySendQueue *self,
79 static void modest_tny_send_queue_add_async (TnySendQueue *self,
81 TnySendQueueAddCallback callback,
82 TnyStatusCallback status_callback,
85 static TnyFolder* modest_tny_send_queue_get_outbox (TnySendQueue *self);
86 static TnyFolder* modest_tny_send_queue_get_sentbox (TnySendQueue *self);
90 STATUS_CHANGED_SIGNAL,
94 typedef struct _SendInfo SendInfo;
97 ModestTnySendQueueStatus status;
100 typedef struct _ModestTnySendQueuePrivate ModestTnySendQueuePrivate;
101 struct _ModestTnySendQueuePrivate {
105 /* The info that is currently being sent */
108 /* Special folders */
112 /* last was send receive operation?*/
113 gboolean requested_send_receive;
118 #define MODEST_TNY_SEND_QUEUE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
119 MODEST_TYPE_TNY_SEND_QUEUE, \
120 ModestTnySendQueuePrivate))
123 static TnyCamelSendQueueClass *parent_class = NULL;
125 /* uncomment the following if you have defined any signals */
126 static guint signals[LAST_SIGNAL] = {0};
129 * this thread actually tries to send all the mails in the outbox and keeps
130 * track of their state.
134 on_modest_tny_send_queue_compare_id (gconstpointer info, gconstpointer msg_id)
136 g_return_val_if_fail (info && ((SendInfo*)info)->msg_id && msg_id, -1);
138 return strcmp( ((SendInfo*)info)->msg_id, msg_id);
142 modest_tny_send_queue_info_free (SendInfo *info)
144 g_free(info->msg_id);
145 g_slice_free(SendInfo, info);
149 modest_tny_send_queue_lookup_info (ModestTnySendQueue *self, const gchar *msg_id)
151 ModestTnySendQueuePrivate *priv;
152 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
154 return g_queue_find_custom (priv->queue, msg_id, on_modest_tny_send_queue_compare_id);
159 queue_item_to_string (gpointer data, gchar **user_data)
161 SendInfo *info = (SendInfo*)data;
165 if (!(user_data && *user_data))
168 switch (info->status) {
169 case MODEST_TNY_SEND_QUEUE_UNKNOWN: status = "UNKNOWN"; break;
170 case MODEST_TNY_SEND_QUEUE_WAITING: status = "WAITING"; break;
171 case MODEST_TNY_SEND_QUEUE_SUSPENDED: status = "SUSPENDED"; break;
172 case MODEST_TNY_SEND_QUEUE_SENDING: status = "SENDING"; break;
173 case MODEST_TNY_SEND_QUEUE_FAILED: status = "FAILED"; break;
174 default: status= "UNEXPECTED"; break;
177 tmp = g_strdup_printf ("%s\"%s\" => [%s]\n",
178 *user_data, info->msg_id, status);
184 modest_tny_send_queue_to_string (ModestTnySendQueue *self)
187 ModestTnySendQueuePrivate *priv;
189 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), NULL);
190 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
192 str = g_strdup_printf ("items in the send queue: %d\n",
193 g_queue_get_length (priv->queue));
195 g_queue_foreach (priv->queue, (GFunc)queue_item_to_string, &str);
201 TnySendQueueAddCallback callback;
206 _on_added_to_outbox (TnySendQueue *self,
212 ModestTnySendQueuePrivate *priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE(self);
213 TnyHeader *header = NULL;
214 SendInfo *info = NULL;
215 GList* existing = NULL;
216 gchar* msg_id = NULL;
217 AddAsyncHelper *helper;
219 g_return_if_fail (TNY_IS_SEND_QUEUE(self));
220 g_return_if_fail (TNY_IS_CAMEL_MSG(msg));
222 header = tny_msg_get_header (msg);
223 msg_id = modest_tny_send_queue_get_msg_id (header);
225 g_warning ("%s: No msg_id returned for header", __FUNCTION__);
229 /* Put newly added message in WAITING state */
230 existing = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE(self), msg_id);
231 if(existing != NULL) {
232 info = existing->data;
233 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
235 info = g_slice_new (SendInfo);
236 info->msg_id = msg_id;
237 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
238 g_queue_push_tail (priv->queue, info);
241 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
244 g_object_unref (G_OBJECT(header));
246 /* Call the user callback */
247 helper = (AddAsyncHelper *) user_data;
248 if (helper->callback)
249 helper->callback (self, cancelled, msg, err, helper->user_data);
250 g_slice_free (AddAsyncHelper, helper);
254 _add_message (ModestTnySendQueue *self, TnyHeader *header)
256 ModestWindowMgr *mgr = NULL;
257 ModestTnySendQueuePrivate *priv;
258 SendInfo *info = NULL;
259 GList* existing = NULL;
260 gchar* msg_uid = NULL;
261 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
262 gboolean editing = FALSE;
264 g_return_if_fail (TNY_IS_SEND_QUEUE(self));
265 g_return_if_fail (TNY_IS_HEADER(header));
266 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
268 /* Check whether the mail is already in the queue */
269 msg_uid = modest_tny_send_queue_get_msg_id (header);
270 status = modest_tny_send_queue_get_msg_status (self, msg_uid);
272 case MODEST_TNY_SEND_QUEUE_UNKNOWN:
273 case MODEST_TNY_SEND_QUEUE_SUSPENDED:
274 case MODEST_TNY_SEND_QUEUE_FAILED:
276 /* Check if it already exists on queue */
277 existing = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE(self), msg_uid);
281 /* Check if its being edited */
282 mgr = modest_runtime_get_window_mgr ();
283 editing = modest_window_mgr_find_registered_header (mgr, header, NULL);
287 /* Add new meesage info */
288 info = g_slice_new0 (SendInfo);
289 info->msg_id = strdup(msg_uid);
290 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
291 g_queue_push_tail (priv->queue, info);
302 modest_tny_send_queue_add_async (TnySendQueue *self,
304 TnySendQueueAddCallback callback,
305 TnyStatusCallback status_callback,
308 AddAsyncHelper *helper = g_slice_new0 (AddAsyncHelper);
309 helper->callback = callback;
310 helper->user_data = user_data;
312 /* Call the superclass passing our own callback */
313 TNY_CAMEL_SEND_QUEUE_CLASS(parent_class)->add_async (self, msg,
321 modest_tny_send_queue_get_sentbox (TnySendQueue *self)
323 ModestTnySendQueuePrivate *priv;
325 g_return_val_if_fail (self, NULL);
327 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
329 return g_object_ref (priv->sentbox);
334 modest_tny_send_queue_get_outbox (TnySendQueue *self)
336 ModestTnySendQueuePrivate *priv;
338 g_return_val_if_fail (self, NULL);
340 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
342 return g_object_ref (priv->outbox);
346 modest_tny_send_queue_get_type (void)
348 static GType my_type = 0;
351 static const GTypeInfo my_info = {
352 sizeof(ModestTnySendQueueClass),
353 NULL, /* base init */
354 NULL, /* base finalize */
355 (GClassInitFunc) modest_tny_send_queue_class_init,
356 NULL, /* class finalize */
357 NULL, /* class data */
358 sizeof(ModestTnySendQueue),
360 (GInstanceInitFunc) modest_tny_send_queue_instance_init,
364 my_type = g_type_register_static (TNY_TYPE_CAMEL_SEND_QUEUE,
365 "ModestTnySendQueue",
373 modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass)
375 GObjectClass *gobject_class;
377 gobject_class = (GObjectClass*) klass;
379 parent_class = g_type_class_peek_parent (klass);
380 gobject_class->finalize = modest_tny_send_queue_finalize;
382 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->add_async = modest_tny_send_queue_add_async;
383 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_outbox = modest_tny_send_queue_get_outbox;
384 TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_sentbox = modest_tny_send_queue_get_sentbox;
385 klass->status_changed = NULL;
387 signals[STATUS_CHANGED_SIGNAL] =
388 g_signal_new ("status_changed",
389 G_TYPE_FROM_CLASS (gobject_class),
391 G_STRUCT_OFFSET (ModestTnySendQueueClass, status_changed),
393 modest_marshal_VOID__STRING_INT,
394 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
396 g_type_class_add_private (gobject_class, sizeof(ModestTnySendQueuePrivate));
400 modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class)
402 ModestTnySendQueuePrivate *priv;
404 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (instance);
405 priv->queue = g_queue_new();
406 priv->current = NULL;
408 priv->sentbox = NULL;
409 priv->sending = FALSE;
413 modest_tny_send_queue_finalize (GObject *obj)
415 ModestTnySendQueuePrivate *priv;
417 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj);
419 g_queue_foreach (priv->queue, (GFunc)modest_tny_send_queue_info_free, NULL);
420 g_queue_free (priv->queue);
422 G_OBJECT_CLASS(parent_class)->finalize (obj);
423 g_object_unref (priv->outbox);
424 g_object_unref (priv->sentbox);
428 TnyCamelTransportAccount *account;
429 ModestTnySendQueue *queue;
433 new_queue_get_headers_async_cb (TnyFolder *folder,
439 ModestTnySendQueue *self;
441 GetHeadersInfo *info;
443 info = (GetHeadersInfo *) user_data;
444 self = MODEST_TNY_SEND_QUEUE (info->queue);
446 /* In case of error set the transport account anyway */
447 if (cancelled || err)
450 /* Add messages to our internal queue */
451 iter = tny_list_create_iterator (headers);
452 while (!tny_iterator_is_done (iter)) {
453 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
454 _add_message (self, header);
455 g_object_unref (header);
456 tny_iterator_next (iter);
459 /* Reenable suspended items */
460 modest_tny_send_queue_wakeup (self);
463 g_object_unref (iter);
464 g_object_unref (headers);
467 /* Do this at the end, because it'll call tny_send_queue_flush
468 which will call tny_send_queue_get_outbox and
469 tny_send_queue_get_sentbox */
470 tny_camel_send_queue_set_transport_account (TNY_CAMEL_SEND_QUEUE(self),
474 g_object_unref (info->account);
475 g_object_unref (info->queue);
476 g_slice_free (GetHeadersInfo, info);
480 modest_tny_send_queue_new (TnyCamelTransportAccount *account)
482 ModestTnySendQueue *self = NULL;
483 ModestTnySendQueuePrivate *priv = NULL;
484 TnyList *headers = NULL;
485 GetHeadersInfo *info;
487 g_return_val_if_fail (TNY_IS_CAMEL_TRANSPORT_ACCOUNT(account), NULL);
489 self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
491 /* Set outbox and sentbox */
492 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
493 priv->outbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
494 TNY_FOLDER_TYPE_OUTBOX);
495 priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
496 TNY_FOLDER_TYPE_SENT);
498 /* NOTE that this could happen if there was not enough disk
499 space when the account was created */
500 if (!priv->outbox || !priv->sentbox) {
501 g_object_unref (self);
505 /* Connect signals to control when a msg is being or has been sent */
506 g_signal_connect (G_OBJECT(self), "msg-sending",
507 G_CALLBACK(_on_msg_start_sending),
509 g_signal_connect (G_OBJECT(self), "msg-sent",
510 G_CALLBACK(_on_msg_has_been_sent),
512 g_signal_connect (G_OBJECT(self), "error-happened",
513 G_CALLBACK(_on_msg_error_happened),
516 g_signal_connect (G_OBJECT (self), "queue-start",
517 G_CALLBACK (_on_queue_start),
520 g_signal_connect (G_OBJECT (self), "queue-stop",
521 G_CALLBACK (_on_queue_stop),
524 priv->requested_send_receive = FALSE;
526 headers = tny_simple_list_new ();
527 info = g_slice_new0 (GetHeadersInfo);
528 info->account = g_object_ref (account);
529 info->queue = g_object_ref (self);
530 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
531 new_queue_get_headers_async_cb,
538 modest_tny_send_queue_msg_is_being_sent (ModestTnySendQueue* self,
541 ModestTnySendQueueStatus status;
543 g_return_val_if_fail (msg_id != NULL, FALSE);
545 status = modest_tny_send_queue_get_msg_status (self, msg_id);
546 return status == MODEST_TNY_SEND_QUEUE_SENDING;
550 modest_tny_send_queue_sending_in_progress (ModestTnySendQueue* self)
552 ModestTnySendQueuePrivate *priv;
554 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), FALSE);
556 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
558 return priv->sending;
561 ModestTnySendQueueStatus
562 modest_tny_send_queue_get_msg_status (ModestTnySendQueue *self, const gchar *msg_id)
566 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE(self), MODEST_TNY_SEND_QUEUE_UNKNOWN);
567 g_return_val_if_fail (msg_id, MODEST_TNY_SEND_QUEUE_UNKNOWN);
569 item = modest_tny_send_queue_lookup_info (self, msg_id);
571 return MODEST_TNY_SEND_QUEUE_UNKNOWN;
573 return ((SendInfo*)item->data)->status;
577 modest_tny_send_queue_get_msg_id (TnyHeader *header)
579 gchar* msg_uid = NULL;
581 time_t date_received;
583 g_return_val_if_fail (header && TNY_IS_HEADER(header), NULL);
585 /* Get message uid */
586 subject = tny_header_dup_subject (header);
587 date_received = tny_header_get_date_received (header);
589 msg_uid = g_strdup_printf ("%s %d", subject, (int) date_received);
597 _on_msg_start_sending (TnySendQueue *self, TnyHeader *header,
598 TnyMsg *msg, int done, int total, gpointer user_data)
600 ModestTnySendQueuePrivate *priv = NULL;
602 SendInfo *info = NULL;
603 gchar *msg_id = NULL;
605 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
607 /* Get message uid */
608 msg_id = modest_tny_send_queue_get_msg_id (header);
610 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
612 g_warning ("%s: could not get msg-id for header", __FUNCTION__);
615 /* Set current status item */
617 info->status = MODEST_TNY_SEND_QUEUE_SENDING;
618 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
619 priv->current = item;
621 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_id);
628 _on_msg_has_been_sent (TnySendQueue *self,
635 ModestTnySendQueuePrivate *priv;
636 gchar *msg_id = NULL;
639 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
641 /* Get message uid */
642 msg_id = modest_tny_send_queue_get_msg_id (header);
644 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
646 tny_folder_sync_async (priv->sentbox, FALSE, NULL, NULL, NULL);
648 /* Get status info */
649 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
652 /* TODO: note that item=NULL must not happen, but I found that
653 tinymail is issuing the message-sent signal twice, because
654 tny_camel_send_queue_update is called twice for each
655 message sent. This must be fixed in tinymail. Sergio */
657 /* Remove status info */
658 modest_tny_send_queue_info_free (item->data);
659 g_queue_delete_link (priv->queue, item);
660 priv->current = NULL;
662 modest_platform_information_banner (NULL, NULL, _("mcen_ib_message_sent"));
670 _on_msg_error_happened (TnySendQueue *self,
676 ModestTnySendQueuePrivate *priv = NULL;
678 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
680 /* Note that header could be NULL. Tinymail notifies about
681 generic send queue errors with this signal as well, and
682 those notifications are not bound to any particular header
684 if (header && TNY_IS_HEADER (header)) {
685 SendInfo *info = NULL;
687 gchar* msg_uid = NULL;
689 /* Get sending info (create new if it doesn not exist) */
690 msg_uid = modest_tny_send_queue_get_msg_id (header);
691 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self),
694 /* TODO: this should not happen (but it does), so the
695 problem should be located in the way we generate
698 g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_uid);
705 /* Keep in queue so that we remember that the opertion has failed */
706 /* and was not just cancelled */
707 if (err->code == TNY_SYSTEM_ERROR_CANCEL) {
708 info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED;
710 if (err->code == TNY_SERVICE_ERROR_CONNECT) {
711 TnyCamelTransportAccount* transport;
712 TnyTransportAccount *conn_specific;
714 transport = tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
717 ModestTnyAccountStore *acc_store;
718 const gchar *acc_name;
720 acc_store = modest_runtime_get_account_store();
721 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
722 conn_specific = (TnyTransportAccount *)
723 modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
725 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
726 tny_account_get_hostname (TNY_ACCOUNT (conn_specific)));
727 g_object_unref (conn_specific);
729 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"),
730 tny_account_get_hostname (TNY_ACCOUNT (transport)));
732 modest_platform_run_alert_dialog (message, FALSE);
734 g_object_unref (transport);
737 info->status = MODEST_TNY_SEND_QUEUE_FAILED;
739 priv->current = NULL;
741 /* Notify status has changed */
742 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
750 _on_queue_start (TnySendQueue *self,
753 ModestTnySendQueuePrivate *priv;
754 ModestMailOperation *mail_op;
756 mail_op = modest_mail_operation_new (NULL);
757 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
759 modest_mail_operation_run_queue (mail_op, MODEST_TNY_SEND_QUEUE (self));
760 g_object_unref (mail_op);
762 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
763 priv->sending = TRUE;
767 _on_queue_stop (TnySendQueue *self,
770 ModestTnySendQueuePrivate *priv;
772 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
773 priv->sending = FALSE;
777 fill_list_of_caches (gpointer key, gpointer value, gpointer userdata)
779 GSList **send_queues = (GSList **) userdata;
780 *send_queues = g_slist_prepend (*send_queues, value);
783 /* This function shouldn't be here. Move it to another place. Sergio */
784 ModestTnySendQueueStatus
785 modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
787 ModestCacheMgr *cache_mgr = NULL;
788 GHashTable *send_queue_cache = NULL;
789 ModestTnyAccountStore *accounts_store = NULL;
790 TnyList *accounts = NULL;
791 TnyIterator *iter = NULL;
792 TnyTransportAccount *account = NULL;
793 GSList *send_queues = NULL, *node;
794 /* get_msg_status returns suspended by default, so we want to detect changes */
795 ModestTnySendQueueStatus status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
796 ModestTnySendQueueStatus queue_status = MODEST_TNY_SEND_QUEUE_UNKNOWN;
797 gchar *msg_uid = NULL;
798 ModestTnySendQueue *send_queue = NULL;
800 g_return_val_if_fail (TNY_IS_HEADER(header), MODEST_TNY_SEND_QUEUE_UNKNOWN);
802 msg_uid = modest_tny_send_queue_get_msg_id (header);
803 cache_mgr = modest_runtime_get_cache_mgr ();
804 send_queue_cache = modest_cache_mgr_get_cache (cache_mgr,
805 MODEST_CACHE_MGR_CACHE_TYPE_SEND_QUEUE);
807 g_hash_table_foreach (send_queue_cache, (GHFunc) fill_list_of_caches, &send_queues);
808 if (send_queues == NULL) {
809 accounts = tny_simple_list_new ();
810 accounts_store = modest_runtime_get_account_store ();
811 tny_account_store_get_accounts (TNY_ACCOUNT_STORE(accounts_store),
813 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
815 iter = tny_list_create_iterator (accounts);
816 while (!tny_iterator_is_done (iter)) {
817 account = TNY_TRANSPORT_ACCOUNT(tny_iterator_get_current (iter));
818 send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account), TRUE);
819 g_object_unref(account);
820 if (TNY_IS_SEND_QUEUE (send_queue)) {
821 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
822 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
823 status = queue_status;
827 tny_iterator_next (iter);
829 g_object_unref (iter);
830 g_object_unref (accounts);
833 for (node = send_queues; node != NULL; node = g_slist_next (node)) {
834 send_queue = MODEST_TNY_SEND_QUEUE (node->data);
836 queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
837 if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
838 status = queue_status;
845 g_slist_free (send_queues);
850 wakeup_get_headers_async_cb (TnyFolder *folder,
856 ModestTnySendQueue *self;
857 ModestTnySendQueuePrivate *priv;
860 self = MODEST_TNY_SEND_QUEUE (user_data);
861 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
863 if (cancelled || err) {
864 g_debug ("Failed to wake up the headers of the send queue");
865 g_object_unref (self);
869 /* Wake up every single suspended header */
870 iter = tny_list_create_iterator (headers);
871 while (!tny_iterator_is_done (iter)) {
872 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
874 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_SUSPENDED) {
879 /* Unset the suspended flag */
880 tny_header_unset_flag (header, TNY_HEADER_FLAG_SUSPENDED);
883 msg_id = modest_tny_send_queue_get_msg_id (header);
884 item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
886 info = g_slice_new (SendInfo);
887 info->msg_id = msg_id;
888 g_queue_push_tail (priv->queue, info);
890 info = (SendInfo *) item->data;
893 info->status = MODEST_TNY_SEND_QUEUE_WAITING;
894 g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
898 g_object_unref (header);
899 tny_iterator_next (iter);
902 /* Make changes persistent on disk */
903 tny_folder_sync_async (priv->outbox, FALSE, NULL, NULL, NULL);
906 g_object_unref (iter);
907 g_object_unref (headers);
908 g_object_unref (self);
913 modest_tny_send_queue_wakeup (ModestTnySendQueue *self)
915 ModestTnySendQueuePrivate *priv;
918 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
920 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
922 headers = tny_simple_list_new ();
923 tny_folder_get_headers_async (priv->outbox, headers, TRUE,
924 wakeup_get_headers_async_cb,
925 NULL, g_object_ref (self));
929 modest_tny_send_queue_get_requested_send_receive (ModestTnySendQueue *self)
931 ModestTnySendQueuePrivate *priv;
933 g_return_val_if_fail (MODEST_IS_TNY_SEND_QUEUE (self), FALSE);
934 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
936 return priv->requested_send_receive;
940 modest_tny_send_queue_set_requested_send_receive (ModestTnySendQueue *self, gboolean requested_send_receive)
942 ModestTnySendQueuePrivate *priv;
944 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
945 priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
947 priv->requested_send_receive = requested_send_receive;