[evolution-data-server] Bug #720154 - [IMAPx] Silently recover from "Connection reset by peer" error



commit 8f9269309dd55de551ff1b4cae9ab987bde5361d
Author: Milan Crha <mcrha redhat com>
Date:   Wed Apr 30 13:10:08 2014 +0200

    Bug #720154 - [IMAPx] Silently recover from "Connection reset by peer" error
    
    This is a partial commit for the bug, to address "Connection reset by peer"
    errors, and even the BYE response from the server, more gracefully, like
    reconnecting to the server and re-issue the job. There will be at least
    one more commit for this bug report, for an NNTP provider.

 camel/providers/imapx/camel-imapx-conn-manager.c |   53 ++++-
 camel/providers/imapx/camel-imapx-conn-manager.h |    3 +-
 camel/providers/imapx/camel-imapx-folder.c       |  254 ++++++++++++++++------
 camel/providers/imapx/camel-imapx-input-stream.c |    3 +-
 camel/providers/imapx/camel-imapx-search.c       |  216 ++++++++++++-------
 camel/providers/imapx/camel-imapx-search.h       |   16 +-
 camel/providers/imapx/camel-imapx-server.c       |  180 +++++++++++-----
 camel/providers/imapx/camel-imapx-server.h       |    9 +-
 camel/providers/imapx/camel-imapx-store.c        |  209 +++++++++++++++---
 9 files changed, 688 insertions(+), 255 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.c 
b/camel/providers/imapx/camel-imapx-conn-manager.c
index 02a52fd..75942dd 100644
--- a/camel/providers/imapx/camel-imapx-conn-manager.c
+++ b/camel/providers/imapx/camel-imapx-conn-manager.c
@@ -54,6 +54,7 @@ struct _ConnectionInfo {
        CamelIMAPXServer *is;
        GHashTable *folder_names;
        gchar *selected_folder;
+       GError *shutdown_error;
        volatile gint ref_count;
 };
 
@@ -68,7 +69,9 @@ G_DEFINE_TYPE (
        G_TYPE_OBJECT)
 
 static void
-imapx_conn_shutdown (CamelIMAPXServer *is, CamelIMAPXConnManager *con_man);
+imapx_conn_shutdown (CamelIMAPXServer *is,
+                    const GError *error,
+                    CamelIMAPXConnManager *con_man);
 
 static void
 imapx_conn_update_select (CamelIMAPXServer *is,
@@ -95,6 +98,7 @@ connection_info_new (CamelIMAPXServer *is)
        g_mutex_init (&cinfo->lock);
        cinfo->is = g_object_ref (is);
        cinfo->folder_names = folder_names;
+       cinfo->shutdown_error = NULL;
        cinfo->ref_count = 1;
 
        return cinfo;
@@ -118,7 +122,7 @@ connection_info_unref (ConnectionInfo *cinfo)
        g_return_if_fail (cinfo->ref_count > 0);
 
        if (g_atomic_int_dec_and_test (&cinfo->ref_count)) {
-               camel_imapx_server_shutdown (cinfo->is);
+               camel_imapx_server_shutdown (cinfo->is, cinfo->shutdown_error);
                g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, 
imapx_conn_shutdown, NULL);
                g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, 
imapx_conn_update_select, NULL);
                g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, 
imapx_conn_mailbox_closed, NULL);
@@ -127,6 +131,7 @@ connection_info_unref (ConnectionInfo *cinfo)
                g_object_unref (cinfo->is);
                g_hash_table_destroy (cinfo->folder_names);
                g_free (cinfo->selected_folder);
+               g_clear_error (&cinfo->shutdown_error);
 
                g_slice_free (ConnectionInfo, cinfo);
        }
@@ -141,7 +146,7 @@ connection_info_cancel_and_unref (ConnectionInfo *cinfo)
        g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, 
imapx_conn_shutdown, NULL);
        g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, 
imapx_conn_update_select, NULL);
        g_signal_handlers_disconnect_matched (cinfo->is, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, 
imapx_conn_mailbox_closed, NULL);
-       camel_imapx_server_shutdown (cinfo->is);
+       camel_imapx_server_shutdown (cinfo->is, cinfo->shutdown_error);
        connection_info_unref (cinfo);
 }
 
@@ -244,6 +249,23 @@ connection_info_set_selected_folder (ConnectionInfo *cinfo,
        g_mutex_unlock (&cinfo->lock);
 }
 
+static void
+connection_info_set_shutdown_error (ConnectionInfo *cinfo,
+                                    const GError *shutdown_error)
+{
+       g_return_if_fail (cinfo != NULL);
+
+       g_mutex_lock (&cinfo->lock);
+
+       if (cinfo->shutdown_error != shutdown_error) {
+               g_clear_error (&cinfo->shutdown_error);
+               if (shutdown_error)
+                       cinfo->shutdown_error = g_error_copy (shutdown_error);
+       }
+
+       g_mutex_unlock (&cinfo->lock);
+}
+
 static GList *
 imapx_conn_manager_list_info (CamelIMAPXConnManager *con_man)
 {
@@ -426,11 +448,9 @@ camel_imapx_conn_manager_init (CamelIMAPXConnManager *con_man)
        g_rw_lock_init (&con_man->priv->rw_lock);
 }
 
-/* Static functions go here */
-
-/* TODO destroy unused connections in a time-out loop */
 static void
 imapx_conn_shutdown (CamelIMAPXServer *is,
+                    const GError *error,
                      CamelIMAPXConnManager *con_man)
 {
        ConnectionInfo *cinfo;
@@ -442,6 +462,14 @@ imapx_conn_shutdown (CamelIMAPXServer *is,
                imapx_conn_manager_remove_info (con_man, cinfo);
                connection_info_unref (cinfo);
        }
+
+       /* If one connection ends with this error, then it means all
+          other opened connections also may end with the same error,
+          thus better to kill them all from the list of connections.
+       */
+       if (g_error_matches (error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               camel_imapx_conn_manager_close_connections (con_man, error);
+       }
 }
 
 static void
@@ -792,7 +820,7 @@ camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man,
 
                                        g_clear_error (&local_error);
                                        is = imapx_find_connection_unlocked (con_man, folder_name, 
for_expensive_job);
-                               } else {
+                               } else if (local_error) {
                                        g_propagate_error (error, local_error);
                                }
                        }
@@ -848,13 +876,20 @@ camel_imapx_conn_manager_update_con_info (CamelIMAPXConnManager *con_man,
 }
 
 void
-camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man)
+camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man,
+                                           const GError *error)
 {
+       GList *iter;
+
        g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
 
        CON_WRITE_LOCK (con_man);
 
-       c('*', "Closing all %d connections\n", g_list_length (con_man->priv->connections));
+       c('*', "Closing all %d connections, with propagated error: %s\n", g_list_length 
(con_man->priv->connections), error ? error->message : "none");
+
+       for (iter = con_man->priv->connections; iter; iter = g_list_next (iter)) {
+               connection_info_set_shutdown_error (iter->data, error);
+       }
 
        g_list_free_full (
                con_man->priv->connections,
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.h 
b/camel/providers/imapx/camel-imapx-conn-manager.h
index fc93a11..5ada11d 100644
--- a/camel/providers/imapx/camel-imapx-conn-manager.h
+++ b/camel/providers/imapx/camel-imapx-conn-manager.h
@@ -71,7 +71,8 @@ CamelIMAPXServer *
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           camel_imapx_conn_manager_close_connections
-                                               (CamelIMAPXConnManager *con_man);
+                                               (CamelIMAPXConnManager *con_man,
+                                                const GError *error);
 GList *                camel_imapx_conn_manager_get_connections
                                                (CamelIMAPXConnManager *con_man);
 void           camel_imapx_conn_manager_update_con_info
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index a02eabc..af5b92f 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -300,44 +300,29 @@ imapx_search_by_uids (CamelFolder *folder,
                       GCancellable *cancellable,
                       GError **error)
 {
-       CamelIMAPXStore *imapx_store;
        CamelIMAPXFolder *imapx_folder;
        CamelIMAPXSearch *imapx_search;
-       CamelIMAPXServer *imapx_server = NULL;
-       const gchar *folder_name;
-       CamelStore *store;
        GPtrArray *matches;
 
        if (uids->len == 0)
                return g_ptr_array_new ();
 
        imapx_folder = CAMEL_IMAPX_FOLDER (folder);
-       store = camel_folder_get_parent_store (folder);
-       folder_name = camel_folder_get_full_name (folder);
-
-       imapx_store = CAMEL_IMAPX_STORE (store);
-       if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
-               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
NULL);
 
        g_mutex_lock (&imapx_folder->search_lock);
 
        imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
-       camel_imapx_search_set_server (imapx_search, imapx_server);
 
        camel_folder_search_set_folder (imapx_folder->search, folder);
+       camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error);
 
        matches = camel_folder_search_search (
                imapx_folder->search, expression, uids, cancellable, error);
 
-       camel_imapx_search_set_server (imapx_search, NULL);
-
-       if (imapx_server)
-               camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+       camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL);
 
        g_mutex_unlock (&imapx_folder->search_lock);
 
-       g_clear_object (&imapx_server);
-
        return matches;
 }
 
@@ -347,41 +332,26 @@ imapx_count_by_expression (CamelFolder *folder,
                            GCancellable *cancellable,
                            GError **error)
 {
-       CamelIMAPXStore *imapx_store;
        CamelIMAPXFolder *imapx_folder;
        CamelIMAPXSearch *imapx_search;
-       CamelIMAPXServer *imapx_server = NULL;
-       const gchar *folder_name;
-       CamelStore *store;
        guint32 matches;
 
        imapx_folder = CAMEL_IMAPX_FOLDER (folder);
-       store = camel_folder_get_parent_store (folder);
-       folder_name = camel_folder_get_full_name (folder);
-
-       imapx_store = CAMEL_IMAPX_STORE (store);
-       if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
-               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
NULL);
 
        g_mutex_lock (&imapx_folder->search_lock);
 
        imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
-       camel_imapx_search_set_server (imapx_search, imapx_server);
 
        camel_folder_search_set_folder (imapx_folder->search, folder);
+       camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error);
 
        matches = camel_folder_search_count (
                imapx_folder->search, expression, cancellable, error);
 
-       camel_imapx_search_set_server (imapx_search, NULL);
-
-       if (imapx_server)
-               camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+       camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL);
 
        g_mutex_unlock (&imapx_folder->search_lock);
 
-       g_clear_object (&imapx_server);
-
        return matches;
 }
 
@@ -391,41 +361,26 @@ imapx_search_by_expression (CamelFolder *folder,
                             GCancellable *cancellable,
                             GError **error)
 {
-       CamelIMAPXStore *imapx_store;
        CamelIMAPXFolder *imapx_folder;
        CamelIMAPXSearch *imapx_search;
-       CamelIMAPXServer *imapx_server = NULL;
-       const gchar *folder_name;
-       CamelStore *store;
        GPtrArray *matches;
 
        imapx_folder = CAMEL_IMAPX_FOLDER (folder);
-       store = camel_folder_get_parent_store (folder);
-       folder_name = camel_folder_get_full_name (folder);
-
-       imapx_store = CAMEL_IMAPX_STORE (store);
-       if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
-               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
NULL);
 
        g_mutex_lock (&imapx_folder->search_lock);
 
        imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
-       camel_imapx_search_set_server (imapx_search, imapx_server);
 
        camel_folder_search_set_folder (imapx_folder->search, folder);
+       camel_imapx_search_set_cancellable_and_error (imapx_search, cancellable, error);
 
        matches = camel_folder_search_search (
                imapx_folder->search, expression, NULL, cancellable, error);
 
-       camel_imapx_search_set_server (imapx_search, NULL);
-
-       if (imapx_server)
-               camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+       camel_imapx_search_set_cancellable_and_error (imapx_search, NULL, NULL);
 
        g_mutex_unlock (&imapx_folder->search_lock);
 
-       g_clear_object (&imapx_server);
-
        return matches;
 }
 
@@ -455,6 +410,7 @@ imapx_append_message_sync (CamelFolder *folder,
        CamelIMAPXServer *imapx_server;
        CamelIMAPXMailbox *mailbox = NULL;
        const gchar *folder_name;
+       GError *local_error = NULL;
        gboolean success = FALSE;
 
        if (appended_uid != NULL)
@@ -480,10 +436,28 @@ imapx_append_message_sync (CamelFolder *folder,
        success = camel_imapx_server_append_message (
                imapx_server, mailbox, folder->summary,
                CAMEL_IMAPX_FOLDER (folder)->cache, message,
-               info, appended_uid, cancellable, error);
+               info, appended_uid, cancellable, &local_error);
 
        camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       success = camel_imapx_server_append_message (
+                               imapx_server, mailbox, folder->summary,
+                               CAMEL_IMAPX_FOLDER (folder)->cache, message,
+                               info, appended_uid, cancellable, &local_error);
+
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
 exit:
        g_clear_object (&mailbox);
        g_clear_object (&imapx_server);
@@ -500,6 +474,7 @@ imapx_expunge_sync (CamelFolder *folder,
        CamelIMAPXStore *imapx_store;
        CamelIMAPXServer *imapx_server;
        CamelIMAPXMailbox *mailbox = NULL;
+       GError *local_error = NULL;
        const gchar *folder_name;
        gboolean success = FALSE;
 
@@ -523,7 +498,6 @@ imapx_expunge_sync (CamelFolder *folder,
        if ((store->flags & CAMEL_STORE_VTRASH) == 0) {
                CamelFolder *trash;
                const gchar *full_name;
-               GError *local_error = NULL;
 
                full_name = camel_folder_get_full_name (folder);
 
@@ -553,11 +527,25 @@ imapx_expunge_sync (CamelFolder *folder,
                g_clear_error (&local_error);
        }
 
-       success = camel_imapx_server_expunge (
-               imapx_server, mailbox, cancellable, error);
+       success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable, &local_error);
 
        camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable, 
&local_error);
+
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
 exit:
        g_clear_object (&mailbox);
        g_clear_object (&imapx_server);
@@ -618,6 +606,7 @@ imapx_get_message_sync (CamelFolder *folder,
        GIOStream *base_stream;
        const gchar *path = NULL;
        gboolean offline_message = FALSE;
+       GError *local_error = NULL;
 
        imapx_folder = CAMEL_IMAPX_FOLDER (folder);
        store = camel_folder_get_parent_store (folder);
@@ -666,10 +655,28 @@ imapx_get_message_sync (CamelFolder *folder,
                stream = camel_imapx_server_get_message (
                        imapx_server, mailbox, folder->summary,
                        CAMEL_IMAPX_FOLDER (folder)->cache, uid,
-                       cancellable, error);
+                       cancellable, &local_error);
 
                camel_imapx_store_folder_op_done (CAMEL_IMAPX_STORE (store), imapx_server, folder_name);
 
+               while (!stream && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                       g_clear_error (&local_error);
+                       g_clear_object (&imapx_server);
+
+                       imapx_server = camel_imapx_store_ref_server (CAMEL_IMAPX_STORE (store), folder_name, 
FALSE, cancellable, &local_error);
+                       if (imapx_server) {
+                               stream = camel_imapx_server_get_message (
+                                       imapx_server, mailbox, folder->summary,
+                                       CAMEL_IMAPX_FOLDER (folder)->cache, uid,
+                                       cancellable, &local_error);
+
+                               camel_imapx_store_folder_op_done (CAMEL_IMAPX_STORE (store), imapx_server, 
folder_name);
+                       }
+               }
+
+               if (local_error)
+                       g_propagate_error (error, local_error);
+
                g_clear_object (&mailbox);
                g_clear_object (&imapx_server);
        }
@@ -727,6 +734,7 @@ imapx_get_quota_info_sync (CamelFolder *folder,
        const gchar *folder_name;
        gchar **quota_roots;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        store = camel_folder_get_parent_store (folder);
        folder_name = camel_folder_get_full_name (folder);
@@ -744,11 +752,25 @@ imapx_get_quota_info_sync (CamelFolder *folder,
                goto exit;
        }
 
-       success = camel_imapx_server_update_quota_info (
-               imapx_server, mailbox, cancellable, error);
+       success = camel_imapx_server_update_quota_info (imapx_server, mailbox, cancellable, &local_error);
 
        camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       success = camel_imapx_server_update_quota_info (imapx_server, mailbox, cancellable, 
&local_error);
+
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
        if (!success)
                goto exit;
 
@@ -798,6 +820,7 @@ imapx_refresh_info_sync (CamelFolder *folder,
        CamelFolderChangeInfo *changes;
        const gchar *folder_name;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        store = camel_folder_get_parent_store (folder);
        folder_name = camel_folder_get_full_name (folder);
@@ -816,11 +839,25 @@ imapx_refresh_info_sync (CamelFolder *folder,
                goto exit;
        }
 
-       changes = camel_imapx_server_refresh_info (
-               imapx_server, mailbox, cancellable, error);
+       changes = camel_imapx_server_refresh_info (imapx_server, mailbox, cancellable, &local_error);
 
        camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       changes = camel_imapx_server_refresh_info (imapx_server, mailbox, cancellable, 
&local_error);
+
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
        if (changes != NULL) {
                if (camel_folder_change_info_changed (changes))
                        camel_folder_changed (folder, changes);
@@ -1034,6 +1071,7 @@ imapx_synchronize_sync (CamelFolder *folder,
        const gchar *folder_name;
        gboolean need_to_expunge;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        store = camel_folder_get_parent_store (folder);
        folder_name = camel_folder_get_full_name (folder);
@@ -1053,8 +1091,19 @@ imapx_synchronize_sync (CamelFolder *folder,
                goto exit;
        }
 
-       success = camel_imapx_server_sync_changes (
-               imapx_server, mailbox, cancellable, error);
+       success = camel_imapx_server_sync_changes (imapx_server, mailbox, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       success = camel_imapx_server_sync_changes (imapx_server, mailbox, cancellable, 
&local_error);
+               }
+       }
 
        if (success) {
                success = imapx_move_to_real_junk (
@@ -1074,11 +1123,26 @@ imapx_synchronize_sync (CamelFolder *folder,
         * then sync again incase expunge changed anything */
 
        if (success && expunge) {
-               success = camel_imapx_server_expunge (
-                       imapx_server, mailbox, cancellable, error);
+               success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable, &local_error);
+
+               while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+
+                       g_clear_error (&local_error);
+                       g_clear_object (&imapx_server);
+
+                       imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, 
cancellable, &local_error);
+                       if (imapx_server) {
+                               success = camel_imapx_server_expunge (imapx_server, mailbox, cancellable, 
&local_error);
+                       }
+               }
        }
 
-       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+       if (local_error)
+               g_propagate_error (error, local_error);
+
+       if (imapx_server)
+               camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
 exit:
        g_clear_object (&mailbox);
@@ -1099,6 +1163,7 @@ imapx_synchronize_message_sync (CamelFolder *folder,
        CamelIMAPXMailbox *mailbox = NULL;
        const gchar *folder_name;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        store = camel_folder_get_parent_store (folder);
        folder_name = camel_folder_get_full_name (folder);
@@ -1120,10 +1185,28 @@ imapx_synchronize_message_sync (CamelFolder *folder,
        success = camel_imapx_server_sync_message (
                imapx_server, mailbox, folder->summary,
                CAMEL_IMAPX_FOLDER (folder)->cache, uid,
-               cancellable, error);
+               cancellable, &local_error);
 
        camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       success = camel_imapx_server_sync_message (
+                               imapx_server, mailbox, folder->summary,
+                               CAMEL_IMAPX_FOLDER (folder)->cache, uid,
+                               cancellable, &local_error);
+
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
 exit:
        g_clear_object (&mailbox);
        g_clear_object (&imapx_server);
@@ -1147,6 +1230,7 @@ imapx_transfer_messages_to_sync (CamelFolder *source,
        CamelIMAPXMailbox *dst_mailbox = NULL;
        const gchar *folder_name;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        store = camel_folder_get_parent_store (source);
        folder_name = camel_folder_get_full_name (source);
@@ -1175,10 +1259,27 @@ imapx_transfer_messages_to_sync (CamelFolder *source,
 
        success = camel_imapx_server_copy_message (
                imapx_server, src_mailbox, dst_mailbox, uids,
-               delete_originals, cancellable, error);
+               delete_originals, cancellable, &local_error);
 
        camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
 
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, 
&local_error);
+               if (imapx_server) {
+                       success = camel_imapx_server_copy_message (
+                               imapx_server, src_mailbox, dst_mailbox, uids,
+                               delete_originals, cancellable, &local_error);
+
+                       camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
        /* Update destination folder only if it's not frozen,
         * to avoid updating for each "move" action on a single
         * message while filtering. */
@@ -1380,7 +1481,7 @@ camel_imapx_folder_new (CamelStore *store,
        g_free (state_file);
        camel_object_state_read (CAMEL_OBJECT (folder));
 
-       imapx_folder->search = camel_imapx_search_new ();
+       imapx_folder->search = camel_imapx_search_new (CAMEL_IMAPX_STORE (store));
        g_mutex_init (&imapx_folder->search_lock);
        g_mutex_init (&imapx_folder->stream_lock);
 
@@ -1500,6 +1601,7 @@ camel_imapx_folder_list_mailbox (CamelIMAPXFolder *folder,
        gchar *mailbox_name = NULL;
        gchar *pattern;
        gboolean success;
+       GError *local_error = NULL;
 
        g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), FALSE);
 
@@ -1552,8 +1654,20 @@ camel_imapx_folder_list_mailbox (CamelIMAPXFolder *folder,
        pattern = camel_utf8_utf7 (mailbox_name);
 
        /* This creates a mailbox instance from the LIST response. */
-       success = camel_imapx_server_list (
-               server, pattern, 0, cancellable, error);
+       success = camel_imapx_server_list (server, pattern, 0, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&server);
+
+               server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, &local_error);
+               if (server) {
+                       success = camel_imapx_server_list (server, pattern, 0, cancellable, &local_error);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
 
        g_free (pattern);
 
diff --git a/camel/providers/imapx/camel-imapx-input-stream.c 
b/camel/providers/imapx/camel-imapx-input-stream.c
index e5fbd15..ccc1542 100644
--- a/camel/providers/imapx/camel-imapx-input-stream.c
+++ b/camel/providers/imapx/camel-imapx-input-stream.c
@@ -27,6 +27,7 @@
 
 #include <camel/camel.h>
 
+#include "camel-imapx-server.h"
 #include "camel-imapx-utils.h"
 
 #define CAMEL_IMAPX_INPUT_STREAM_GET_PRIVATE(obj) \
@@ -88,7 +89,7 @@ imapx_input_stream_fill (CamelIMAPXInputStream *is,
                 * accordingly */
                if (!left)
                        g_set_error (
-                               error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+                               error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
                                _("Source stream returned no data"));
                return -1;
        }
diff --git a/camel/providers/imapx/camel-imapx-search.c b/camel/providers/imapx/camel-imapx-search.c
index c8c4ebf..e99c7a4 100644
--- a/camel/providers/imapx/camel-imapx-search.c
+++ b/camel/providers/imapx/camel-imapx-search.c
@@ -27,13 +27,16 @@
        ((obj), CAMEL_TYPE_IMAPX_SEARCH, CamelIMAPXSearchPrivate))
 
 struct _CamelIMAPXSearchPrivate {
-       GWeakRef server;
+       GWeakRef imapx_store;
        gint *local_data_search; /* not NULL, if testing whether all used headers are all locally available */
+
+       GCancellable *cancellable; /* not referenced */
+       GError **error; /* not referenced */
 };
 
 enum {
        PROP_0,
-       PROP_SERVER
+       PROP_STORE
 };
 
 G_DEFINE_TYPE (
@@ -48,8 +51,8 @@ imapx_search_set_property (GObject *object,
                            GParamSpec *pspec)
 {
        switch (property_id) {
-               case PROP_SERVER:
-                       camel_imapx_search_set_server (
+               case PROP_STORE:
+                       camel_imapx_search_set_store (
                                CAMEL_IMAPX_SEARCH (object),
                                g_value_get_object (value));
                        return;
@@ -65,10 +68,10 @@ imapx_search_get_property (GObject *object,
                            GParamSpec *pspec)
 {
        switch (property_id) {
-               case PROP_SERVER:
+               case PROP_STORE:
                        g_value_take_object (
                                value,
-                               camel_imapx_search_ref_server (
+                               camel_imapx_search_ref_store (
                                CAMEL_IMAPX_SEARCH (object)));
                        return;
        }
@@ -83,7 +86,7 @@ imapx_search_dispose (GObject *object)
 
        priv = CAMEL_IMAPX_SEARCH_GET_PRIVATE (object);
 
-       g_weak_ref_set (&priv->server, NULL);
+       g_weak_ref_set (&priv->imapx_store, NULL);
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (camel_imapx_search_parent_class)->dispose (object);
@@ -137,43 +140,64 @@ imapx_search_result_match_none (CamelSExp *sexp,
 static CamelSExpResult *
 imapx_search_process_criteria (CamelSExp *sexp,
                                CamelFolderSearch *search,
-                               CamelIMAPXServer *server,
+                               CamelIMAPXStore *imapx_store,
                                const GString *criteria,
                                const gchar *from_function)
 {
        CamelSExpResult *result;
+       CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
        CamelIMAPXMailbox *mailbox;
        GPtrArray *uids = NULL;
-       GError *error = NULL;
+       GError *local_error = NULL;
 
        mailbox = camel_imapx_folder_list_mailbox (
-               CAMEL_IMAPX_FOLDER (search->folder), NULL, &error);
+               CAMEL_IMAPX_FOLDER (search->folder), imapx_search->priv->cancellable, &local_error);
 
        /* Sanity check. */
        g_return_val_if_fail (
-               ((mailbox != NULL) && (error == NULL)) ||
-               ((mailbox == NULL) && (error != NULL)), NULL);
+               ((mailbox != NULL) && (local_error == NULL)) ||
+               ((mailbox == NULL) && (local_error != NULL)), NULL);
 
        if (mailbox != NULL) {
-               uids = camel_imapx_server_uid_search (
-                       server, mailbox, criteria->str, NULL, &error);
+               CamelIMAPXStore *imapx_store;
+               CamelIMAPXServer *imapx_server;
+               const gchar *folder_name;
+
+               imapx_store = camel_imapx_search_ref_store (imapx_search);
+
+               /* there should always be one, held by one of the callers of this function */
+               g_warn_if_fail (imapx_store != NULL);
+
+               folder_name = camel_folder_get_full_name (search->folder);
+               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE, 
imapx_search->priv->cancellable, &local_error);
+               if (imapx_server) {
+                       uids = camel_imapx_server_uid_search (imapx_server, mailbox, criteria->str, 
imapx_search->priv->cancellable, &local_error);
+
+                       while (!uids && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                               g_clear_error (&local_error);
+                               g_clear_object (&imapx_server);
+
+                               imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE, 
imapx_search->priv->cancellable, &local_error);
+                               if (imapx_server)
+                                       uids = camel_imapx_server_uid_search (imapx_server, mailbox, 
criteria->str, imapx_search->priv->cancellable, &local_error);
+                       }
+               }
+
+               g_clear_object (&imapx_server);
+               g_clear_object (&imapx_store);
                g_object_unref (mailbox);
        }
 
        /* Sanity check. */
        g_return_val_if_fail (
-               ((uids != NULL) && (error == NULL)) ||
-               ((uids == NULL) && (error != NULL)), NULL);
-
-       /* XXX No allowance for errors in CamelSExp callbacks!
-        *     Dump the error to the console and make like we
-        *     got an empty result. */
-       if (error != NULL) {
-               g_warning (
-                       "%s: (UID SEARCH %s): %s",
-                       from_function, criteria->str, error->message);
+               ((uids != NULL) && (local_error == NULL)) ||
+               ((uids == NULL) && (local_error != NULL)), NULL);
+
+       if (local_error != NULL) {
+               g_propagate_error (imapx_search->priv->error, local_error);
+
+               /* Make like we've got an empty result */
                uids = g_ptr_array_new ();
-               g_error_free (error);
        }
 
        if (search->current != NULL) {
@@ -196,7 +220,7 @@ imapx_search_match_all (CamelSExp *sexp,
                         CamelFolderSearch *search)
 {
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
-       CamelIMAPXServer *server;
+       CamelIMAPXStore *imapx_store;
        CamelSExpResult *result;
        GPtrArray *summary;
        gint local_data_search = 0, *prev_local_data_search, ii;
@@ -204,9 +228,9 @@ imapx_search_match_all (CamelSExp *sexp,
        if (argc != 1)
                return imapx_search_result_match_none (sexp, search);
 
-       server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
-       if (!server || search->current || !search->summary) {
-               g_clear_object (&server);
+       imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
+       if (!imapx_store || search->current || !search->summary) {
+               g_clear_object (&imapx_store);
 
                /* Chain up to parent's method. */
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
@@ -237,7 +261,7 @@ imapx_search_match_all (CamelSExp *sexp,
        imapx_search->priv->local_data_search = prev_local_data_search;
 
        if (local_data_search >= 0) {
-               g_clear_object (&server);
+               g_clear_object (&imapx_store);
 
                /* Chain up to parent's method. */
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
@@ -248,7 +272,7 @@ imapx_search_match_all (CamelSExp *sexp,
         * but here is expected GPtrArray of matched UIDs */
        result = camel_sexp_term_eval (sexp, argv[0]);
 
-       g_object_unref (server);
+       g_object_unref (imapx_store);
 
        g_return_val_if_fail (result != NULL, result);
        g_return_val_if_fail (result->type == CAMEL_SEXP_RES_ARRAY_PTR, result);
@@ -263,7 +287,7 @@ imapx_search_body_contains (CamelSExp *sexp,
                             CamelFolderSearch *search)
 {
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
-       CamelIMAPXServer *server;
+       CamelIMAPXStore *imapx_store;
        CamelSExpResult *result;
        GString *criteria;
        gint ii, jj;
@@ -282,10 +306,10 @@ imapx_search_body_contains (CamelSExp *sexp,
        if (argc == 0 || search->summary->len == 0)
                return imapx_search_result_match_none (sexp, search);
 
-       server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
+       imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
 
-       /* This will be NULL if we're offline.  Search from cache. */
-       if (server == NULL) {
+       /* This will be NULL if we're offline. Search from cache. */
+       if (imapx_store == NULL) {
                /* Chain up to parent's method. */
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
                        body_contains (sexp, argc, argv, search);
@@ -333,10 +357,10 @@ imapx_search_body_contains (CamelSExp *sexp,
                }
        }
 
-       result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
+       result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, G_STRFUNC);
 
        g_string_free (criteria, TRUE);
-       g_object_unref (server);
+       g_object_unref (imapx_store);
 
        return result;
 }
@@ -357,7 +381,7 @@ imapx_search_header_contains (CamelSExp *sexp,
                               CamelFolderSearch *search)
 {
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
-       CamelIMAPXServer *server;
+       CamelIMAPXStore *imapx_store;
        CamelSExpResult *result;
        const gchar *headername, *command = NULL;
        GString *criteria;
@@ -386,10 +410,10 @@ imapx_search_header_contains (CamelSExp *sexp,
                return imapx_search_result_match_none (sexp, search);
        }
 
-       server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
+       imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
 
-       /* This will be NULL if we're offline.  Search from cache. */
-       if (server == NULL) {
+       /* This will be NULL if we're offline. Search from cache. */
+       if (imapx_store == NULL) {
                /* Chain up to parent's method. */
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
                        header_contains (sexp, argc, argv, search);
@@ -453,10 +477,10 @@ imapx_search_header_contains (CamelSExp *sexp,
                }
        }
 
-       result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
+       result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, G_STRFUNC);
 
        g_string_free (criteria, TRUE);
-       g_object_unref (server);
+       g_object_unref (imapx_store);
 
        return result;
 }
@@ -468,7 +492,7 @@ imapx_search_header_exists (CamelSExp *sexp,
                             CamelFolderSearch *search)
 {
        CamelIMAPXSearch *imapx_search = CAMEL_IMAPX_SEARCH (search);
-       CamelIMAPXServer *server;
+       CamelIMAPXStore *imapx_store;
        CamelSExpResult *result;
        GString *criteria;
        gint ii;
@@ -503,10 +527,10 @@ imapx_search_header_exists (CamelSExp *sexp,
                return imapx_search_result_match_none (sexp, search);
        }
 
-       server = camel_imapx_search_ref_server (CAMEL_IMAPX_SEARCH (search));
+       imapx_store = camel_imapx_search_ref_store (CAMEL_IMAPX_SEARCH (search));
 
-       /* This will be NULL if we're offline.  Search from cache. */
-       if (server == NULL) {
+       /* This will be NULL if we're offline. Search from cache. */
+       if (imapx_store == NULL) {
                /* Chain up to parent's method. */
                return CAMEL_FOLDER_SEARCH_CLASS (camel_imapx_search_parent_class)->
                        header_exists (sexp, argc, argv, search);
@@ -538,10 +562,10 @@ imapx_search_header_exists (CamelSExp *sexp,
                g_string_append_printf (criteria, "HEADER \"%s\" \"\"", headername);
        }
 
-       result = imapx_search_process_criteria (sexp, search, server, criteria, G_STRFUNC);
+       result = imapx_search_process_criteria (sexp, search, imapx_store, criteria, G_STRFUNC);
 
        g_string_free (criteria, TRUE);
-       g_object_unref (server);
+       g_object_unref (imapx_store);
 
        return result;
 }
@@ -567,12 +591,12 @@ camel_imapx_search_class_init (CamelIMAPXSearchClass *class)
 
        g_object_class_install_property (
                object_class,
-               PROP_SERVER,
+               PROP_STORE,
                g_param_spec_object (
-                       "server",
-                       "Server",
-                       "Server proxy for server-side searches",
-                       CAMEL_TYPE_IMAPX_SERVER,
+                       "store",
+                       "IMAPX Store",
+                       "IMAPX Store for server-side searches",
+                       CAMEL_TYPE_IMAPX_STORE,
                        G_PARAM_READWRITE |
                        G_PARAM_STATIC_STRINGS));
 }
@@ -586,67 +610,105 @@ camel_imapx_search_init (CamelIMAPXSearch *search)
 
 /**
  * camel_imapx_search_new:
+ * imapx_store: a #CamelIMAPXStore to which the search belongs
  *
  * Returns a new #CamelIMAPXSearch instance.
  *
- * The #CamelIMAPXSearch must be given a #CamelIMAPXSearch:server before
- * it can issue server-side search requests.  Otherwise it will fallback
- * to the default #CamelFolderSearch behavior.
- *
  * Returns: a new #CamelIMAPXSearch
  *
  * Since: 3.8
  **/
 CamelFolderSearch *
-camel_imapx_search_new (void)
+camel_imapx_search_new (CamelIMAPXStore *imapx_store)
 {
-       return g_object_new (CAMEL_TYPE_IMAPX_SEARCH, NULL);
+       g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store), NULL);
+
+       return g_object_new (
+               CAMEL_TYPE_IMAPX_SEARCH,
+               "store", imapx_store,
+               NULL);
 }
 
 /**
- * camel_imapx_search_ref_server:
+ * camel_imapx_search_ref_store:
  * @search: a #CamelIMAPXSearch
  *
- * Returns a #CamelIMAPXServer to use for server-side searches,
- * or %NULL when the corresponding #CamelIMAPXStore is offline.
+ * Returns a #CamelIMAPXStore to use for server-side searches,
+ * or %NULL when the store is offline.
  *
- * The returned #CamelIMAPXSearch is referenced for thread-safety and
+ * The returned #CamelIMAPXStore is referenced for thread-safety and
  * must be unreferenced with g_object_unref() when finished with it.
  *
- * Returns: a #CamelIMAPXServer, or %NULL
+ * Returns: a #CamelIMAPXStore, or %NULL
  *
  * Since: 3.8
  **/
-CamelIMAPXServer *
-camel_imapx_search_ref_server (CamelIMAPXSearch *search)
+CamelIMAPXStore *
+camel_imapx_search_ref_store (CamelIMAPXSearch *search)
 {
+       CamelIMAPXStore *imapx_store;
+
        g_return_val_if_fail (CAMEL_IS_IMAPX_SEARCH (search), NULL);
 
-       return g_weak_ref_get (&search->priv->server);
+       imapx_store = g_weak_ref_get (&search->priv->imapx_store);
+
+       if (imapx_store && !camel_offline_store_get_online (CAMEL_OFFLINE_STORE (imapx_store)))
+               g_clear_object (&imapx_store);
+
+       return imapx_store;
 }
 
 /**
- * camel_imapx_search_set_server:
+ * camel_imapx_search_set_store:
  * @search: a #CamelIMAPXSearch
- * @server: a #CamelIMAPXServer, or %NULL
+ * @imapx_server: a #CamelIMAPXStore, or %NULL
  *
- * Sets a #CamelIMAPXServer to use for server-side searches.  Generally
+ * Sets a #CamelIMAPXStore to use for server-side searches. Generally
  * this is set for the duration of a single search when online, and then
  * reset to %NULL.
  *
  * Since: 3.8
  **/
 void
-camel_imapx_search_set_server (CamelIMAPXSearch *search,
-                               CamelIMAPXServer *server)
+camel_imapx_search_set_store (CamelIMAPXSearch *search,
+                             CamelIMAPXStore *imapx_store)
 {
        g_return_if_fail (CAMEL_IS_IMAPX_SEARCH (search));
 
-       if (server != NULL)
-               g_return_if_fail (CAMEL_IS_IMAPX_SERVER (server));
+       if (imapx_store != NULL)
+               g_return_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store));
 
-       g_weak_ref_set (&search->priv->server, server);
+       g_weak_ref_set (&search->priv->imapx_store, imapx_store);
 
-       g_object_notify (G_OBJECT (search), "server");
+       g_object_notify (G_OBJECT (search), "store");
 }
 
+/**
+ * camel_imapx_search_set_cancellable_and_error:
+ * @search: a #CamelIMAPXSearch
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Sets @cancellable and @error to use for server-side searches. This way
+ * the search can return accurate errors and be eventually cancelled by
+ * a user.
+ *
+ * Note: The caller is responsible to keep alive both @cancellable and @error
+ * for the whole run of the search and reset them both to NULL after
+ * the search is finished.
+ *
+ * Since: 3.14
+ **/
+void
+camel_imapx_search_set_cancellable_and_error (CamelIMAPXSearch *search,
+                                             GCancellable *cancellable,
+                                             GError **error)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_SEARCH (search));
+
+       if (cancellable)
+               g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
+       search->priv->cancellable = cancellable;
+       search->priv->error = error;
+}
diff --git a/camel/providers/imapx/camel-imapx-search.h b/camel/providers/imapx/camel-imapx-search.h
index 6fd9d05..acdba79 100644
--- a/camel/providers/imapx/camel-imapx-search.h
+++ b/camel/providers/imapx/camel-imapx-search.h
@@ -20,7 +20,7 @@
 
 #include <camel/camel.h>
 
-#include "camel-imapx-server.h"
+#include "camel-imapx-store.h"
 
 /* Standard GObject macros */
 #define CAMEL_TYPE_IMAPX_SEARCH \
@@ -66,11 +66,15 @@ struct _CamelIMAPXSearchClass {
 
 GType          camel_imapx_search_get_type     (void) G_GNUC_CONST;
 CamelFolderSearch *
-               camel_imapx_search_new          (void);
-CamelIMAPXServer *
-               camel_imapx_search_ref_server   (CamelIMAPXSearch *search);
-void           camel_imapx_search_set_server   (CamelIMAPXSearch *search,
-                                                CamelIMAPXServer *server);
+               camel_imapx_search_new          (CamelIMAPXStore *imapx_store);
+CamelIMAPXStore *
+               camel_imapx_search_ref_store    (CamelIMAPXSearch *search);
+void           camel_imapx_search_set_store    (CamelIMAPXSearch *search,
+                                                CamelIMAPXStore *imapx_store);
+void           camel_imapx_search_set_cancellable_and_error
+                                               (CamelIMAPXSearch *search,
+                                                GCancellable *cancellable,
+                                                GError **error);
 
 G_END_DECLS
 
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 44f886a..b9624ef 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -354,6 +354,9 @@ struct _CamelIMAPXServerPrivate {
        GMainContext *parser_main_context;
        GWeakRef parser_cancellable;
 
+       GMutex shutdown_error_lock;
+       GError *shutdown_error;
+
        GSource *inactivity_timeout;
        GMutex inactivity_timeout_lock;
 
@@ -576,6 +579,36 @@ imapx_weak_ref_free (GWeakRef *weak_ref)
 }
 
 static void
+imapx_server_set_shutdown_error (CamelIMAPXServer *imapx_server,
+                                const GError *error)
+{
+       g_mutex_lock (&imapx_server->priv->shutdown_error_lock);
+
+       if (error != imapx_server->priv->shutdown_error) {
+               g_clear_error (&imapx_server->priv->shutdown_error);
+               if (error)
+                       imapx_server->priv->shutdown_error = g_error_copy (error);
+       }
+
+       g_mutex_unlock (&imapx_server->priv->shutdown_error_lock);
+}
+
+static GError *
+imapx_server_dup_shutdown_error (CamelIMAPXServer *imapx_server)
+{
+       GError *error = NULL;
+
+       g_mutex_lock (&imapx_server->priv->shutdown_error_lock);
+
+       if (imapx_server->priv->shutdown_error)
+               error = g_error_copy (imapx_server->priv->shutdown_error);
+
+       g_mutex_unlock (&imapx_server->priv->shutdown_error_lock);
+
+       return error;
+}
+
+static void
 imapx_server_command_added (CamelIMAPXServer *imapx_server,
                            CamelIMAPXCommand *command)
 {
@@ -1696,7 +1729,7 @@ imapx_command_queue (CamelIMAPXServer *is,
                c (is->tagprefix, "refuse to queue job on disconnected server\n");
 
                local_error = g_error_new (
-                       CAMEL_IMAPX_ERROR, 1,
+                       CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
                        "%s", _("Server disconnected"));
                camel_imapx_command_failed (ic, local_error);
                g_error_free (local_error);
@@ -2710,9 +2743,6 @@ imapx_untagged_bye (CamelIMAPXServer *is,
                     GCancellable *cancellable,
                     GError **error)
 {
-       CamelIMAPXStore *imapx_store;
-       CamelService *service;
-       CamelServiceConnectionStatus status;
        guchar *token = NULL;
        gboolean success;
 
@@ -2727,7 +2757,7 @@ imapx_untagged_bye (CamelIMAPXServer *is,
        if (success) {
                c (is->tagprefix, "BYE: %s\n", token);
                g_set_error (
-                       error, CAMEL_IMAPX_ERROR, 1,
+                       error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
                        "IMAP server said BYE: %s", token);
        }
 
@@ -2735,19 +2765,6 @@ imapx_untagged_bye (CamelIMAPXServer *is,
 
        is->state = IMAPX_SHUTDOWN;
 
-       imapx_store = camel_imapx_server_ref_store (is);
-       service = CAMEL_SERVICE (imapx_store);
-       status = camel_service_get_connection_status (service);
-
-       /* Do not disconnect the service if we're still connecting.
-        * camel_service_disconnect_sync() will cancel the connect
-        * operation and the server message will get replaced with
-        * a generic "Operation was cancelled" message. */
-       if (status == CAMEL_SERVICE_CONNECTED)
-               camel_service_disconnect_sync (service, FALSE, NULL, NULL);
-
-       g_object_unref (imapx_store);
-
        return FALSE;
 }
 
@@ -4904,39 +4921,6 @@ exit:
        return success;
 }
 
-/**
- * camel_imapx_server_shutdown:
- * @is: a #CamelIMAPXServer
- *
- * Signals the server to shut down command processing.  #CamelIMAPXStore
- * should call this immediately before unreferencing its server instance.
- * Note, the server instance may linger a short time after this function
- * returns as its own worker threads finish.
- *
- * Since: 3.12
- **/
-void
-camel_imapx_server_shutdown (CamelIMAPXServer *is)
-{
-       GCancellable *cancellable;
-
-       g_return_if_fail (CAMEL_IS_IMAPX_SERVER (is));
-
-       QUEUE_LOCK (is);
-
-       is->state = IMAPX_SHUTDOWN;
-
-       cancellable = g_weak_ref_get (&is->priv->parser_cancellable);
-
-       QUEUE_UNLOCK (is);
-
-       g_main_loop_quit (is->priv->idle_main_loop);
-       g_main_loop_quit (is->priv->parser_main_loop);
-
-       g_cancellable_cancel (cancellable);
-       g_clear_object (&cancellable);
-}
-
 /* ********************************************************************** */
 
 static void
@@ -7447,6 +7431,8 @@ imapx_abort_all_commands (CamelIMAPXServer *is,
 
        queue = camel_imapx_command_queue_new ();
 
+       imapx_server_set_shutdown_error (is, error);
+
        QUEUE_LOCK (is);
 
        camel_imapx_command_queue_transfer (is->queue, queue);
@@ -7538,6 +7524,25 @@ imapx_ready_to_read (GInputStream *input_stream,
        g_clear_object (&cancellable);
 
        if (local_error != NULL) {
+               camel_imapx_debug (io, is->tagprefix, "Data read failed with error '%s'\n", 
local_error->message);
+
+               /* Sadly, G_IO_ERROR_FAILED is also used for 'Connection reset by peer' error */
+               if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED)) {
+                       local_error->domain = CAMEL_IMAPX_SERVER_ERROR;
+                       local_error->code = CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT;
+               }
+
+               imapx_server_set_shutdown_error (is, local_error);
+
+               /* Call the signal early, certain thread interleaving can cause the closed connection
+                  being reused on the following reconnect attempt. There is also re-setting
+                  the shutdown_error above, because the signal handler in connection manager
+                  also calls camel_imapx_server_shutdown(), but without the error, while we want
+                  to have there propagated the "try reconnect" error instead. As there is no
+                  guarantee that it'll be called, then we also quit the parser's mainloop and
+                  call the imapx_abort_all_commands() below - just in case. */
+               g_signal_emit (is, signals[SHUTDOWN], 0, local_error);
+
                g_main_loop_quit (is->priv->parser_main_loop);
                imapx_abort_all_commands (is, local_error);
                g_clear_error (&local_error);
@@ -7561,6 +7566,7 @@ imapx_parser_thread (gpointer user_data)
        GInputStream *input_stream;
        GCancellable *cancellable;
        GSource *pollable_source;
+       GError *shutdown_error;
 
        is = CAMEL_IMAPX_SERVER (user_data);
 
@@ -7600,7 +7606,11 @@ imapx_parser_thread (gpointer user_data)
 
        g_main_context_pop_thread_default (is->priv->parser_main_context);
 
-       g_signal_emit (is, signals[SHUTDOWN], 0);
+       shutdown_error = imapx_server_dup_shutdown_error (is);
+
+       g_signal_emit (is, signals[SHUTDOWN], 0, shutdown_error);
+
+       g_clear_error (&shutdown_error);
 
        g_object_unref (is);
 
@@ -7736,6 +7746,9 @@ imapx_server_finalize (GObject *object)
        g_mutex_clear (&is->priv->jobs_prop_lock);
        g_hash_table_destroy (is->priv->jobs_prop_folder_paths);
 
+       g_mutex_clear (&is->priv->shutdown_error_lock);
+       g_clear_error (&is->priv->shutdown_error);
+
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (camel_imapx_server_parent_class)->finalize (object);
 }
@@ -7831,6 +7844,7 @@ camel_imapx_server_class_init (CamelIMAPXServerClass *class)
        /**
         * CamelIMAPXServer::shutdown
         * @server: the #CamelIMAPXServer which emitted the signal
+        * @error: a #GError, which caused the shutdown; can be %NULL
         **/
        signals[SHUTDOWN] = g_signal_new (
                "shutdown",
@@ -7838,8 +7852,8 @@ camel_imapx_server_class_init (CamelIMAPXServerClass *class)
                G_SIGNAL_RUN_FIRST,
                G_STRUCT_OFFSET (CamelIMAPXServerClass, shutdown),
                NULL, NULL,
-               g_cclosure_marshal_VOID__VOID,
-               G_TYPE_NONE, 0);
+               g_cclosure_marshal_VOID__BOXED,
+               G_TYPE_NONE, 1, G_TYPE_ERROR);
 
        class->tagprefix = 'A';
 }
@@ -7859,6 +7873,7 @@ camel_imapx_server_init (CamelIMAPXServer *is)
        g_mutex_init (&is->priv->search_results_lock);
        g_mutex_init (&is->priv->known_alerts_lock);
        g_mutex_init (&is->priv->jobs_prop_lock);
+       g_mutex_init (&is->priv->shutdown_error_lock);
 
        is->priv->jobs_prop_folder_paths = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
        is->priv->jobs_prop_command_count = 0;
@@ -7888,6 +7903,7 @@ camel_imapx_server_init (CamelIMAPXServer *is)
 
        is->priv->parser_main_loop = g_main_loop_new (main_context, FALSE);
        is->priv->parser_main_context = g_main_context_ref (main_context);
+       is->priv->shutdown_error = NULL;
 
        g_main_context_unref (main_context);
 
@@ -9282,3 +9298,59 @@ camel_imapx_server_register_untagged_handler (CamelIMAPXServer *is,
        return previous;
 }
 
+/**
+ * camel_imapx_server_shutdown:
+ * @is: a #CamelIMAPXServer
+ * @error: a #GError with which cancel any pending jobs
+ *
+ * Signals the server to shut down command processing. A #CamelIMAPXStore
+ * should call this immediately before unreferencing its server instance.
+ * Note, the server instance may linger a short time after this function
+ * returns as its own worker threads finish.
+ *
+ * Since: 3.12
+ **/
+void
+camel_imapx_server_shutdown (CamelIMAPXServer *is,
+                            const GError *error)
+{
+       GCancellable *cancellable;
+       GError *shutdown_error_copy = NULL;
+
+       g_return_if_fail (CAMEL_IS_IMAPX_SERVER (is));
+
+       QUEUE_LOCK (is);
+
+       is->state = IMAPX_SHUTDOWN;
+
+       cancellable = g_weak_ref_get (&is->priv->parser_cancellable);
+
+       QUEUE_UNLOCK (is);
+
+       if (!error) {
+               shutdown_error_copy = imapx_server_dup_shutdown_error (is);
+               error = shutdown_error_copy;
+       }
+
+       if (error) {
+               imapx_abort_all_commands (is, error);
+       } else {
+               GError *local_error = NULL;
+
+               g_set_error (
+                       &local_error, CAMEL_SERVICE_ERROR,
+                       CAMEL_SERVICE_ERROR_UNAVAILABLE,
+                       "Shutting down");
+
+               imapx_abort_all_commands (is, local_error);
+
+               g_clear_error (&local_error);
+       }
+
+       g_main_loop_quit (is->priv->idle_main_loop);
+       g_main_loop_quit (is->priv->parser_main_loop);
+
+       g_cancellable_cancel (cancellable);
+       g_clear_object (&cancellable);
+       g_clear_error (&shutdown_error_copy);
+}
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index 3a61ba1..ceacc23 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -50,7 +50,8 @@
 G_BEGIN_DECLS
 
 typedef enum {
-       CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED
+       CAMEL_IMAPX_SERVER_ERROR_CONCURRENT_CONNECT_FAILED,
+       CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT
 } CamelIMAPXServerError;
 
 GQuark         camel_imapx_server_error_quark          (void) G_GNUC_CONST;
@@ -135,7 +136,8 @@ struct _CamelIMAPXServerClass {
                                                 CamelIMAPXMailbox *mailbox);
        void            (*mailbox_closed)       (CamelIMAPXServer *is,
                                                 CamelIMAPXMailbox *mailbox);
-       void            (*shutdown)             (CamelIMAPXServer *is);
+       void            (*shutdown)             (CamelIMAPXServer *is,
+                                                const GError *error);
 };
 
 GType          camel_imapx_server_get_type     (void);
@@ -162,7 +164,8 @@ CamelAuthenticationResult
                                                 const gchar *mechanism,
                                                 GCancellable *cancellable,
                                                 GError **error);
-void           camel_imapx_server_shutdown     (CamelIMAPXServer *is);
+void           camel_imapx_server_shutdown     (CamelIMAPXServer *is,
+                                                const GError *error);
 gboolean       camel_imapx_server_list         (CamelIMAPXServer *is,
                                                 const gchar *pattern,
                                                 CamelStoreGetFolderInfoFlags flags,
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 96c080f..6b577d3 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -794,7 +794,7 @@ imapx_disconnect_sync (CamelService *service,
        priv = CAMEL_IMAPX_STORE_GET_PRIVATE (service);
 
        if (priv->con_man != NULL)
-               camel_imapx_conn_manager_close_connections (priv->con_man);
+               camel_imapx_conn_manager_close_connections (priv->con_man, NULL);
 
        g_mutex_lock (&priv->server_lock);
 
@@ -1146,24 +1146,39 @@ fetch_folder_info_for_pattern (CamelIMAPXServer *server,
        GError *local_error = NULL;
        gboolean success;
 
-       success = camel_imapx_server_list (
-               server, pattern, flags, cancellable, &local_error);
+       g_object_ref (server);
+
+       imapx_store = camel_imapx_server_ref_store (server);
+
+       success = camel_imapx_server_list (server, pattern, flags, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&server);
+
+               server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, &local_error);
+               if (server)
+                       success = camel_imapx_server_list (server, pattern, flags, cancellable, &local_error);
+       }
+
+       g_clear_object (&server);
+
        if (!success) {
+               g_clear_object (&imapx_store);
+
                if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
                    camel_imapx_namespace_get_category (namespace) != CAMEL_IMAPX_NAMESPACE_PERSONAL) {
                        /* Ignore errors for non-personal namespaces; one such error can be:
                           "NO LIST failed: wildcards not permitted in username" */
                        g_clear_error (&local_error);
                        return TRUE;
-               } else {
+               } else if (local_error) {
                        g_propagate_error (error, local_error);
                }
 
                return FALSE;
        }
 
-       imapx_store = camel_imapx_server_ref_store (server);
-
        list = camel_imapx_store_list_mailboxes (imapx_store, namespace, pattern);
 
        for (link = list; link != NULL; link = g_list_next (link)) {
@@ -1189,26 +1204,41 @@ fetch_folder_info_for_inbox (CamelIMAPXServer *server,
                              GCancellable *cancellable,
                              GError **error)
 {
+       CamelIMAPXStore *imapx_store;
+       GError *local_error = NULL;
        gboolean success;
 
-       success = camel_imapx_server_list (
-               server, "INBOX", flags, cancellable, error);
+       g_object_ref (server);
+       imapx_store = camel_imapx_server_ref_store (server);
+
+       success = camel_imapx_server_list (server, "INBOX", flags, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&server);
+
+               server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, &local_error);
+               if (server)
+                       success = camel_imapx_server_list (server, "INBOX", flags, cancellable, &local_error);
+       }
+
+       g_clear_object (&server);
+
+       if (local_error)
+               g_propagate_error (error, local_error);
 
        if (success) {
-               CamelIMAPXStore *imapx_store;
                CamelIMAPXMailbox *mailbox;
 
-               imapx_store = camel_imapx_server_ref_store (server);
-
                mailbox = camel_imapx_store_ref_mailbox (imapx_store, "INBOX");
                g_return_val_if_fail (mailbox != NULL, FALSE);
 
                collect_folder_info_for_list (
                        imapx_store, mailbox, folder_info_results);
-
-               g_object_unref (imapx_store);
        }
 
+       g_object_unref (imapx_store);
+
        return success;
 }
 
@@ -1475,8 +1505,21 @@ discover_inbox (CamelIMAPXStore *imapx_store,
 
        attribute = CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED;
        if (!camel_imapx_mailbox_has_attribute (mailbox, attribute)) {
-               camel_imapx_server_subscribe_mailbox (
-                       imapx_server, mailbox, cancellable, NULL);
+               GError *local_error = NULL;
+               gboolean success;
+
+               success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable, 
&local_error);
+
+               while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                       g_clear_error (&local_error);
+                       g_clear_object (&imapx_server);
+
+                       imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+                       if (imapx_server)
+                               success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, 
cancellable, &local_error);
+               }
+
+               g_clear_error (&local_error);
        }
 
 exit:
@@ -1808,6 +1851,7 @@ imapx_store_create_folder_sync (CamelStore *store,
        gchar *mailbox_name = NULL;
        gchar separator;
        gboolean success;
+       GError *local_error = NULL;
 
        imapx_store = CAMEL_IMAPX_STORE (store);
        imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
@@ -1884,8 +1928,19 @@ check_separator:
        /* This also LISTs the mailbox after creating it, which
         * triggers the CamelIMAPXStore::mailbox-created signal
         * and all the local processing that goes along with it. */
-       success = camel_imapx_server_create_mailbox (
-               imapx_server, mailbox_name, cancellable, error);
+       success = camel_imapx_server_create_mailbox (imapx_server, mailbox_name, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+               if (imapx_server)
+                       success = camel_imapx_server_create_mailbox (imapx_server, mailbox_name, cancellable, 
&local_error);
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
 
        if (success) {
                fi = imapx_store_build_folder_info (
@@ -1912,6 +1967,7 @@ imapx_store_delete_folder_sync (CamelStore *store,
        CamelIMAPXServer *imapx_server;
        CamelIMAPXMailbox *mailbox = NULL;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        folder = camel_store_get_folder_sync (
                store, folder_name, 0, cancellable, error);
@@ -1930,8 +1986,19 @@ imapx_store_delete_folder_sync (CamelStore *store,
        if (mailbox == NULL)
                goto exit;
 
-       success = camel_imapx_server_delete_mailbox (
-               imapx_server, mailbox, cancellable, error);
+       success = camel_imapx_server_delete_mailbox (imapx_server, mailbox, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+               if (imapx_server)
+                       success = camel_imapx_server_delete_mailbox (imapx_server, mailbox, cancellable, 
&local_error);
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
 
        if (success)
                imapx_delete_folder_from_cache (imapx_store, folder_name);
@@ -1962,6 +2029,7 @@ imapx_store_rename_folder_sync (CamelStore *store,
        gchar separator;
        gboolean use_subscriptions;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        service = CAMEL_SERVICE (store);
        imapx_store = CAMEL_IMAPX_STORE (store);
@@ -1996,16 +2064,53 @@ imapx_store_rename_folder_sync (CamelStore *store,
        separator = camel_imapx_mailbox_get_separator (mailbox);
        new_mailbox_name = camel_imapx_folder_path_to_mailbox (new, separator);
 
-       if (use_subscriptions)
-               camel_imapx_server_unsubscribe_mailbox (
-                       imapx_server, mailbox, cancellable, NULL);
+       if (use_subscriptions) {
+               success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, cancellable, 
&local_error);
+
+               while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                       g_clear_error (&local_error);
+                       g_clear_object (&imapx_server);
+
+                       imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+                       if (imapx_server)
+                               success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, 
cancellable, &local_error);
+               }
+
+               g_clear_error (&local_error);
+       }
+
+       success = camel_imapx_server_rename_mailbox (imapx_server, mailbox, new_mailbox_name, cancellable, 
&local_error);
 
-       success = camel_imapx_server_rename_mailbox (
-               imapx_server, mailbox, new_mailbox_name, cancellable, error);
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+               if (imapx_server)
+                       success = camel_imapx_server_rename_mailbox (imapx_server, mailbox, new_mailbox_name, 
cancellable, &local_error);
+       }
 
        if (!success) {
-               camel_imapx_server_subscribe_mailbox (
-                       imapx_server, mailbox, cancellable, NULL);
+               if (local_error)
+                       g_propagate_error (error, local_error);
+               local_error = NULL;
+
+               if (use_subscriptions) {
+                       gboolean success_2;
+
+                       success_2 = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable, 
&local_error);
+
+                       while (!success_2 && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                               g_clear_error (&local_error);
+                               g_clear_object (&imapx_server);
+
+                               imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, 
cancellable, &local_error);
+                               if (imapx_server)
+                                       success_2 = camel_imapx_server_subscribe_mailbox (imapx_server, 
mailbox, cancellable, &local_error);
+                       }
+
+                       g_clear_error (&local_error);
+               }
                goto exit;
        }
 
@@ -2019,9 +2124,21 @@ imapx_store_rename_folder_sync (CamelStore *store,
        camel_imapx_folder_set_mailbox (
                CAMEL_IMAPX_FOLDER (folder), cloned_mailbox);
 
-       if (use_subscriptions)
-               success = camel_imapx_server_subscribe_mailbox (
-                       imapx_server, cloned_mailbox, cancellable, error);
+       if (use_subscriptions) {
+               success = camel_imapx_server_subscribe_mailbox (imapx_server, cloned_mailbox, cancellable, 
&local_error);
+
+               while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+                       g_clear_error (&local_error);
+                       g_clear_object (&imapx_server);
+
+                       imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+                       if (imapx_server)
+                               success = camel_imapx_server_subscribe_mailbox (imapx_server, cloned_mailbox, 
cancellable, &local_error);
+               }
+
+               if (local_error)
+                       g_propagate_error (error, local_error);
+       }
 
        g_clear_object (&cloned_mailbox);
 
@@ -2216,6 +2333,7 @@ imapx_store_subscribe_folder_sync (CamelSubscribable *subscribable,
        CamelIMAPXServer *imapx_server;
        CamelIMAPXMailbox *mailbox = NULL;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        imapx_store = CAMEL_IMAPX_STORE (subscribable);
        imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
@@ -2236,8 +2354,19 @@ imapx_store_subscribe_folder_sync (CamelSubscribable *subscribable,
        if (mailbox == NULL)
                goto exit;
 
-       success = camel_imapx_server_subscribe_mailbox (
-               imapx_server, mailbox, cancellable, error);
+       success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+               if (imapx_server)
+                       success = camel_imapx_server_subscribe_mailbox (imapx_server, mailbox, cancellable, 
&local_error);
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
 
        if (success) {
                CamelFolderInfo *fi;
@@ -2269,6 +2398,7 @@ imapx_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
        CamelIMAPXServer *imapx_server;
        CamelIMAPXMailbox *mailbox = NULL;
        gboolean success = FALSE;
+       GError *local_error = NULL;
 
        imapx_store = CAMEL_IMAPX_STORE (subscribable);
        imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
@@ -2289,8 +2419,19 @@ imapx_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
        if (mailbox == NULL)
                goto exit;
 
-       success = camel_imapx_server_unsubscribe_mailbox (
-               imapx_server, mailbox, cancellable, error);
+       success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, cancellable, &local_error);
+
+       while (!success && g_error_matches (local_error, CAMEL_IMAPX_SERVER_ERROR, 
CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT)) {
+               g_clear_error (&local_error);
+               g_clear_object (&imapx_server);
+
+               imapx_server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, 
&local_error);
+               if (imapx_server)
+                       success = camel_imapx_server_unsubscribe_mailbox (imapx_server, mailbox, cancellable, 
&local_error);
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
 
        if (success) {
                CamelFolderInfo *fi;
@@ -2526,7 +2667,7 @@ camel_imapx_store_ref_server (CamelIMAPXStore *store,
        server = camel_imapx_conn_manager_get_connection (
                store->priv->con_man, folder_name, for_expensive_job, cancellable, error);
 
-       if (!server) {
+       if (!server && error && !*error) {
                g_set_error (
                        error, CAMEL_SERVICE_ERROR,
                        CAMEL_SERVICE_ERROR_UNAVAILABLE,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]