diff --git a/camel/camel-disco-store.c b/camel/camel-disco-store.c
index 4ef1886..349eb7b 100644
--- a/camel/camel-disco-store.c
+++ b/camel/camel-disco-store.c
@@ -152,8 +152,6 @@ disco_store_connect_sync (CamelService *service,
 			return FALSE;
 		}
 
-		if (!camel_service_disconnect_sync (service, TRUE, cancellable, error))
-			return FALSE;
 		return camel_service_connect_sync (service, cancellable, error);
 
 	case CAMEL_DISCO_STORE_OFFLINE:
@@ -359,10 +357,12 @@ disco_store_set_status (CamelDiscoStore *disco_store,
 			FALSE, cancellable, NULL);
 	}
 
-	if (!camel_service_disconnect_sync (
-		CAMEL_SERVICE (disco_store),
-		network_available, cancellable, error))
-		return FALSE;
+	if (camel_service_get_connection_status (CAMEL_SERVICE (disco_store)) != CAMEL_SERVICE_CONNECTING) {
+		if (!camel_service_disconnect_sync (
+			CAMEL_SERVICE (disco_store),
+			network_available, cancellable, error))
+			return FALSE;
+	}
 
 	disco_store->status = status;
 
diff --git a/camel/camel-service.c b/camel/camel-service.c
index ad4cfb8..46e9e1e 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -495,7 +495,7 @@ service_shared_disconnect_cb (GObject *source_object,
 	if (service->priv->connection_op == op) {
 		connection_op_unref (service->priv->connection_op);
 		service->priv->connection_op = NULL;
-		if (success)
+		if (success || service->priv->status == CAMEL_SERVICE_CONNECTING)
 			service->priv->status = CAMEL_SERVICE_DISCONNECTED;
 		else
 			service->priv->status = CAMEL_SERVICE_CONNECTED;
@@ -1899,8 +1899,14 @@ camel_service_disconnect (CamelService *service,
 			op = connection_op_new (simple, cancellable);
 			service->priv->connection_op = op;
 
-			service->priv->status = CAMEL_SERVICE_DISCONNECTING;
-			service_queue_notify_connection_status (service);
+			/* Do not change the status if "Connecting" - in case a provider calls
+			   "Disconnect" during the connection phase, which confuses the other
+			   logic here, effectively makes the service's connection state "Connected",
+			   instead of "Disconnected", at the end. */
+			if (service->priv->status != CAMEL_SERVICE_CONNECTING) {
+				service->priv->status = CAMEL_SERVICE_DISCONNECTING;
+				service_queue_notify_connection_status (service);
+			}
 
 			class->disconnect (
 				service, clean,
diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c
index 0605401..66edeca 100644
--- a/camel/providers/nntp/camel-nntp-store.c
+++ b/camel/providers/nntp/camel-nntp-store.c
@@ -2275,13 +2275,15 @@ camel_nntp_command (CamelNNTPStore *nntp_store,
 		case 400:	/* service discontinued */
 		case 401:	/* wrong client state - this should quit but this is what the old code did */
 		case 503:	/* information not available - this should quit but this is what the old code did (?) */
-			camel_service_disconnect_sync (
-				service, FALSE, cancellable, NULL);
+			if (camel_service_get_connection_status (service) != CAMEL_SERVICE_CONNECTING)
+				camel_service_disconnect_sync (
+					service, FALSE, cancellable, NULL);
 			ret = -1;
 			continue;
 		case -1:	/* i/o error */
-			camel_service_disconnect_sync (
-				service, FALSE, cancellable, NULL);
+			if (camel_service_get_connection_status (service) != CAMEL_SERVICE_CONNECTING)
+				camel_service_disconnect_sync (
+					service, FALSE, cancellable, NULL);
 			if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || retry >= 3) {
 				g_propagate_error (error, local_error);
 				ret = -1;
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 5aa226b..e906913 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -314,6 +314,8 @@ try_sasl (CamelPOP3Store *store,
 		goto ioerror;
 
 	while (1) {
+		GError *local_error = NULL;
+
 		if (camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, error) == -1)
 			goto ioerror;
 
@@ -332,10 +334,17 @@ try_sasl (CamelPOP3Store *store,
 		 * so fail, and try reset the server. */
 		if (strncmp ((gchar *) line, "+ ", 2) != 0
 		    || camel_sasl_get_authenticated (sasl)
-		    || (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2, cancellable, NULL)) == NULL) {
+		    || (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2, cancellable, &local_error)) == NULL) {
 			camel_stream_write_string (
 				CAMEL_STREAM (pop3_stream), "*\r\n", cancellable, NULL);
 			camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, NULL);
+
+			if (local_error) {
+				g_propagate_error (error, local_error);
+				local_error = NULL;
+				goto ioerror;
+			}
+
 			g_set_error (
 				error, CAMEL_SERVICE_ERROR,
 				CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
@@ -540,11 +549,8 @@ pop3_store_connect_sync (CamelService *service,
 	success = camel_session_authenticate_sync (
 		session, service, mechanism, cancellable, error);
 
-	if (!success) {
-		camel_service_disconnect_sync (
-			service, TRUE, cancellable, NULL);
+	if (!success)
 		goto exit;
-	}
 
 	/* Now that we are in the TRANSACTION state,
 	 * try regetting the capabilities */
diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c
index 8c46bec..40cec3c 100644
--- a/camel/providers/smtp/camel-smtp-transport.c
+++ b/camel/providers/smtp/camel-smtp-transport.c
@@ -184,9 +184,6 @@ connect_to_server (CamelService *service,
 		transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP;
 
 		if (!smtp_helo (transport, cancellable, error)) {
-			camel_service_disconnect_sync (
-				CAMEL_SERVICE (transport),
-				TRUE, cancellable, NULL);
 			success = FALSE;
 			goto exit;
 		}
@@ -250,9 +247,6 @@ connect_to_server (CamelService *service,
 	/* We are supposed to re-EHLO after a successful STARTTLS to
 	 * re-fetch any supported extensions. */
 	if (!smtp_helo (transport, cancellable, error)) {
-		camel_service_disconnect_sync (
-			CAMEL_SERVICE (transport),
-			TRUE, cancellable, NULL);
 		success = FALSE;
 	}
 
@@ -266,13 +260,14 @@ exception_cleanup:
 	g_object_unref (transport->ostream);
 	transport->ostream = NULL;
 
-	transport->connected = FALSE;
-
 	success = FALSE;
 
 exit:
 	g_free (host);
 
+	if (!success)
+		transport->connected = FALSE;
+
 	return success;
 }
 
@@ -429,8 +424,7 @@ smtp_transport_connect_sync (CamelService *service,
 		g_object_unref (session);
 
 		if (!success)
-			camel_service_disconnect_sync (
-				service, TRUE, cancellable, NULL);
+			transport->connected = FALSE;
 	}
 
 exit:
@@ -1203,10 +1197,6 @@ smtp_helo (CamelSmtpTransport *transport,
 		g_prefix_error (error, _("HELO command failed: "));
 		camel_operation_pop_message (cancellable);
 
-		camel_service_disconnect_sync (
-			CAMEL_SERVICE (transport),
-			FALSE, cancellable, NULL);
-
 		return FALSE;
 	}
 	g_free (cmdbuf);
