File 0001-Added-yandex-backend-support-prebuild.patch of Package evolution-data-server

From 5e4f0862a99e6fa628ded59938772f2604a6caee Mon Sep 17 00:00:00 2001
From: tigro <tigro@msvsphere-os.ru>
Date: Wed, 24 Dec 2025 17:41:39 +0300
Subject: [PATCH] Added yandex backend support prebuild

---
 CMakeLists.txt                                |  11 +
 config.h.in                                   |   6 +
 data/CMakeLists.txt                           |  26 +
 ...gnome.evolution-data-server.gschema.xml.in |  10 +
 po/POTFILES.in                                |   3 +
 src/camel/CMakeLists.txt                      |   2 +
 src/camel/camel-autocleanups.h                |   1 +
 src/camel/camel-sasl-xoauth2-yandex.c         |  44 ++
 src/camel/camel-sasl-xoauth2-yandex.h         |  63 ++
 src/camel/camel-sasl.c                        |   2 +
 src/camel/camel.h                             |   1 +
 src/libebackend/e-webdav-collection-backend.c |   2 +-
 src/libedataserver/CMakeLists.txt             |   2 +
 .../e-dataserver-autocleanups.h               |   1 +
 src/libedataserver/e-oauth2-service-yandex.c  | 214 ++++++
 src/libedataserver/e-oauth2-service-yandex.h  |  62 ++
 src/libedataserver/e-oauth2-services.c        |   2 +
 src/libedataserver/e-soup-auth-bearer.c       |  22 +-
 src/libedataserver/e-soup-auth-bearer.h       |   4 +
 src/libedataserver/e-soup-session.c           |  21 +
 src/libedataserver/libedataserver.h           |   1 +
 src/modules/CMakeLists.txt                    |   1 +
 .../module-gnome-online-accounts.c            |   3 +
 src/modules/yandex-backend/CMakeLists.txt     |  17 +
 .../yandex-backend/module-yandex-backend.c    | 619 ++++++++++++++++++
 25 files changed, 1138 insertions(+), 2 deletions(-)
 create mode 100644 src/camel/camel-sasl-xoauth2-yandex.c
 create mode 100644 src/camel/camel-sasl-xoauth2-yandex.h
 create mode 100644 src/libedataserver/e-oauth2-service-yandex.c
 create mode 100644 src/libedataserver/e-oauth2-service-yandex.h
 create mode 100644 src/modules/yandex-backend/CMakeLists.txt
 create mode 100644 src/modules/yandex-backend/module-yandex-backend.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c37366..2370c35 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -479,6 +479,17 @@ if(WITH_YAHOO_CLIENT_SECRET STREQUAL "")
 	set(WITH_YAHOO_CLIENT_SECRET "|c3UmdHkmcXl5JCR3dXQlI3UleHYkcyN3IyR1d3YhcXN0cSN5IiNwIkA=|")
 endif(WITH_YAHOO_CLIENT_SECRET STREQUAL "")
 
+add_printable_variable(WITH_YANDEX_CLIENT_ID "Yandex OAuth 2.0 client id" "")
+add_printable_variable(WITH_YANDEX_CLIENT_SECRET "Yandex OAuth 2.0 client secret" "")
+
+if(WITH_YANDEX_CLIENT_ID STREQUAL "")
+	set(WITH_YANDEX_CLIENT_ID "aab3f89a0d504003bfa3bb5326f68575")
+endif(WITH_YANDEX_CLIENT_ID STREQUAL "")
+
+if(WITH_YANDEX_CLIENT_SECRET STREQUAL "")
+	set(WITH_YANDEX_CLIENT_SECRET "4e6f4755f2ec457e9a80f0f43683fc32")
+endif(WITH_YANDEX_CLIENT_SECRET STREQUAL "")
+
 # ******************************************
 # Check whether to build examples/demos
 # ******************************************
diff --git a/config.h.in b/config.h.in
index aa381f2..6d63b64 100644
--- a/config.h.in
+++ b/config.h.in
@@ -60,6 +60,12 @@
 /* Define Yahoo! OAuth 2.0 Client Secret to use */
 #define YAHOO_CLIENT_SECRET "@WITH_YAHOO_CLIENT_SECRET@"
 
+/* Define Yandex OAuth 2.0 Client ID to use */
+#define YANDEX_CLIENT_ID "@WITH_YANDEX_CLIENT_ID@"
+
+/* Define Yandex OAuth 2.0 Client Secret to use */
+#define YANDEX_CLIENT_SECRET "@WITH_YANDEX_CLIENT_SECRET@"
+
 /* Path to a sendmail binary, or equivalent */
 #define SENDMAIL_PATH "@SENDMAIL_PATH@"
 
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 5cdd467..9995cf8 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -54,6 +54,32 @@ if(NOT WITH_GOOGLE_CLIENT_ID STREQUAL "")
 	unset(_google_oauth2_scheme)
 endif(NOT WITH_GOOGLE_CLIENT_ID STREQUAL "")
 
+
+# if(NOT WITH_YANDEX_CLIENT_ID STREQUAL "")
+# 	set(CMAKE_REQUIRED_DEFINITIONS ${DATA_SERVER_CFLAGS})
+# 	set(CMAKE_REQUIRED_INCLUDES ${CMAKE_BINARY_DIR} ${DATA_SERVER_INCLUDE_DIRS})
+# 	set(CMAKE_REQUIRED_LIBRARIES ${DATA_SERVER_LDFLAGS})
+# 	list(APPEND CMAKE_REQUIRED_DEFINITIONS -DG_LOG_DOMAIN=\"oauth2-value-helper\" -DBUILDING_VALUE_HELPER=1)
+# 	file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/oauth2-yandex-client-id" _binary_dir_to_file)
+# 	CHECK_C_SOURCE_RUNS("#define DECODE_KEY \"${WITH_YANDEX_CLIENT_ID}\"
+# 			     #define DECODE_TO_FILE \"${_binary_dir_to_file}\"
+# 			     #define DECODE_REVERSED 1
+# 			     #include \"${CMAKE_SOURCE_DIR}/src/libedataserver/e-oauth2-service.c\"" _decoded)
+# 	file(READ ${_binary_dir_to_file} _yandex_oauth2_scheme)
+# 	unset(_binary_dir_to_file)
+# 	unset(_decoded)
+# 	unset(CMAKE_REQUIRED_LIBRARIES)
+# 	unset(CMAKE_REQUIRED_INCLUDES)
+# 	unset(CMAKE_REQUIRED_DEFINITIONS)
+#
+# 	if(NOT _yandex_oauth2_scheme STREQUAL "")
+# 		set(OAUTH2_SCHEMES "x-scheme-handler/${_yandex_oauth2_scheme};${OAUTH2_SCHEMES}")
+# 	endif(NOT _yandex_oauth2_scheme STREQUAL "")
+# 	unset(_yandex_oauth2_scheme)
+# endif(NOT WITH_YANDEX_CLIENT_ID STREQUAL "")
+
+set(OAUTH2_SCHEMES "x-scheme-handler/eds-oauth2;")
+
 configure_file(org.gnome.evolution-data-server.OAuth2-handler.desktop.in
 	org.gnome.evolution-data-server.OAuth2-handler.desktop.in
 	@ONLY
diff --git a/data/org.gnome.evolution-data-server.gschema.xml.in b/data/org.gnome.evolution-data-server.gschema.xml.in
index b66c019..d171255 100644
--- a/data/org.gnome.evolution-data-server.gschema.xml.in
+++ b/data/org.gnome.evolution-data-server.gschema.xml.in
@@ -86,6 +86,16 @@
       <summary>An OAuth2 client secret to use to connect to Yahoo! servers, instead of the one provided during build time</summary>
       <description>User-specified OAuth2 client secret for Yahoo! servers. Empty string means to use the one provided during build time. Change of this requires restart.</description>
     </key>
+    <key name="oauth2-yandex-client-id" type="s">
+      <default>''</default>
+      <summary>An OAuth2 client ID to use to connect to Yandex servers, instead of the one provided during build time</summary>
+      <description>User-specified OAuth2 client ID for Yandex servers. Empty string means to use the one provided during build time. Change of this requires restart.</description>
+    </key>
+    <key name="oauth2-yandex-client-secret" type="s">
+      <default>''</default>
+      <summary>An OAuth2 client secret to use to connect to Yandex servers, instead of the one provided during build time</summary>
+      <description>User-specified OAuth2 client secret for Yandex servers. Empty string means to use the one provided during build time. Change of this requires restart.</description>
+    </key>
     <key name="limit-operations-in-power-saver-mode" type="b">
       <default>false</default>
       <summary>Whether to limit operations in Power Saver mode</summary>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b53323d..a209363 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -113,6 +113,7 @@ src/camel/camel-sasl-xoauth2.c
 src/camel/camel-sasl-xoauth2-google.c
 src/camel/camel-sasl-xoauth2-outlook.c
 src/camel/camel-sasl-xoauth2-yahoo.c
+src/camel/camel-sasl-xoauth2-yandex.c
 src/camel/camel-search-private.c
 src/camel/camel-service.c
 src/camel/camel-session.c
@@ -199,6 +200,7 @@ src/libedataserver/e-oauth2-service.c
 src/libedataserver/e-oauth2-service-google.c
 src/libedataserver/e-oauth2-service-outlook.c
 src/libedataserver/e-oauth2-service-yahoo.c
+src/libedataserver/e-oauth2-service-yandex.c
 src/libedataserver/e-soup-session.c
 src/libedataserver/e-source.c
 src/libedataserver/e-source-credentials-provider-impl.c
@@ -225,6 +227,7 @@ src/modules/google-backend/module-google-backend.c
 src/modules/trust-prompt/module-trust-prompt.c
 src/modules/trust-prompt/trust-prompt-gtk.c
 src/modules/yahoo-backend/module-yahoo-backend.c
+src/modules/yandex-backend/module-yandex-backend.c
 src/services/evolution-addressbook-factory/evolution-addressbook-factory.c
 src/services/evolution-alarm-notify/e-alarm-notify.c
 src/services/evolution-calendar-factory/evolution-calendar-factory.c
diff --git a/src/camel/CMakeLists.txt b/src/camel/CMakeLists.txt
index 228defd..4d81587 100644
--- a/src/camel/CMakeLists.txt
+++ b/src/camel/CMakeLists.txt
@@ -111,6 +111,7 @@ set(SOURCES
 	camel-sasl-xoauth2-google.c
 	camel-sasl-xoauth2-outlook.c
 	camel-sasl-xoauth2-yahoo.c
+	camel-sasl-xoauth2-yandex.c
 	camel-sasl.c
 	camel-search-private.c
 	camel-search-utils.c
@@ -255,6 +256,7 @@ set(HEADERS
 	camel-sasl-xoauth2-google.h
 	camel-sasl-xoauth2-outlook.h
 	camel-sasl-xoauth2-yahoo.h
+	camel-sasl-xoauth2-yandex.h
 	camel-sasl.h
 	camel-search-private.h
 	camel-search-utils.h
diff --git a/src/camel/camel-autocleanups.h b/src/camel/camel-autocleanups.h
index c9c6ca8..b1336b0 100644
--- a/src/camel/camel-autocleanups.h
+++ b/src/camel/camel-autocleanups.h
@@ -108,6 +108,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslPlain, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslPOPB4SMTP, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2Google, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2Yandex, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2Outlook, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelService, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelServiceAuthType, camel_service_auth_type_free)
diff --git a/src/camel/camel-sasl-xoauth2-yandex.c b/src/camel/camel-sasl-xoauth2-yandex.c
new file mode 100644
index 0000000..234839a
--- /dev/null
+++ b/src/camel/camel-sasl-xoauth2-yandex.c
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "camel-sasl-xoauth2-yandex.h"
+
+static CamelServiceAuthType sasl_xoauth2_yandex_auth_type = {
+	N_("OAuth2 (Yandex)"),
+	N_("This option will use an OAuth 2.0 "
+	   "access token to connect to the yandex server"),
+	"Yandex",
+	FALSE
+};
+
+G_DEFINE_TYPE (CamelSaslXOAuth2Yandex, camel_sasl_xoauth2_yandex, CAMEL_TYPE_SASL_XOAUTH2)
+
+static void
+camel_sasl_xoauth2_yandex_class_init (CamelSaslXOAuth2YandexClass *klass)
+{
+	CamelSaslClass *sasl_class;
+
+	sasl_class = CAMEL_SASL_CLASS (klass);
+	sasl_class->auth_type = &sasl_xoauth2_yandex_auth_type;
+}
+
+static void
+camel_sasl_xoauth2_yandex_init (CamelSaslXOAuth2Yandex *sasl)
+{
+}
diff --git a/src/camel/camel-sasl-xoauth2-yandex.h b/src/camel/camel-sasl-xoauth2-yandex.h
new file mode 100644
index 0000000..0141ef9
--- /dev/null
+++ b/src/camel/camel-sasl-xoauth2-yandex.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_SASL_XOAUTH2_YANDEX_H
+#define CAMEL_SASL_XOAUTH2_YANDEX_H
+
+#include <camel/camel-sasl-xoauth2.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_SASL_XOAUTH2_YANDEX \
+	(camel_sasl_xoauth2_yandex_get_type ())
+#define CAMEL_SASL_XOAUTH2_YANDEX(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), CAMEL_TYPE_SASL_XOAUTH2_YANDEX, CamelSaslXOAuth2Yandex))
+#define CAMEL_SASL_XOAUTH2_YANDEX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), CAMEL_TYPE_SASL_XOAUTH2_YANDEX, CamelSaslXOAuth2YandexClass))
+#define CAMEL_IS_SASL_XOAUTH2_YANDEX(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), CAMEL_TYPE_SASL_XOAUTH2_YANDEX))
+#define CAMEL_IS_SASL_XOAUTH2_YANDEX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), CAMEL_TYPE_SASL_XOAUTH2_YANDEX))
+#define CAMEL_SASL_XOAUTH2_YANDEX_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), CAMEL_TYPE_SASL_XOAUTH2_YANDEX, CamelSaslXOAuth2YandexClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelSaslXOAuth2Yandex CamelSaslXOAuth2Yandex;
+typedef struct _CamelSaslXOAuth2YandexClass CamelSaslXOAuth2YandexClass;
+typedef struct _CamelSaslXOAuth2YandexPrivate CamelSaslXOAuth2YandexPrivate;
+
+struct _CamelSaslXOAuth2Yandex {
+	CamelSaslXOAuth2 parent;
+	CamelSaslXOAuth2YandexPrivate *priv;
+};
+
+struct _CamelSaslXOAuth2YandexClass {
+	CamelSaslXOAuth2Class parent_class;
+};
+
+GType		camel_sasl_xoauth2_yandex_get_type	(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* CAMEL_SASL_XOAUTH2_YANDEX_H */
diff --git a/src/camel/camel-sasl.c b/src/camel/camel-sasl.c
index b6eb4b1..d62df5d 100644
--- a/src/camel/camel-sasl.c
+++ b/src/camel/camel-sasl.c
@@ -34,6 +34,7 @@
 #include "camel-sasl-xoauth2-google.h"
 #include "camel-sasl-xoauth2-outlook.h"
 #include "camel-sasl-xoauth2-yahoo.h"
+#include "camel-sasl-xoauth2-yandex.h"
 #include "camel-sasl.h"
 #include "camel-service.h"
 
@@ -135,6 +136,7 @@ sasl_build_class_table (void)
 	g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_GOOGLE);
 	g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_OUTLOOK);
 	g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_YAHOO);
+	g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_YANDEX);
 
 	class_table = g_hash_table_new_full (
 		(GHashFunc) g_str_hash,
diff --git a/src/camel/camel.h b/src/camel/camel.h
index b6d1842..e6854bc 100644
--- a/src/camel/camel.h
+++ b/src/camel/camel.h
@@ -111,6 +111,7 @@
 #include <camel/camel-sasl-xoauth2-google.h>
 #include <camel/camel-sasl-xoauth2-outlook.h>
 #include <camel/camel-sasl-xoauth2-yahoo.h>
+#include <camel/camel-sasl-xoauth2-yandex.h>
 #include <camel/camel-search-utils.h>
 #include <camel/camel-service.h>
 #include <camel/camel-session.h>
diff --git a/src/libebackend/e-webdav-collection-backend.c b/src/libebackend/e-webdav-collection-backend.c
index 2706cbc..ceb45c3 100644
--- a/src/libebackend/e-webdav-collection-backend.c
+++ b/src/libebackend/e-webdav-collection-backend.c
@@ -480,7 +480,7 @@ webdav_collection_backend_populate (ECollectionBackend *collection)
 			auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
 			method = e_source_authentication_dup_method (auth_extension);
 			user = e_source_authentication_dup_user (auth_extension);
-			needs_credentials = user && *user && g_strcmp0 (method, "OAuth2") != 0 &&
+			needs_credentials = user && *user && (g_strcmp0 (method, "OAuth2") != 0 || g_strcmp0 (method, "Yandex") != 0) &&
 				!e_oauth2_services_is_oauth2_alias (e_source_registry_server_get_oauth2_services (server), method);
 			g_free (method);
 			g_free (user);
diff --git a/src/libedataserver/CMakeLists.txt b/src/libedataserver/CMakeLists.txt
index 3806914..997b36d 100644
--- a/src/libedataserver/CMakeLists.txt
+++ b/src/libedataserver/CMakeLists.txt
@@ -73,6 +73,7 @@ set(SOURCES
 	e-oauth2-service-google.c
 	e-oauth2-service-outlook.c
 	e-oauth2-service-yahoo.c
+	e-oauth2-service-yandex.c
 	e-oauth2-services.c
 	e-operation-pool.c
 	e-secret-store.c
@@ -167,6 +168,7 @@ set(HEADERS
 	e-oauth2-service-google.h
 	e-oauth2-service-outlook.h
 	e-oauth2-service-yahoo.h
+	e-oauth2-service-yandex.h
 	e-oauth2-services.h
 	e-operation-pool.h
 	e-secret-store.h
diff --git a/src/libedataserver/e-dataserver-autocleanups.h b/src/libedataserver/e-dataserver-autocleanups.h
index f432984..f66dd5a 100644
--- a/src/libedataserver/e-dataserver-autocleanups.h
+++ b/src/libedataserver/e-dataserver-autocleanups.h
@@ -40,6 +40,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(ENetworkMonitor, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2Service, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceBase, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceGoogle, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceYandex, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceOutlook, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2Services, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOperationPool, e_operation_pool_free)
diff --git a/src/libedataserver/e-oauth2-service-yandex.c b/src/libedataserver/e-oauth2-service-yandex.c
new file mode 100644
index 0000000..008e416
--- /dev/null
+++ b/src/libedataserver/e-oauth2-service-yandex.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "e-oauth2-service.h"
+#include "e-oauth2-service-base.h"
+#include "e-data-server-util.h"
+#include "e-oauth2-service-yandex.h"
+
+/* Forward Declarations */
+static void e_oauth2_service_yandex_oauth2_service_init (EOAuth2ServiceInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EOAuth2ServiceYandex, e_oauth2_service_yandex, E_TYPE_OAUTH2_SERVICE_BASE,
+	G_IMPLEMENT_INTERFACE (E_TYPE_OAUTH2_SERVICE, e_oauth2_service_yandex_oauth2_service_init))
+
+static gboolean
+eos_yandex_guess_can_process (EOAuth2Service *service,
+			      const gchar *protocol,
+			      const gchar *hostname)
+{
+	return hostname && (
+		e_util_utf8_strstrcase (hostname, ".yandex.ru") ||
+		e_util_utf8_strstrcase (hostname, ".ya.ru") ||
+		e_util_utf8_strstrcase (hostname, ".yandex.com"));
+}
+
+static const gchar *
+eos_yandex_get_name (EOAuth2Service *service)
+{
+	return "Yandex";
+}
+
+static const gchar *
+eos_yandex_get_display_name (EOAuth2Service *service)
+{
+	/* Translators: This is a user-visible string, display name of an OAuth2 service. */
+	return C_("OAuth2Service", "yandex");
+}
+
+static const gchar *
+eos_yandex_read_settings (EOAuth2Service *service,
+			  const gchar *key_name)
+{
+	G_LOCK_DEFINE_STATIC (user_settings);
+	gchar *value;
+
+	G_LOCK (user_settings);
+
+	value = g_object_get_data (G_OBJECT (service), key_name);
+	if (!value) {
+		GSettings *settings;
+
+		settings = g_settings_new ("org.gnome.evolution-data-server");
+		value = g_settings_get_string (settings, key_name);
+		g_object_unref (settings);
+
+		if (value && *value) {
+			g_object_set_data_full (G_OBJECT (service), key_name, value, g_free);
+		} else {
+			g_free (value);
+			value = (gchar *) "";
+
+			g_object_set_data (G_OBJECT (service), key_name, value);
+		}
+	}
+
+	G_UNLOCK (user_settings);
+
+	return value;
+}
+
+static const gchar *
+eos_yandex_get_client_id (EOAuth2Service *service,
+			  ESource *source)
+{
+	const gchar *client_id;
+
+	client_id = eos_yandex_read_settings (service, "oauth2-yandex-client-id");
+
+	if (client_id && *client_id)
+		return client_id;
+
+	return YANDEX_CLIENT_ID;
+}
+
+static const gchar *
+eos_yandex_get_client_secret (EOAuth2Service *service,
+			      ESource *source)
+{
+	const gchar *client_secret;
+
+	client_secret = eos_yandex_read_settings (service, "oauth2-yandex-client-secret");
+
+	if (client_secret && *client_secret)
+		return client_secret;
+
+	return YANDEX_CLIENT_SECRET;
+}
+
+static const gchar *
+eos_yandex_get_authentication_uri (EOAuth2Service *service,
+				   ESource *source)
+{
+	return "https://oauth.yandex.ru/authorize";
+}
+
+static const gchar *
+eos_yandex_get_refresh_uri (EOAuth2Service *service,
+			    ESource *source)
+{
+	return "https://oauth.yandex.ru/token";
+}
+
+static void
+eos_yandex_prepare_authentication_uri_query (EOAuth2Service *service,
+					     ESource *source,
+					     GHashTable *uri_query)
+{
+	const gchar *YANDEX_SCOPE =
+		/* GMail IMAP and SMTP access */
+		"login:email login:info mail:imap_full mail:imap_ro mail:smtp calendar:all";
+
+	g_return_if_fail (uri_query != NULL);
+
+	e_oauth2_service_util_set_to_form (uri_query, "scope", YANDEX_SCOPE);
+	e_oauth2_service_util_set_to_form (uri_query, "include_granted_scopes", "false");
+}
+
+static gboolean
+eos_yandex_extract_authorization_code (EOAuth2Service *service,
+				       ESource *source,
+				       const gchar *page_title,
+				       const gchar *page_uri,
+				       const gchar *page_content,
+				       gchar **out_authorization_code)
+{
+	g_return_val_if_fail (out_authorization_code != NULL, FALSE);
+
+	*out_authorization_code = NULL;
+
+	if (page_uri && *page_uri) {
+		GUri *suri;
+
+		suri = g_uri_parse (page_uri, SOUP_HTTP_URI_FLAGS, NULL);
+		if (suri) {
+			const gchar *query = g_uri_get_query (suri);
+			gboolean known = FALSE;
+
+			if (query && *query) {
+				GHashTable *params;
+
+				params = soup_form_decode (query);
+				if (params) {
+					const gchar *response;
+
+					response = g_hash_table_lookup (params, "code");
+					if (response) {
+						*out_authorization_code = g_strdup (response);
+						known = TRUE;
+					}
+
+					g_hash_table_destroy (params);
+				}
+			}
+
+//			soup_uri_free (suri);
+
+			if (known)
+				return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static void
+e_oauth2_service_yandex_oauth2_service_init (EOAuth2ServiceInterface *iface)
+{
+	iface->guess_can_process = eos_yandex_guess_can_process;
+	iface->get_name = eos_yandex_get_name;
+	iface->get_display_name = eos_yandex_get_display_name;
+	iface->get_client_id = eos_yandex_get_client_id;
+	iface->get_client_secret = eos_yandex_get_client_secret;
+	iface->get_authentication_uri = eos_yandex_get_authentication_uri;
+	iface->get_refresh_uri = eos_yandex_get_refresh_uri;
+	iface->prepare_authentication_uri_query = eos_yandex_prepare_authentication_uri_query;
+	iface->extract_authorization_code = eos_yandex_extract_authorization_code;
+}
+
+static void
+e_oauth2_service_yandex_class_init (EOAuth2ServiceYandexClass *klass)
+{
+}
+
+static void
+e_oauth2_service_yandex_init (EOAuth2ServiceYandex *oauth2_google)
+{
+}
diff --git a/src/libedataserver/e-oauth2-service-yandex.h b/src/libedataserver/e-oauth2-service-yandex.h
new file mode 100644
index 0000000..0011fd9
--- /dev/null
+++ b/src/libedataserver/e-oauth2-service-yandex.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__LIBEDATASERVER_H_INSIDE__) && !defined (LIBEDATASERVER_COMPILATION)
+#error "Only <libedataserver/libedataserver.h> should be included directly."
+#endif
+
+#ifndef E_OAUTH2_SERVICE_YANDEX_H
+#define E_OAUTH2_SERVICE_YANDEX_H
+
+#include <libedataserver/e-oauth2-service-base.h>
+
+/* Standard GObject macros */
+#define E_TYPE_OAUTH2_SERVICE_YANDEX \
+	(e_oauth2_service_yandex_get_type ())
+#define E_OAUTH2_SERVICE_YANDEX(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_OAUTH2_SERVICE_YANDEX, EOAuth2ServiceYandex))
+#define E_OAUTH2_SERVICE_YANDEX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_OAUTH2_SERVICE_YANDEX, EOAuth2ServiceYandexClass))
+#define E_IS_OAUTH2_SERVICE_YANDEX(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_OAUTH2_SERVICE_YANDEX))
+#define E_IS_OAUTH2_SERVICE_YANDEX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_OAUTH2_SERVICE_YANDEX))
+#define E_OAUTH2_SERVICE_YANDEX_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_OAUTH2_SERVICE_YANDEX, EOAuth2ServiceYandexClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EOAuth2ServiceYandex EOAuth2ServiceYandex;
+typedef struct _EOAuth2ServiceYandexClass EOAuth2ServiceYandexClass;
+
+struct _EOAuth2ServiceYandex {
+	EOAuth2ServiceBase parent;
+};
+
+struct _EOAuth2ServiceYandexClass {
+	EOAuth2ServiceBaseClass parent_class;
+};
+
+GType		e_oauth2_service_yandex_get_type	(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* E_OAUTH2_SERVICE_YANDEX_H */
diff --git a/src/libedataserver/e-oauth2-services.c b/src/libedataserver/e-oauth2-services.c
index fc029fe..924d1a8 100644
--- a/src/libedataserver/e-oauth2-services.c
+++ b/src/libedataserver/e-oauth2-services.c
@@ -35,6 +35,7 @@
 
 /* Known built-in implementations */
 #include "e-oauth2-service-google.h"
+#include "e-oauth2-service-yandex.h"
 #include "e-oauth2-service-outlook.h"
 #include "e-oauth2-service-yahoo.h"
 
@@ -135,6 +136,7 @@ e_oauth2_services_class_init (EOAuth2ServicesClass *klass)
 
 	/* Ensure built-in service types are registered */
 	g_type_ensure (E_TYPE_OAUTH2_SERVICE_GOOGLE);
+	g_type_ensure (E_TYPE_OAUTH2_SERVICE_YANDEX);
 	g_type_ensure (E_TYPE_OAUTH2_SERVICE_OUTLOOK);
 	g_type_ensure (E_TYPE_OAUTH2_SERVICE_YAHOO);
 }
diff --git a/src/libedataserver/e-soup-auth-bearer.c b/src/libedataserver/e-soup-auth-bearer.c
index ccf0136..310c781 100644
--- a/src/libedataserver/e-soup-auth-bearer.c
+++ b/src/libedataserver/e-soup-auth-bearer.c
@@ -41,6 +41,8 @@
 #define AUTH_STRENGTH 1
 
 #define EXPIRY_INVALID ((time_t) -1)
+#define DEFAULT_BEARER_AUTH (gchar)0
+#define MAX_CUSTOM_BEARER_ID 16
 
 /* How many seconds earlier than reported by the server is the token considered expired. */
 #define TOKEN_VALIDITY_GAP_SECS 5
@@ -49,6 +51,7 @@ struct _ESoupAuthBearerPrivate {
 	GMutex property_lock;
 	gchar *access_token;
 	time_t expiry;
+	gchar is_custom_bearer[MAX_CUSTOM_BEARER_ID];
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (
@@ -194,7 +197,10 @@ e_soup_auth_bearer_get_authorization (SoupAuth *auth,
 
 	g_mutex_lock (&bearer->priv->property_lock);
 
-	res = g_strdup_printf ("Bearer %s", bearer->priv->access_token);
+	if (!bearer->priv->is_custom_bearer[0])
+		res = g_strdup_printf ("Bearer %s", bearer->priv->access_token);
+	else
+		res = g_strdup_printf ("%s %s", bearer->priv->is_custom_bearer, bearer->priv->access_token);
 
 	e_soup_auth_bearer_debug_print ("%s: bearer:%p message:%p; status:%u token:%p expired:%d\n",
 		G_STRFUNC, bearer, message, soup_message_get_status (message),
@@ -249,6 +255,7 @@ e_soup_auth_bearer_init (ESoupAuthBearer *bearer)
 {
 	bearer->priv = e_soup_auth_bearer_get_instance_private (bearer);
 	bearer->priv->expiry = EXPIRY_INVALID;
+	bearer->priv->is_custom_bearer[0] = DEFAULT_BEARER_AUTH;
 
 	g_mutex_init (&bearer->priv->property_lock);
 }
@@ -343,3 +350,16 @@ e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer)
 
 	return expired;
 }
+
+gboolean
+e_soup_auth_bearer_set_custom_bearer_name (ESoupAuthBearer *bearer, const gchar *bearer_name)
+{
+	if (!bearer) return TRUE;
+	g_return_val_if_fail (E_IS_SOUP_AUTH_BEARER (bearer), TRUE);
+
+	g_mutex_lock (&bearer->priv->property_lock);
+	g_utf8_strncpy(bearer->priv->is_custom_bearer, bearer_name, MAX_CUSTOM_BEARER_ID-1);
+	g_mutex_unlock (&bearer->priv->property_lock);
+
+	return TRUE;
+}
diff --git a/src/libedataserver/e-soup-auth-bearer.h b/src/libedataserver/e-soup-auth-bearer.h
index 545bf02..a6cb576 100644
--- a/src/libedataserver/e-soup-auth-bearer.h
+++ b/src/libedataserver/e-soup-auth-bearer.h
@@ -74,6 +74,10 @@ void		e_soup_auth_bearer_set_access_token
 						 gint expires_in_seconds);
 gboolean	e_soup_auth_bearer_is_expired	(ESoupAuthBearer *bearer);
 
+gboolean
+e_soup_auth_bearer_set_custom_bearer_name (ESoupAuthBearer *bearer,
+const gchar *bearer_name);
+
 G_END_DECLS
 
 #endif /* E_SOUP_AUTH_BEARER_H */
diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c
index 99bc681..68237b6 100644
--- a/src/libedataserver/e-soup-session.c
+++ b/src/libedataserver/e-soup-session.c
@@ -238,16 +238,31 @@ e_soup_session_maybe_prepare_bearer_auth (ESoupSession *session,
 					  GError **error)
 {
 	gboolean success;
+	gchar *auth_method = NULL;
+	ESource *source;
 
 	g_return_val_if_fail (E_IS_SOUP_SESSION (session), FALSE);
 	g_return_val_if_fail (g_uri != NULL, FALSE);
 
 	g_mutex_lock (&session->priv->property_lock);
+	source = e_soup_session_get_source (session);
+	if (source && e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
+		ESourceAuthentication *extension;
+
+		extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+		auth_method = e_source_authentication_dup_method (extension);
+	}
 	if (session->priv->using_bearer_auth) {
 		ESoupAuthBearer *using_bearer_auth = g_object_ref (session->priv->using_bearer_auth);
 
 		g_mutex_unlock (&session->priv->property_lock);
 
+		if (auth_method){
+			if (!g_strcmp0(auth_method, "Yandex")){
+				e_soup_auth_bearer_set_custom_bearer_name (using_bearer_auth, "OAuth");
+			}
+		}
+
 		success = e_soup_session_setup_bearer_auth (session, message, FALSE, using_bearer_auth, cancellable, error);
 
 		g_clear_object (&using_bearer_auth);
@@ -258,6 +273,12 @@ e_soup_session_maybe_prepare_bearer_auth (ESoupSession *session,
 			E_TYPE_SOUP_AUTH_BEARER,
 			"authority", g_uri_get_host (g_uri), NULL);
 
+		if (auth_method){
+			if (!g_strcmp0(auth_method, "Yandex")){
+				e_soup_auth_bearer_set_custom_bearer_name (E_SOUP_AUTH_BEARER(soup_auth), "OAuth");
+			}
+		}
+
 		success = e_soup_session_setup_bearer_auth (session, message, FALSE, E_SOUP_AUTH_BEARER (soup_auth), cancellable, error);
 		if (success) {
 			g_clear_object (&session->priv->using_bearer_auth);
diff --git a/src/libedataserver/libedataserver.h b/src/libedataserver/libedataserver.h
index 9acf33f..508f27d 100644
--- a/src/libedataserver/libedataserver.h
+++ b/src/libedataserver/libedataserver.h
@@ -45,6 +45,7 @@
 #include <libedataserver/e-oauth2-service.h>
 #include <libedataserver/e-oauth2-service-base.h>
 #include <libedataserver/e-oauth2-service-google.h>
+#include <libedataserver/e-oauth2-service-yandex.h>
 #include <libedataserver/e-oauth2-service-outlook.h>
 #include <libedataserver/e-oauth2-service-yahoo.h>
 #include <libedataserver/e-oauth2-services.h>
diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt
index 0046e7a..ff80114 100644
--- a/src/modules/CMakeLists.txt
+++ b/src/modules/CMakeLists.txt
@@ -67,6 +67,7 @@ add_subdirectory(google-backend)
 add_subdirectory(outlook-backend)
 add_subdirectory(webdav-backend)
 add_subdirectory(yahoo-backend)
+add_subdirectory(yandex-backend)
 add_subdirectory(oauth2-services)
 
 if(HAVE_GTK)
diff --git a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c
index e8af938..245d53b 100644
--- a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c
+++ b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c
@@ -124,6 +124,9 @@ gnome_online_accounts_get_backend_name (const gchar *goa_provider_type)
 	if (g_str_equal (goa_provider_type, "google"))
 		eds_backend_name = "google";
 
+	if (g_str_equal (goa_provider_type, "yandex"))
+		eds_backend_name = "yandex";
+
 	if (g_str_equal (goa_provider_type, "imap_smtp"))
 		eds_backend_name = "none";
 
diff --git a/src/modules/yandex-backend/CMakeLists.txt b/src/modules/yandex-backend/CMakeLists.txt
new file mode 100644
index 0000000..960c882
--- /dev/null
+++ b/src/modules/yandex-backend/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(extra_deps)
+set(sources
+		module-yandex-backend.c
+	)
+set(extra_defines)
+set(extra_cflags)
+set(extra_incdirs)
+set(extra_ldflags)
+
+add_source_registry_module(module-yandex-backend
+	sources
+	extra_deps
+	extra_defines
+	extra_cflags
+	extra_incdirs
+	extra_ldflags
+)
diff --git a/src/modules/yandex-backend/module-yandex-backend.c b/src/modules/yandex-backend/module-yandex-backend.c
new file mode 100644
index 0000000..a99d35c
--- /dev/null
+++ b/src/modules/yandex-backend/module-yandex-backend.c
@@ -0,0 +1,619 @@
+/*
+ * module-yandex-backend.c
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/libebackend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_YANDEX_BACKEND \
+	(e_yandex_backend_get_type ())
+#define E_YANDEX_BACKEND(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_YANDEX_BACKEND, EYandexBackend))
+
+/* Just for readability... */
+#define METHOD(x) (CAMEL_NETWORK_SECURITY_METHOD_##x)
+
+/* IMAP Configuration Details */
+#define YANDEX_IMAP_BACKEND_NAME		"imapx"
+#define YANDEX_IMAP_HOST			"imap.yandex.ru"
+#define YANDEX_IMAP_PORT			993
+#define YANDEX_IMAP_SECURITY_METHOD	METHOD (SSL_ON_ALTERNATE_PORT)
+
+/* SMTP Configuration Details */
+#define YANDEX_SMTP_BACKEND_NAME		"smtp"
+#define YANDEX_SMTP_HOST			"smtp.yandex.ru"
+#define YANDEX_SMTP_PORT			465
+#define YANDEX_SMTP_SECURITY_METHOD	METHOD (SSL_ON_ALTERNATE_PORT)
+
+/* WebDAV Configuration Details */
+#define YANDEX_CALDAV_URL		"https://caldav.yandex.ru/"
+#define YANDEX_CARDDAV_URL		"https://carddav.yandex.ru/"
+
+#define YANDEX_CONTACTS_RESOURCE_ID	"Contacts"
+#define YANDEX_CONTACTS_BACKEND_NAME	"yandex"
+#define YANDEX_CONTACTS_HOST		"carddav.yandex.ru"
+
+#define YANDEX_OAUTH2_METHOD_CUSTOM  "Yandex"
+
+typedef struct _EYandexBackend EYandexBackend;
+typedef struct _EYandexBackendClass EYandexBackendClass;
+
+typedef struct _EYandexBackendFactory EYandexBackendFactory;
+typedef struct _EYandexBackendFactoryClass EYandexBackendFactoryClass;
+
+struct _EYandexBackend {
+	EWebDAVCollectionBackend parent;
+};
+
+struct _EYandexBackendClass {
+	EWebDAVCollectionBackendClass parent_class;
+};
+
+struct _EYandexBackendFactory {
+	ECollectionBackendFactory parent;
+};
+
+struct _EYandexBackendFactoryClass {
+	ECollectionBackendFactoryClass parent_class;
+};
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+/* Forward Declarations */
+GType e_yandex_backend_get_type (void);
+GType e_yandex_backend_factory_get_type (void);
+
+G_DEFINE_DYNAMIC_TYPE (
+	EYandexBackend,
+	e_yandex_backend,
+	E_TYPE_WEBDAV_COLLECTION_BACKEND)
+
+G_DEFINE_DYNAMIC_TYPE (
+	EYandexBackendFactory,
+	e_yandex_backend_factory,
+	E_TYPE_COLLECTION_BACKEND_FACTORY)
+
+static void
+yandex_backend_calendar_update_auth_method (ECollectionBackend *collection_backend,
+					    ESource *child_source,
+					    ESource *master_source);
+
+static ESourceAuthenticationResult
+yandex_backend_authenticate_sync (EBackend *backend,
+				 const ENamedParameters *credentials,
+				 gchar **out_certificate_pem,
+				 GTlsCertificateFlags *out_certificate_errors,
+				 GCancellable *cancellable,
+				 GError **error)
+{
+	ECollectionBackend *collection = E_COLLECTION_BACKEND (backend);
+	ESourceCollection *collection_extension;
+	ESource *source;
+	ESourceAuthenticationResult result = E_SOURCE_AUTHENTICATION_ERROR;
+	ESourceGoa *goa_extension = NULL;
+	const gchar *calendar_url;
+	const gchar *carddav_url;
+
+	g_return_val_if_fail (collection != NULL, E_SOURCE_AUTHENTICATION_ERROR);
+
+	source = e_backend_get_source (backend);
+	collection_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_COLLECTION);
+	if (e_source_has_extension (source, E_SOURCE_EXTENSION_GOA))
+		goa_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_GOA);
+	
+	g_return_val_if_fail (e_source_collection_get_calendar_enabled (collection_extension) ||
+		e_source_collection_get_contacts_enabled (collection_extension), E_SOURCE_AUTHENTICATION_ERROR);
+	
+	e_collection_backend_freeze_populate (collection);
+
+	(void) e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+	yandex_backend_calendar_update_auth_method (collection, source, NULL);
+
+	if (goa_extension) {
+		calendar_url = e_source_goa_get_calendar_url (goa_extension);
+		carddav_url = e_source_goa_get_contacts_url (goa_extension);
+	} else {
+		calendar_url = "https://caldav.yandex.ru/";
+		carddav_url = "https://carddav.yandex.ru";
+	}
+
+	if (e_source_collection_get_calendar_enabled (collection_extension) && (calendar_url || carddav_url)) {
+		result = e_webdav_collection_backend_discover_sync (E_WEBDAV_COLLECTION_BACKEND (backend),
+			calendar_url, carddav_url, credentials,
+			out_certificate_pem, out_certificate_errors, cancellable, error);
+	} else {
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+	}
+
+	if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
+		ESourceRegistryServer *server;
+
+		server = e_collection_backend_ref_server (collection);
+
+		if (server) {
+			g_object_unref (server);
+		}
+	}
+
+	e_collection_backend_thaw_populate (collection);
+
+	return result;
+}
+
+static gchar *
+yandex_backend_get_resource_id (EWebDAVCollectionBackend *webdav_backend,
+				ESource *source)
+{
+	g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+	if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
+		return g_strdup (YANDEX_CONTACTS_RESOURCE_ID);
+
+	/* Chain up to parent's method. */
+	return E_WEBDAV_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->get_resource_id (webdav_backend, source);
+}
+
+static gboolean
+yandex_backend_is_custom_source (EWebDAVCollectionBackend *webdav_backend,
+				 ESource *source)
+{
+	g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+	if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK) ||
+	    e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST))
+		return TRUE;
+
+	/* Chain up to parent's method. */
+	return E_WEBDAV_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->is_custom_source (webdav_backend, source);
+}
+
+static void
+yandex_backend_populate (ECollectionBackend *backend)
+{
+	ESourceCollection *collection_extension;
+	ESourceAuthentication *authentication_extension;
+	ESource *source;
+
+	source = e_backend_get_source (E_BACKEND (backend));
+	collection_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_COLLECTION);
+	authentication_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+	(void) e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+	if (e_source_authentication_get_is_external (authentication_extension))
+		e_source_authentication_set_method (authentication_extension, YANDEX_OAUTH2_METHOD_CUSTOM);
+
+	/* Chain up to parent's method. */
+	E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->populate (backend);
+
+}
+
+static gboolean
+host_ends_with (const gchar *host,
+		const gchar *ends_with)
+{
+	gint host_len, ends_with_len;
+
+	if (!host || !ends_with)
+		return FALSE;
+
+	host_len = strlen (host);
+	ends_with_len = strlen (ends_with);
+
+	if (host_len <= ends_with_len)
+		return FALSE;
+
+	return g_ascii_strcasecmp (host + host_len - ends_with_len, ends_with) == 0;
+}
+
+static gboolean
+yandex_backend_is_yandex_host (ESourceAuthentication *auth_extension,
+			       gboolean *out_requires_oauth2)
+{
+	gboolean is_yandex;
+	gchar *host;
+
+	g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (auth_extension), FALSE);
+
+	host = e_source_authentication_dup_host (auth_extension);
+
+	is_yandex = (host && (
+		host_ends_with (host, "yandex.ru") ||
+		host_ends_with (host, "yandex.com") ||
+		host_ends_with (host, "ya.ru")));
+
+	g_free (host);
+
+	if (out_requires_oauth2)
+		*out_requires_oauth2 = TRUE;
+
+	return is_yandex;
+}
+
+static void
+yandex_backend_mail_update_auth_method (ECollectionBackend *collection_backend,
+					ESource *child_source,
+					ESource *master_source)
+{
+	ESourceAuthentication *auth_extension;
+	EOAuth2Support *oauth2_support;
+	const gchar *method;
+
+	auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+	if (!yandex_backend_is_yandex_host (auth_extension, NULL))
+		return;
+
+	oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source));
+	if (!oauth2_support && master_source)
+		oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (master_source));
+
+	if (oauth2_support) {
+		method = "XOAUTH2";
+	} else {
+		method = NULL;
+	}
+
+	if (method && e_collection_backend_is_new_source (collection_backend, child_source))
+		e_source_authentication_set_method (auth_extension, method);
+
+	g_clear_object (&oauth2_support);
+}
+
+static void
+yandex_backend_mail_update_auth_method_cb (ESource *child_source,
+					   GParamSpec *param,
+					   EBackend *backend)
+{
+	yandex_backend_mail_update_auth_method (E_COLLECTION_BACKEND (backend), child_source, e_backend_get_source (backend));
+}
+
+static void
+yandex_backend_calendar_update_auth_method (ECollectionBackend *collection_backend,
+					    ESource *child_source,
+					    ESource *master_source)
+{
+	EOAuth2Support *oauth2_support;
+	ESourceAuthentication *auth_extension;
+	const gchar *method;
+
+	auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+	if (!yandex_backend_is_yandex_host (auth_extension, NULL))
+		return;
+
+	oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source));
+	if (!oauth2_support && master_source)
+		oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (master_source));
+
+	if (oauth2_support) {
+		method = YANDEX_OAUTH2_METHOD_CUSTOM;
+	} else {
+		method = NULL;
+	}
+
+	if (e_collection_backend_is_new_source (collection_backend, child_source))
+		e_source_authentication_set_method (auth_extension, method);
+
+	g_clear_object (&oauth2_support);
+}
+
+static void
+yandex_backend_calendar_update_auth_method_cb (ESource *child_source,
+					       GParamSpec *param,
+					       EBackend *backend)
+{
+	yandex_backend_calendar_update_auth_method (E_COLLECTION_BACKEND (backend), child_source, e_backend_get_source (backend));
+}
+
+static gchar *
+yandex_backend_dup_resource_id (ECollectionBackend *backend,
+                                ESource *child_source)
+{
+	if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_CALENDAR) ||
+	    e_source_has_extension (child_source, E_SOURCE_EXTENSION_MEMO_LIST) ||
+	    e_source_has_extension (child_source, E_SOURCE_EXTENSION_TASK_LIST))
+		return E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->dup_resource_id (backend, child_source);
+
+	if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
+		return g_strdup (YANDEX_CONTACTS_RESOURCE_ID);
+
+	return NULL;
+}
+
+static void
+yandex_backend_child_added (ECollectionBackend *backend,
+                           ESource *child_source)
+{
+	ESource *collection_source;
+	const gchar *extension_name;
+	gboolean is_mail = FALSE;
+	gboolean has_external_auth = FALSE;
+
+	/* Chain up to parent's child_added() method. */
+	E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->
+		child_added (backend, child_source);
+
+	collection_source = e_backend_get_source (E_BACKEND (backend));
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	is_mail |= e_source_has_extension (child_source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	is_mail |= e_source_has_extension (child_source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+	is_mail |= e_source_has_extension (child_source, extension_name);
+
+	/* Synchronize mail-related user with the collection identity. */
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	if (is_mail && e_source_has_extension (child_source, extension_name)) {
+		ESourceAuthentication *auth_child_extension;
+		ESourceCollection *collection_extension;
+		const gchar *collection_identity;
+		const gchar *auth_child_user;
+
+		extension_name = E_SOURCE_EXTENSION_COLLECTION;
+		collection_extension = e_source_get_extension (
+			collection_source, extension_name);
+		collection_identity = e_source_collection_get_identity (
+			collection_extension);
+
+		extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+		auth_child_extension = e_source_get_extension (
+			child_source, extension_name);
+		auth_child_user = e_source_authentication_get_user (
+			auth_child_extension);
+		has_external_auth = e_source_authentication_get_is_external (
+			auth_child_extension);
+
+		if (auth_child_user == NULL)
+			e_source_authentication_set_user (
+				auth_child_extension,
+				collection_identity);
+
+		if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT) ||
+		    e_source_has_extension (child_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT)) {
+			yandex_backend_mail_update_auth_method (backend, child_source, collection_source);
+			g_signal_connect (
+				child_source, "notify::oauth2-support",
+				G_CALLBACK (yandex_backend_mail_update_auth_method_cb),
+				backend);
+		}
+	}
+
+	extension_name = E_SOURCE_EXTENSION_CALENDAR;
+	if (e_source_has_extension (child_source, extension_name)) {
+		ESourceAlarms *alarms_extension;
+
+		/* To not notify about past reminders. */
+		alarms_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_ALARMS);
+		if (!e_source_alarms_get_last_notified (alarms_extension)) {
+			GTimeVal today_tv;
+			gchar *today;
+
+			g_get_current_time (&today_tv);
+			today = g_time_val_to_iso8601 (&today_tv);
+			e_source_alarms_set_last_notified (alarms_extension, today);
+			g_free (today);
+		}
+
+		yandex_backend_calendar_update_auth_method (backend, child_source, collection_source);
+		g_signal_connect (
+			child_source, "notify::oauth2-support",
+			G_CALLBACK (yandex_backend_calendar_update_auth_method_cb),
+			backend);
+	}
+
+}
+
+static void
+yandex_backend_child_removed (ECollectionBackend *backend,
+			      ESource *child_source)
+{
+	ESource *collection_source;
+	gboolean has_external_auth = FALSE;
+
+	/* Chain up to parent's method. */
+	E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->child_removed (backend, child_source);
+
+	collection_source = e_backend_get_source (E_BACKEND (backend));
+
+	if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
+		ESourceAuthentication *auth_child_extension;
+
+		auth_child_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+		has_external_auth = e_source_authentication_get_is_external (auth_child_extension);
+	}
+
+	if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK) &&
+	    e_source_has_extension (collection_source, E_SOURCE_EXTENSION_COLLECTION) &&
+	    !has_external_auth) {
+		ESourceCollection *collection_extension;
+
+		collection_extension = e_source_get_extension (collection_source, E_SOURCE_EXTENSION_COLLECTION);
+
+		e_source_collection_set_contacts_enabled (collection_extension, FALSE);
+	}
+}
+
+static void
+e_yandex_backend_class_init (EYandexBackendClass *class)
+{
+	EBackendClass *backend_class;
+	ECollectionBackendClass *collection_backend_class;
+	EWebDAVCollectionBackendClass *webdav_collection_backend_class;
+
+	backend_class = E_BACKEND_CLASS (class);
+	backend_class->authenticate_sync = yandex_backend_authenticate_sync;
+
+	collection_backend_class = E_COLLECTION_BACKEND_CLASS (class);
+	collection_backend_class->child_added = yandex_backend_child_added;
+	collection_backend_class->populate = yandex_backend_populate;
+	collection_backend_class->dup_resource_id = yandex_backend_dup_resource_id;
+	collection_backend_class->child_removed = yandex_backend_child_removed;
+
+	webdav_collection_backend_class = E_WEBDAV_COLLECTION_BACKEND_CLASS (class);
+	webdav_collection_backend_class->get_resource_id = yandex_backend_get_resource_id;
+	webdav_collection_backend_class->is_custom_source = yandex_backend_is_custom_source;
+}
+
+static void
+e_yandex_backend_class_finalize (EYandexBackendClass *class)
+{
+}
+
+static void
+e_yandex_backend_init (EYandexBackend *backend)
+{
+}
+
+static void
+yandex_backend_prepare_mail_account_source (ESource *source)
+{
+	ESourceCamel *camel_extension;
+	ESourceExtension *extension;
+	CamelSettings *settings;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	backend_name = YANDEX_IMAP_BACKEND_NAME;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (extension), backend_name);
+
+	extension_name = e_source_camel_get_extension_name (backend_name);
+	camel_extension = e_source_get_extension (source, extension_name);
+	settings = e_source_camel_get_settings (camel_extension);
+
+	/* The "auth-mechanism" should be determined elsewhere. */
+
+	camel_network_settings_set_host (
+		CAMEL_NETWORK_SETTINGS (settings),
+		YANDEX_IMAP_HOST);
+
+	camel_network_settings_set_port (
+		CAMEL_NETWORK_SETTINGS (settings),
+		YANDEX_IMAP_PORT);
+
+	camel_network_settings_set_security_method (
+		CAMEL_NETWORK_SETTINGS (settings),
+		YANDEX_IMAP_SECURITY_METHOD);
+}
+
+static void
+yandex_backend_prepare_mail_transport_source (ESource *source)
+{
+	ESourceCamel *camel_extension;
+	ESourceExtension *extension;
+	CamelSettings *settings;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	/* Configure the mail transport source. */
+
+	backend_name = YANDEX_SMTP_BACKEND_NAME;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+	extension = e_source_get_extension (source, extension_name);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (extension), backend_name);
+
+	extension_name = e_source_camel_get_extension_name (backend_name);
+	camel_extension = e_source_get_extension (source, extension_name);
+	settings = e_source_camel_get_settings (camel_extension);
+
+	/* The "auth-mechanism" should be determined elsewhere. */
+
+	camel_network_settings_set_host (
+		CAMEL_NETWORK_SETTINGS (settings),
+		YANDEX_SMTP_HOST);
+
+	camel_network_settings_set_port (
+		CAMEL_NETWORK_SETTINGS (settings),
+		YANDEX_SMTP_PORT);
+
+	camel_network_settings_set_security_method (
+		CAMEL_NETWORK_SETTINGS (settings),
+		YANDEX_SMTP_SECURITY_METHOD);
+}
+
+static void
+yandex_backend_factory_prepare_mail (ECollectionBackendFactory *factory,
+                                    ESource *mail_account_source,
+                                    ESource *mail_identity_source,
+                                    ESource *mail_transport_source)
+{
+	ECollectionBackendFactoryClass *parent_class;
+
+	/* Chain up to parent's prepare_mail() method. */
+	parent_class =
+		E_COLLECTION_BACKEND_FACTORY_CLASS (
+		e_yandex_backend_factory_parent_class);
+	parent_class->prepare_mail (
+		factory,
+		mail_account_source,
+		mail_identity_source,
+		mail_transport_source);
+
+	yandex_backend_prepare_mail_account_source (mail_account_source);
+	yandex_backend_prepare_mail_transport_source (mail_transport_source);
+}
+
+static void
+e_yandex_backend_factory_class_init (EYandexBackendFactoryClass *class)
+{
+	ECollectionBackendFactoryClass *factory_class;
+
+	factory_class = E_COLLECTION_BACKEND_FACTORY_CLASS (class);
+	factory_class->factory_name = "yandex";
+	factory_class->backend_type = E_TYPE_YANDEX_BACKEND;
+	factory_class->prepare_mail = yandex_backend_factory_prepare_mail;
+}
+
+static void
+e_yandex_backend_factory_class_finalize (EYandexBackendFactoryClass *class)
+{
+}
+
+static void
+e_yandex_backend_factory_init (EYandexBackendFactory *factory)
+{
+}
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+	e_yandex_backend_register_type (type_module);
+	e_yandex_backend_factory_register_type (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+
-- 
2.52.0

openSUSE Build Service is sponsored by