diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c
index 839daba..7c0068b 100644
--- a/libempathy/empathy-dispatcher.c
+++ b/libempathy/empathy-dispatcher.c
@@ -76,6 +76,9 @@ typedef struct
   GList *handlers;
 
   GHashTable *request_channel_class_async_ids;
+  /* (TpAccount *) => gulong
+   * Signal handler ID of the "status-changed" signal */
+  GHashTable *status_changed_handlers;
 } EmpathyDispatcherPriv;
 
 static GList *
@@ -1013,6 +1016,7 @@ dispatcher_finalize (GObject *object)
   GHashTableIter iter;
   gpointer connection;
   GList *list;
+  gpointer account, id;
 
   if (priv->request_channel_class_async_ids != NULL)
     {
@@ -1036,6 +1040,13 @@ dispatcher_finalize (GObject *object)
       g_list_free (list);
     }
 
+  g_hash_table_iter_init (&iter, priv->status_changed_handlers);
+  while (g_hash_table_iter_next (&iter, &account, &id))
+    {
+      g_signal_handler_disconnect (account, GPOINTER_TO_UINT (id));
+    }
+  g_hash_table_destroy (priv->status_changed_handlers);
+
   g_object_unref (priv->account_manager);
 
   g_hash_table_destroy (priv->outstanding_classes_requests);
@@ -1136,6 +1147,30 @@ empathy_dispatcher_class_init (EmpathyDispatcherClass *klass)
 }
 
 static void
+connect_account (EmpathyDispatcher *self,
+    TpAccount *account)
+{
+  EmpathyDispatcherPriv *priv = GET_PRIV (self);
+  TpConnection *conn = tp_account_get_connection (account);
+  gulong id;
+
+  id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->status_changed_handlers,
+        account));
+
+  if (id != 0)
+    return;
+
+  if (conn != NULL)
+    dispatcher_status_changed_cb (account, 0, 0, 0, NULL, NULL, self);
+
+  id = g_signal_connect (account, "status-changed",
+      G_CALLBACK (dispatcher_status_changed_cb), self);
+
+  g_hash_table_insert (priv->status_changed_handlers, account,
+      GUINT_TO_POINTER (id));
+}
+
+static void
 account_manager_prepared_cb (GObject *source_object,
                              GAsyncResult *result,
                              gpointer user_data)
@@ -1156,19 +1191,44 @@ account_manager_prepared_cb (GObject *source_object,
   for (l = accounts; l; l = l->next)
     {
       TpAccount *a = l->data;
-      TpConnection *conn = tp_account_get_connection (a);
-
-      if (conn != NULL)
-        dispatcher_status_changed_cb (a, 0, 0, 0, NULL, NULL, self);
 
-      empathy_signal_connect_weak (a, "status-changed",
-          G_CALLBACK (dispatcher_status_changed_cb),
-          G_OBJECT (self));
+      connect_account (self, a);
     }
   g_list_free (accounts);
 }
 
 static void
+account_prepare_cb (GObject *source_object,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  EmpathyDispatcher *self = user_data;
+  TpAccount *account = TP_ACCOUNT (source_object);
+  GError *error = NULL;
+
+  if (!tp_account_prepare_finish (account, result, &error))
+    {
+      DEBUG ("Failed to prepare account: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  connect_account (self, account);
+}
+
+static void
+account_validity_changed_cb (TpAccountManager *manager,
+    TpAccount *account,
+    gboolean valid,
+    gpointer user_data)
+{
+  if (!valid)
+    return;
+
+  tp_account_prepare_async (account, NULL, account_prepare_cb, user_data);
+}
+
+static void
 empathy_dispatcher_init (EmpathyDispatcher *self)
 {
   EmpathyDispatcherPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
@@ -1188,8 +1248,14 @@ empathy_dispatcher_init (EmpathyDispatcher *self)
   tp_account_manager_prepare_async (priv->account_manager, NULL,
       account_manager_prepared_cb, self);
 
+  empathy_signal_connect_weak (priv->account_manager,
+      "account-validity-changed", G_CALLBACK (account_validity_changed_cb),
+      G_OBJECT (self));
+
   priv->request_channel_class_async_ids = g_hash_table_new (g_direct_hash,
     g_direct_equal);
+  priv->status_changed_handlers = g_hash_table_new (g_direct_hash,
+      g_direct_equal);
 }
 
 EmpathyDispatcher *
@@ -1532,6 +1598,7 @@ empathy_dispatcher_join_muc (TpConnection *connection,
   priv = GET_PRIV (self);
 
   connection_data = g_hash_table_lookup (priv->connections, connection);
+  g_assert (connection_data != NULL);
 
   /* Don't know the room handle yet */
   request_data  = new_dispatcher_request_data (self, connection,
