pop3_store_authenticate_sync (CamelService *service,
                              const gchar *mechanism,
                              GCancellable *cancellable,
                              GError **error)
{
	CamelPOP3Store *store = CAMEL_POP3_STORE (service);
	CamelNetworkSettings *network_settings;
	CamelAuthenticationResult result;
	CamelSettings *settings;
	CamelPOP3Command *pcu = NULL;
	CamelPOP3Command *pcp = NULL;
	CamelPOP3Engine *pop3_engine;
	const gchar *password;
	gboolean enable_utf8;
	gchar *host;
	gchar *user;
	gint status;

	password = camel_service_get_password (service);

	settings = camel_service_ref_settings (service);
	enable_utf8 = camel_pop3_settings_get_enable_utf8 (CAMEL_POP3_SETTINGS (settings));

	network_settings = CAMEL_NETWORK_SETTINGS (settings);
	host = camel_network_settings_dup_host (network_settings);
	user = camel_network_settings_dup_user (network_settings);

	g_object_unref (settings);

	pop3_engine = camel_pop3_store_ref_engine (store);
	if (!pop3_engine) {
		g_set_error_literal (
			error, CAMEL_SERVICE_ERROR,
			CAMEL_SERVICE_ERROR_UNAVAILABLE,
			_("You must be working online to complete this operation"));
		result = CAMEL_AUTHENTICATION_ERROR;
		goto exit;
	}

	if (!camel_pop3_engine_busy_lock (pop3_engine, cancellable, error)) {
		g_free (host);
		g_free (user);
		g_clear_object (&pop3_engine);

		return CAMEL_AUTHENTICATION_ERROR;
	}

	if ((pop3_engine->capa & CAMEL_POP3_CAP_UTF8) != 0 && enable_utf8) {
		pcu = camel_pop3_engine_command_new (
			pop3_engine, 0, NULL, NULL, cancellable, error,
			"UTF8");
		if (error && *error) {
			g_prefix_error (
				error,
				_("Unable to connect to POP server %s.\n"
				"Error enabling UTF-8 mode: "), host);
			result = CAMEL_AUTHENTICATION_ERROR;
			goto exit;
		}
		while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
			;
		camel_pop3_engine_command_free (pop3_engine, pcu);
		pcu = NULL;
	}

	if (mechanism == NULL) {
		if (password == NULL) {
			g_set_error_literal (
				error, CAMEL_SERVICE_ERROR,
				CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
				_("Authentication password not available"));
			result = CAMEL_AUTHENTICATION_ERROR;
			goto exit;
		}

		/* pop engine will take care of pipelining ability */
		pcu = camel_pop3_engine_command_new (
			pop3_engine, 0, NULL, NULL, cancellable, error,
			"USER %s\r\n", user);
		if (error && *error) {
			g_prefix_error (
				error,
				_("Unable to connect to POP server %s.\n"
				"Error sending password: "), host);
			result = CAMEL_AUTHENTICATION_ERROR;
			goto exit;
		}

		pcp = camel_pop3_engine_command_new (
			pop3_engine, 0, NULL, NULL, cancellable, error,
			"PASS %s\r\n", password);

		if (error && *error) {
			g_prefix_error (
				error,
				_("Unable to connect to POP server %s.\n"
				"Error sending password: "), host);
			result = CAMEL_AUTHENTICATION_ERROR;
			goto exit;
		}
	} else if (strcmp (mechanism, "+APOP") == 0 && pop3_engine->apop) {
		gchar *secret, *md5asc, *d;
		gsize secret_len;

		if (password == NULL) {
			g_set_error_literal (
				error, CAMEL_SERVICE_ERROR,
				CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
				_("Authentication password not available"));
			result = CAMEL_AUTHENTICATION_ERROR;
			goto exit;
		}

		d = pop3_engine->apop;

		while (*d != '\0') {
			if (!isascii ((gint) * d)) {

				g_set_error (
					error, CAMEL_SERVICE_ERROR,
					CAMEL_SERVICE_ERROR_URL_INVALID,
					/* Translators: Do not translate APOP. */
					_("Unable to connect to POP server %s:	"
					"Invalid APOP ID received. Impersonation "
					"attack suspected. Please contact your admin."),
					host);

				result = CAMEL_AUTHENTICATION_ERROR;
				goto exit;
			}
			d++;
		}

		secret_len =
			strlen (pop3_engine->apop) +
			strlen (password) + 1;
		secret = g_alloca (secret_len);
		g_snprintf (
			secret, secret_len, "%s%s",
			pop3_engine->apop, password);
		md5asc = g_compute_checksum_for_string (
			G_CHECKSUM_MD5, secret, -1);
		pcp = camel_pop3_engine_command_new (
			pop3_engine, 0, NULL, NULL, cancellable, error,
			"APOP %s %s\r\n", user, md5asc);
		g_free (md5asc);

	} else {
		GList *link;
		const gchar *test_mechanism = mechanism;

		if (camel_sasl_is_xoauth2_alias (test_mechanism))
			test_mechanism = "XOAUTH2";

		link = pop3_engine->auth;
		while (link != NULL) {
			CamelServiceAuthType *auth = link->data;

			if (g_strcmp0 (auth->authproto, test_mechanism) == 0) {
				result = try_sasl (
					store, mechanism,
					cancellable, error);
				goto exit;
			}
			link = g_list_next (link);
		}

		g_set_error (
			error, CAMEL_SERVICE_ERROR,
			CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
			_("No support for %s authentication"), mechanism);
		result = CAMEL_AUTHENTICATION_ERROR;
		goto exit;
	}

	while ((status = camel_pop3_engine_iterate (pop3_engine, pcp, cancellable, error)) > 0)
		;

	if (status == -1) {
		g_prefix_error (
			error,
			_("Unable to connect to POP server %s.\n"
			"Error sending password: "), host);
		result = CAMEL_AUTHENTICATION_ERROR;

	} else if (pcu && pcu->state != CAMEL_POP3_COMMAND_OK) {
		gchar *tmp;

		/* Abort authentication if the server rejects the user
		 * name.  Reprompting for a password won't do any good. */
		tmp = get_valid_utf8_error ((gchar *) pop3_engine->line);
		g_set_error (
			error, CAMEL_SERVICE_ERROR,
			CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
			/* Translators: Last %s is an optional explanation
			 * beginning with ": " separator. */
			_("Unable to connect to POP server %s.\n"
			"Error sending username%s"),
			host, (tmp != NULL) ? tmp : "");
		g_free (tmp);
		result = CAMEL_AUTHENTICATION_ERROR;

	} else if (pcp->state != CAMEL_POP3_COMMAND_OK) {
		result = CAMEL_AUTHENTICATION_REJECTED;
	} else {
		result = CAMEL_AUTHENTICATION_ACCEPTED;
	}

exit:
	if (pcp != NULL)
		camel_pop3_engine_command_free (pop3_engine, pcp);

	if (pcu != NULL)
		camel_pop3_engine_command_free (pop3_engine, pcu);

	g_free (host);
	g_free (user);

	camel_pop3_engine_busy_unlock (pop3_engine);
	g_clear_object (&pop3_engine);

	return result;
}