[evolution-ews] I#121 - Allow change of the Microsoft 365 OAuth2 endpoints



commit b3f7d5817952e600d9bba29b955d4cd135b3ee46
Author: Milan Crha <mcrha redhat com>
Date:   Wed Oct 7 11:25:04 2020 +0200

    I#121 - Allow change of the Microsoft 365 OAuth2 endpoints
    
    Closes https://gitlab.gnome.org/GNOME/evolution-ews/-/issues/121

 CMakeLists.txt                                     |  12 ++
 config.h.in                                        |   6 +
 src/EWS/common/camel-ews-settings.c                | 150 +++++++++++++++++++++
 src/EWS/common/camel-ews-settings.h                |  14 ++
 src/EWS/common/e-oauth2-service-office365.c        | 100 ++++++++++++--
 src/EWS/common/e-oauth2-service-office365.h        |   2 +
 src/EWS/evolution/e-mail-config-ews-backend.c      | 148 +++++++++++++++++++-
 src/Microsoft365/common/camel-m365-settings.c      |  75 +++++++++++
 src/Microsoft365/common/camel-m365-settings.h      |   7 +
 .../common/e-oauth2-service-microsoft365.c         |  48 ++++++-
 .../evolution/e-mail-config-m365-backend.c         |  97 ++++++++++++-
 11 files changed, 636 insertions(+), 23 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a7c77c0..24e4b9e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -200,6 +200,12 @@ if(WITH_OFFICE365_REDIRECT_URI STREQUAL "")
        set(WITH_OFFICE365_REDIRECT_URI "https://login.microsoftonline.com/common/oauth2/nativeclient";)
 endif(WITH_OFFICE365_REDIRECT_URI STREQUAL "")
 
+add_printable_variable(WITH_OFFICE365_ENDPOINT_HOST "Office365.com OAuth 2.0 endpoint host" "")
+
+if(WITH_OFFICE365_ENDPOINT_HOST STREQUAL "")
+       set(WITH_OFFICE365_ENDPOINT_HOST "login.microsoftonline.com")
+endif(WITH_OFFICE365_ENDPOINT_HOST STREQUAL "")
+
 # ******************************
 # Microsoft365 OAuth2 support (v2.0)
 # ******************************
@@ -222,6 +228,12 @@ if(WITH_MICROSOFT365_REDIRECT_URI STREQUAL "")
        set(WITH_MICROSOFT365_REDIRECT_URI "https://login.microsoftonline.com/common/oauth2/nativeclient";)
 endif(WITH_MICROSOFT365_REDIRECT_URI STREQUAL "")
 
+add_printable_variable(WITH_MICROSOFT365_ENDPOINT_HOST "Microsoft 365 OAuth 2.0 endpoint host" "")
+
+if(WITH_MICROSOFT365_ENDPOINT_HOST STREQUAL "")
+       set(WITH_MICROSOFT365_ENDPOINT_HOST "login.microsoftonline.com")
+endif(WITH_MICROSOFT365_ENDPOINT_HOST STREQUAL "")
+
 # ******************************
 # Special directories
 # ******************************
diff --git a/config.h.in b/config.h.in
index ae8ae20e..e223f89a 100644
--- a/config.h.in
+++ b/config.h.in
@@ -33,6 +33,9 @@
 /* Define Office365 OAuth 2.0 default Redirect URI to use */
 #define OFFICE365_REDIRECT_URI "@WITH_OFFICE365_REDIRECT_URI@"
 
+/* Define Office365 OAuth 2.0 default Endpoint Host to use */
+#define OFFICE365_ENDPOINT_HOST "@WITH_OFFICE365_ENDPOINT_HOST@"
+
 /* Define Microsoft 365 OAuth 2.0 default Tenant to use */
 #define MICROSOFT365_TENANT "@WITH_MICROSOFT365_TENANT@"
 
@@ -41,3 +44,6 @@
 
 /* Define Microsoft 365 OAuth 2.0 default Redirect URI to use */
 #define MICROSOFT365_REDIRECT_URI "@WITH_MICROSOFT365_REDIRECT_URI@"
+
+/* Define Microsoft 365 OAuth 2.0 default Endpoint Host to use */
+#define MICROSOFT365_ENDPOINT_HOST "@WITH_MICROSOFT365_ENDPOINT_HOST@"
diff --git a/src/EWS/common/camel-ews-settings.c b/src/EWS/common/camel-ews-settings.c
index 6992a311..956bb456 100644
--- a/src/EWS/common/camel-ews-settings.c
+++ b/src/EWS/common/camel-ews-settings.c
@@ -37,6 +37,8 @@ struct _CamelEwsSettingsPrivate {
        gchar *oauth2_tenant;
        gchar *oauth2_client_id;
        gchar *oauth2_redirect_uri;
+       gchar *oauth2_resource_uri;
+       gchar *oauth2_endpoint_host;
 };
 
 enum {
@@ -65,6 +67,8 @@ enum {
        PROP_OAUTH2_TENANT,
        PROP_OAUTH2_CLIENT_ID,
        PROP_OAUTH2_REDIRECT_URI,
+       PROP_OAUTH2_RESOURCE_URI,
+       PROP_OAUTH2_ENDPOINT_HOST,
        PROP_SHOW_PUBLIC_FOLDERS,
        PROP_CONCURRENT_CONNECTIONS
 };
@@ -256,6 +260,18 @@ ews_settings_set_property (GObject *object,
                                g_value_get_string (value));
                        return;
 
+               case PROP_OAUTH2_RESOURCE_URI:
+                       camel_ews_settings_set_oauth2_resource_uri (
+                               CAMEL_EWS_SETTINGS (object),
+                               g_value_get_string (value));
+                       return;
+
+               case PROP_OAUTH2_ENDPOINT_HOST:
+                       camel_ews_settings_set_oauth2_endpoint_host (
+                               CAMEL_EWS_SETTINGS (object),
+                               g_value_get_string (value));
+                       return;
+
                case PROP_SHOW_PUBLIC_FOLDERS:
                        camel_ews_settings_set_show_public_folders (
                                CAMEL_EWS_SETTINGS (object),
@@ -447,6 +463,20 @@ ews_settings_get_property (GObject *object,
                                CAMEL_EWS_SETTINGS (object)));
                        return;
 
+               case PROP_OAUTH2_RESOURCE_URI:
+                       g_value_take_string (
+                               value,
+                               camel_ews_settings_dup_oauth2_resource_uri (
+                               CAMEL_EWS_SETTINGS (object)));
+                       return;
+
+               case PROP_OAUTH2_ENDPOINT_HOST:
+                       g_value_take_string (
+                               value,
+                               camel_ews_settings_dup_oauth2_endpoint_host (
+                               CAMEL_EWS_SETTINGS (object)));
+                       return;
+
                case PROP_SHOW_PUBLIC_FOLDERS:
                        g_value_set_boolean (
                                value,
@@ -484,6 +514,8 @@ ews_settings_finalize (GObject *object)
        g_free (priv->oauth2_tenant);
        g_free (priv->oauth2_client_id);
        g_free (priv->oauth2_redirect_uri);
+       g_free (priv->oauth2_resource_uri);
+       g_free (priv->oauth2_endpoint_host);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (camel_ews_settings_parent_class)->finalize (object);
@@ -759,6 +791,30 @@ camel_ews_settings_class_init (CamelEwsSettingsClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_OAUTH2_RESOURCE_URI,
+               g_param_spec_string (
+                       "oauth2-resource-uri",
+                       "OAuth2 Resource URI",
+                       "OAuth2 Resource URI to use, only if override-oauth2 is TRUE, otherwise the 
compile-time value is used",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_OAUTH2_ENDPOINT_HOST,
+               g_param_spec_string (
+                       "oauth2-endpoint-host",
+                       "OAuth2 Endpoint Host",
+                       "OAuth2 endpoint host to use, only if override-oauth2 is TRUE, otherwise the 
compile-time value is used",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
+
        g_object_class_install_property (
                object_class,
                PROP_SHOW_PUBLIC_FOLDERS,
@@ -1589,6 +1645,100 @@ camel_ews_settings_set_oauth2_redirect_uri (CamelEwsSettings *settings,
        g_object_notify (G_OBJECT (settings), "oauth2-redirect-uri");
 }
 
+const gchar *
+camel_ews_settings_get_oauth2_resource_uri (CamelEwsSettings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+       return settings->priv->oauth2_resource_uri;
+}
+
+gchar *
+camel_ews_settings_dup_oauth2_resource_uri (CamelEwsSettings *settings)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       protected = camel_ews_settings_get_oauth2_resource_uri (settings);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+camel_ews_settings_set_oauth2_resource_uri (CamelEwsSettings *settings,
+                                           const gchar *resource_uri)
+{
+       g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       if (g_strcmp0 (settings->priv->oauth2_resource_uri, resource_uri) == 0) {
+               g_mutex_unlock (&settings->priv->property_lock);
+               return;
+       }
+
+       g_free (settings->priv->oauth2_resource_uri);
+       settings->priv->oauth2_resource_uri = e_util_strdup_strip (resource_uri);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       g_object_notify (G_OBJECT (settings), "oauth2-resource-uri");
+}
+
+const gchar *
+camel_ews_settings_get_oauth2_endpoint_host (CamelEwsSettings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+       return settings->priv->oauth2_endpoint_host;
+}
+
+gchar *
+camel_ews_settings_dup_oauth2_endpoint_host (CamelEwsSettings *settings)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       protected = camel_ews_settings_get_oauth2_endpoint_host (settings);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+camel_ews_settings_set_oauth2_endpoint_host (CamelEwsSettings *settings,
+                                            const gchar *endpoint_host)
+{
+       g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       if (g_strcmp0 (settings->priv->oauth2_endpoint_host, endpoint_host) == 0) {
+               g_mutex_unlock (&settings->priv->property_lock);
+               return;
+       }
+
+       g_free (settings->priv->oauth2_endpoint_host);
+       settings->priv->oauth2_endpoint_host = e_util_strdup_strip (endpoint_host);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       g_object_notify (G_OBJECT (settings), "oauth2-endpoint-host");
+}
+
 gboolean
 camel_ews_settings_get_show_public_folders (CamelEwsSettings *settings)
 {
diff --git a/src/EWS/common/camel-ews-settings.h b/src/EWS/common/camel-ews-settings.h
index 02fbc40f..e0423264 100644
--- a/src/EWS/common/camel-ews-settings.h
+++ b/src/EWS/common/camel-ews-settings.h
@@ -158,6 +158,20 @@ gchar *            camel_ews_settings_dup_oauth2_redirect_uri
 void           camel_ews_settings_set_oauth2_redirect_uri
                                                (CamelEwsSettings *settings,
                                                 const gchar *redirect_uri);
+const gchar *  camel_ews_settings_get_oauth2_resource_uri
+                                               (CamelEwsSettings *settings);
+gchar *                camel_ews_settings_dup_oauth2_resource_uri
+                                               (CamelEwsSettings *settings);
+void           camel_ews_settings_set_oauth2_resource_uri
+                                               (CamelEwsSettings *settings,
+                                                const gchar *resource_uri);
+const gchar *  camel_ews_settings_get_oauth2_endpoint_host
+                                               (CamelEwsSettings *settings);
+gchar *                camel_ews_settings_dup_oauth2_endpoint_host
+                                               (CamelEwsSettings *settings);
+void           camel_ews_settings_set_oauth2_endpoint_host
+                                               (CamelEwsSettings *settings,
+                                                const gchar *endpoint_host);
 gboolean       camel_ews_settings_get_show_public_folders
                                                (CamelEwsSettings *settings);
 void           camel_ews_settings_set_show_public_folders
diff --git a/src/EWS/common/e-oauth2-service-office365.c b/src/EWS/common/e-oauth2-service-office365.c
index 0727b647..ab25d158 100644
--- a/src/EWS/common/e-oauth2-service-office365.c
+++ b/src/EWS/common/e-oauth2-service-office365.c
@@ -18,8 +18,6 @@
    https://tsmatz.wordpress.com/2016/10/07/application-permission-with-v2-endpoint-and-microsoft-graph/
 */
 
-#define OFFICE365_RESOURCE "https://outlook.office.com";
-
 struct _EOAuth2ServiceOffice365Private
 {
        GMutex string_cache_lock;
@@ -43,8 +41,10 @@ eos_office365_cache_string (EOAuth2ServiceOffice365 *oauth2_office365,
        if (!str)
                return NULL;
 
-       if (!*str)
+       if (!*str) {
+               g_free (str);
                return "";
+       }
 
        g_mutex_lock (&oauth2_office365->priv->string_cache_lock);
 
@@ -61,6 +61,24 @@ eos_office365_cache_string (EOAuth2ServiceOffice365 *oauth2_office365,
        return cached_str;
 }
 
+static const gchar *
+eos_office365_get_endpoint_host (EOAuth2ServiceOffice365 *oauth2_office365,
+                                CamelEwsSettings *ews_settings)
+{
+       if (ews_settings && camel_ews_settings_get_override_oauth2 (ews_settings)) {
+               gchar *endpoint_host;
+
+               endpoint_host = camel_ews_settings_dup_oauth2_endpoint_host (ews_settings);
+
+               if (endpoint_host && *endpoint_host)
+                       return eos_office365_cache_string (oauth2_office365, endpoint_host);
+
+               g_free (endpoint_host);
+       }
+
+       return OFFICE365_ENDPOINT_HOST;
+}
+
 static CamelEwsSettings *
 eos_office365_get_camel_settings (ESource *source)
 {
@@ -147,7 +165,8 @@ eos_office365_get_authentication_uri (EOAuth2Service *service,
                }
 
                res = eos_office365_cache_string (oauth2_office365,
-                       g_strdup_printf ("https://login.microsoftonline.com/%s/oauth2/authorize";,
+                       g_strdup_printf ("https://%s/%s/oauth2/authorize";,
+                               eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
                                tenant ? tenant : OFFICE365_TENANT));
 
                g_free (tenant);
@@ -155,7 +174,10 @@ eos_office365_get_authentication_uri (EOAuth2Service *service,
                return res;
        }
 
-       return "https://login.microsoftonline.com/"; OFFICE365_TENANT "/oauth2/authorize";
+       return eos_office365_cache_string (oauth2_office365,
+               g_strdup_printf ("https://%s/%s/oauth2/authorize";,
+                       eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
+                       OFFICE365_TENANT));
 }
 
 static const gchar *
@@ -177,7 +199,8 @@ eos_office365_get_refresh_uri (EOAuth2Service *service,
                }
 
                res = eos_office365_cache_string (oauth2_office365,
-                       g_strdup_printf ("https://login.microsoftonline.com/%s/oauth2/token";,
+                       g_strdup_printf ("https://%s/%s/oauth2/token";,
+                               eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
                                tenant ? tenant : OFFICE365_TENANT));
 
                g_free (tenant);
@@ -185,7 +208,10 @@ eos_office365_get_refresh_uri (EOAuth2Service *service,
                return res;
        }
 
-       return "https://login.microsoftonline.com/"; OFFICE365_TENANT "/oauth2/token";
+       return eos_office365_cache_string (oauth2_office365,
+               g_strdup_printf ("https://%s/%s/oauth2/token";,
+                       eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
+                       OFFICE365_TENANT));
 }
 
 static const gchar *
@@ -209,13 +235,67 @@ eos_office365_get_redirect_uri (EOAuth2Service *service,
 
                if (redirect_uri)
                        return eos_office365_cache_string (oauth2_office365, redirect_uri);
+
+               if (e_util_strcmp0 (camel_ews_settings_get_oauth2_endpoint_host (ews_settings), NULL) != 0) {
+                       return eos_office365_cache_string (oauth2_office365,
+                               g_strdup_printf ("https://%s/common/oauth2/nativeclient";,
+                                       eos_office365_get_endpoint_host (oauth2_office365, ews_settings)));
+               }
        }
 
        res = OFFICE365_REDIRECT_URI;
        if (res && *res)
                return res;
 
-       return "https://login.microsoftonline.com/common/oauth2/nativeclient";;
+       return eos_office365_cache_string (oauth2_office365,
+               g_strdup_printf ("https://%s/common/oauth2/nativeclient";,
+                       eos_office365_get_endpoint_host (oauth2_office365, ews_settings)));
+}
+
+static const gchar *
+eos_office365_get_resource_uri (EOAuth2Service *service,
+                               ESource *source)
+{
+       EOAuth2ServiceOffice365 *oauth2_office365 = E_OAUTH2_SERVICE_OFFICE365 (service);
+       CamelEwsSettings *ews_settings;
+
+       ews_settings = eos_office365_get_camel_settings (source);
+       if (ews_settings && camel_ews_settings_get_override_oauth2 (ews_settings)) {
+               gchar *resource_uri;
+
+               resource_uri = camel_ews_settings_dup_oauth2_resource_uri (ews_settings);
+
+               if (resource_uri && !*resource_uri) {
+                       g_free (resource_uri);
+                       resource_uri = NULL;
+               }
+
+               if (resource_uri)
+                       return eos_office365_cache_string (oauth2_office365, resource_uri);
+       }
+
+       if (ews_settings) {
+               gchar *host_url;
+
+               host_url = camel_ews_settings_dup_hosturl (ews_settings);
+
+               if (host_url && *host_url) {
+                       gchar *ptr;
+
+                       ptr = strstr (host_url, "://");
+                       ptr = ptr ? strchr (ptr + 3, '/') : NULL;
+
+                       if (ptr) {
+                               *ptr = '\0';
+
+                               return eos_office365_cache_string (oauth2_office365, host_url);
+                       }
+               }
+
+               g_free (host_url);
+       }
+
+       return OFFICE365_FALLBACK_RESOURCE_URI;
 }
 
 static void
@@ -227,7 +307,7 @@ eos_office365_prepare_authentication_uri_query (EOAuth2Service *service,
 
        e_oauth2_service_util_set_to_form (uri_query, "response_mode", "query");
        e_oauth2_service_util_set_to_form (uri_query, "prompt", "login");
-       e_oauth2_service_util_set_to_form (uri_query, "resource", OFFICE365_RESOURCE);
+       e_oauth2_service_util_set_to_form (uri_query, "resource", eos_office365_get_resource_uri (service, 
source));
 }
 
 static gboolean
@@ -294,7 +374,7 @@ eos_office365_prepare_refresh_token_form (EOAuth2Service *service,
 {
        g_return_if_fail (form != NULL);
 
-       e_oauth2_service_util_set_to_form (form, "resource", OFFICE365_RESOURCE);
+       e_oauth2_service_util_set_to_form (form, "resource", eos_office365_get_resource_uri (service, 
source));
        e_oauth2_service_util_set_to_form (form, "redirect_uri", e_oauth2_service_get_redirect_uri (service, 
source));
 }
 
diff --git a/src/EWS/common/e-oauth2-service-office365.h b/src/EWS/common/e-oauth2-service-office365.h
index c05c5af9..289dc324 100644
--- a/src/EWS/common/e-oauth2-service-office365.h
+++ b/src/EWS/common/e-oauth2-service-office365.h
@@ -29,6 +29,8 @@
        (G_TYPE_INSTANCE_GET_CLASS \
        ((obj), E_TYPE_OAUTH2_SERVICE_OFFICE365, EOAuth2ServiceOffice365Class))
 
+#define OFFICE365_FALLBACK_RESOURCE_URI "https://outlook.office365.com";
+
 G_BEGIN_DECLS
 
 typedef struct _EOAuth2ServiceOffice365 EOAuth2ServiceOffice365;
diff --git a/src/EWS/evolution/e-mail-config-ews-backend.c b/src/EWS/evolution/e-mail-config-ews-backend.c
index abdabf27..5e4af390 100644
--- a/src/EWS/evolution/e-mail-config-ews-backend.c
+++ b/src/EWS/evolution/e-mail-config-ews-backend.c
@@ -17,6 +17,7 @@
 #include <mail/e-mail-config-receiving-page.h>
 
 #include "common/camel-ews-settings.h"
+#include "common/e-oauth2-service-office365.h"
 
 #include "e-mail-config-ews-autodiscover.h"
 #include "e-ews-config-utils.h"
@@ -38,6 +39,8 @@ struct _EMailConfigEwsBackendPrivate {
        GtkWidget *oauth2_tenant_entry;
        GtkWidget *oauth2_client_id_entry;
        GtkWidget *oauth2_redirect_uri_entry;
+       GtkWidget *oauth2_resource_uri_entry;
+       GtkWidget *oauth2_endpoint_host_entry;
 };
 
 G_DEFINE_DYNAMIC_TYPE (
@@ -144,6 +147,11 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
        GtkLabel *label;
        GtkWidget *widget;
        GtkWidget *container;
+       GtkWidget *expander;
+       GtkWidget *advanced_help;
+       GtkWidget *endpoint_host_label;
+       GtkWidget *redirect_uri_label;
+       GtkWidget *resource_uri_label;
        const gchar *extension_name;
        const gchar *text;
        gchar *markup;
@@ -369,11 +377,62 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
                _("There is not set any default application ID"),
                g_strdup_printf (_("Default application ID is “%s”"), OFFICE365_CLIENT_ID));
 
-       widget = gtk_label_new_with_mnemonic (_("_Redirect URI:"));
+       container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+       gtk_grid_attach (priv->oauth2_settings_grid, container, 0, 3, 2, 1);
+
+       widget = gtk_expander_new_with_mnemonic (_("_Advanced Settings"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       expander = widget;
+
+       e_binding_bind_property (
+               priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       markup = g_markup_printf_escaped ("(<a 
href=\"https://wiki.gnome.org/Apps/Evolution/EWS/OAuth2#Alternative_endpoints\";>%s</a>)", _("Help…"));
+       widget = gtk_label_new (markup);
+       gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       g_free (markup);
+       advanced_help = widget;
+
+       widget = gtk_label_new_with_mnemonic (_("_Endpoint host:"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+       gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 4, 1, 1);
+       label = GTK_LABEL (widget);
+       endpoint_host_label = widget;
+
+       e_binding_bind_property (
+               priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       widget = gtk_entry_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 4, 1, 1);
+       priv->oauth2_endpoint_host_entry = widget;
+
+       e_binding_bind_property (
+               priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       markup = g_strdup_printf (_("Default endpoint host is “%s”"), "login.microsoftonline.com");
+       mail_config_ews_backend_set_oauth2_tooltip (widget, OFFICE365_ENDPOINT_HOST,
+               markup,
+               g_strdup_printf (_("Default endpoint host is “%s”"), OFFICE365_ENDPOINT_HOST));
+       g_free (markup);
+
+       widget = gtk_label_new_with_mnemonic (_("Red_irect URI:"));
        gtk_widget_set_margin_left (widget, 12);
        gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
-       gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 3, 1, 1);
+       gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 5, 1, 1);
        label = GTK_LABEL (widget);
+       redirect_uri_label = widget;
 
        e_binding_bind_property (
                priv->oauth2_override_check, "active",
@@ -383,7 +442,7 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
        widget = gtk_entry_new ();
        gtk_widget_set_hexpand (widget, TRUE);
        gtk_label_set_mnemonic_widget (label, widget);
-       gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 3, 1, 1);
+       gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 5, 1, 1);
        priv->oauth2_redirect_uri_entry = widget;
 
        e_binding_bind_property (
@@ -397,8 +456,77 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
                g_strdup_printf (_("Default redirect URI is “%s”"), OFFICE365_REDIRECT_URI));
        g_free (markup);
 
+       widget = gtk_label_new_with_mnemonic (_("Re_source URI:"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+       gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 6, 1, 1);
+       label = GTK_LABEL (widget);
+       resource_uri_label = widget;
+
+       e_binding_bind_property (
+               priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       widget = gtk_entry_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 6, 1, 1);
+       priv->oauth2_resource_uri_entry = widget;
+
+       e_binding_bind_property (
+               priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       markup = g_strdup_printf (_("Default resource URI is derived from the Host URL, or it can eventually 
fall back to “%s”."), OFFICE365_FALLBACK_RESOURCE_URI);
+       mail_config_ews_backend_set_oauth2_tooltip (widget, NULL,
+               markup,
+               NULL);
+       g_free (markup);
+
        gtk_widget_show_all (GTK_WIDGET (priv->oauth2_settings_grid));
 
+       gtk_expander_set_expanded (GTK_EXPANDER (expander),
+               e_util_strcmp0 (camel_ews_settings_get_oauth2_endpoint_host (CAMEL_EWS_SETTINGS (settings)), 
NULL) != 0 ||
+               e_util_strcmp0 (camel_ews_settings_get_oauth2_redirect_uri (CAMEL_EWS_SETTINGS (settings)), 
NULL) != 0 ||
+               e_util_strcmp0 (camel_ews_settings_get_oauth2_resource_uri (CAMEL_EWS_SETTINGS (settings)), 
NULL) != 0);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               advanced_help, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               endpoint_host_label, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               priv->oauth2_endpoint_host_entry, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               redirect_uri_label, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               priv->oauth2_redirect_uri_entry, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               resource_uri_label, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               priv->oauth2_resource_uri_entry, "visible",
+               G_BINDING_SYNC_CREATE);
+
        e_binding_bind_property_full (
                priv->auth_check, "active-mechanism",
                priv->oauth2_settings_grid, "visible",
@@ -451,11 +579,23 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
                G_BINDING_SYNC_CREATE);
 
        e_binding_bind_object_text_property (
-               settings, "oauth2-redirect_uri",
+               settings, "oauth2-redirect-uri",
                priv->oauth2_redirect_uri_entry, "text",
                G_BINDING_BIDIRECTIONAL |
                G_BINDING_SYNC_CREATE);
 
+       e_binding_bind_object_text_property (
+               settings, "oauth2-resource-uri",
+               priv->oauth2_resource_uri_entry, "text",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_object_text_property (
+               settings, "oauth2-endpoint-host",
+               priv->oauth2_endpoint_host_entry, "text",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE);
+
        extension_name = E_SOURCE_EXTENSION_COLLECTION;
        source = e_mail_config_service_backend_get_collection (backend);
        extension = e_source_get_extension (source, extension_name);
diff --git a/src/Microsoft365/common/camel-m365-settings.c b/src/Microsoft365/common/camel-m365-settings.c
index daeac748..9e5d45cd 100644
--- a/src/Microsoft365/common/camel-m365-settings.c
+++ b/src/Microsoft365/common/camel-m365-settings.c
@@ -25,6 +25,7 @@ struct _CamelM365SettingsPrivate {
        gchar *oauth2_tenant;
        gchar *oauth2_client_id;
        gchar *oauth2_redirect_uri;
+       gchar *oauth2_endpoint_host;
 };
 
 enum {
@@ -45,6 +46,7 @@ enum {
        PROP_OAUTH2_TENANT,
        PROP_OAUTH2_CLIENT_ID,
        PROP_OAUTH2_REDIRECT_URI,
+       PROP_OAUTH2_ENDPOINT_HOST,
        PROP_CONCURRENT_CONNECTIONS
 };
 
@@ -155,6 +157,12 @@ m365_settings_set_property (GObject *object,
                                g_value_get_string (value));
                        return;
 
+               case PROP_OAUTH2_ENDPOINT_HOST:
+                       camel_m365_settings_set_oauth2_endpoint_host (
+                               CAMEL_M365_SETTINGS (object),
+                               g_value_get_string (value));
+                       return;
+
                case PROP_CONCURRENT_CONNECTIONS:
                        camel_m365_settings_set_concurrent_connections (
                                CAMEL_M365_SETTINGS (object),
@@ -284,6 +292,13 @@ m365_settings_get_property (GObject *object,
                                CAMEL_M365_SETTINGS (object)));
                        return;
 
+               case PROP_OAUTH2_ENDPOINT_HOST:
+                       g_value_take_string (
+                               value,
+                               camel_m365_settings_dup_oauth2_endpoint_host (
+                               CAMEL_M365_SETTINGS (object)));
+                       return;
+
                case PROP_CONCURRENT_CONNECTIONS:
                        g_value_set_uint (
                                value,
@@ -306,6 +321,7 @@ m365_settings_finalize (GObject *object)
        g_free (m365_settings->priv->oauth2_tenant);
        g_free (m365_settings->priv->oauth2_client_id);
        g_free (m365_settings->priv->oauth2_redirect_uri);
+       g_free (m365_settings->priv->oauth2_endpoint_host);
 
        /* Chain up to parent's method. */
        G_OBJECT_CLASS (camel_m365_settings_parent_class)->finalize (object);
@@ -483,6 +499,18 @@ camel_m365_settings_class_init (CamelM365SettingsClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_OAUTH2_ENDPOINT_HOST,
+               g_param_spec_string (
+                       "oauth2-endpoint-host",
+                       "OAuth2 Endpoint Host",
+                       "OAuth2 endpoint host to use, only if override-oauth2 is TRUE, otherwise the 
compile-time value is used",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
+
        g_object_class_install_property (
                object_class,
                PROP_CONCURRENT_CONNECTIONS,
@@ -910,6 +938,53 @@ camel_m365_settings_set_oauth2_redirect_uri (CamelM365Settings *settings,
        g_object_notify (G_OBJECT (settings), "oauth2-redirect-uri");
 }
 
+const gchar *
+camel_m365_settings_get_oauth2_endpoint_host (CamelM365Settings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_M365_SETTINGS (settings), NULL);
+
+       return settings->priv->oauth2_endpoint_host;
+}
+
+gchar *
+camel_m365_settings_dup_oauth2_endpoint_host (CamelM365Settings *settings)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (CAMEL_IS_M365_SETTINGS (settings), NULL);
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       protected = camel_m365_settings_get_oauth2_endpoint_host (settings);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+camel_m365_settings_set_oauth2_endpoint_host (CamelM365Settings *settings,
+                                             const gchar *endpoint_host)
+{
+       g_return_if_fail (CAMEL_IS_M365_SETTINGS (settings));
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       if (g_strcmp0 (settings->priv->oauth2_endpoint_host, endpoint_host) == 0) {
+               g_mutex_unlock (&settings->priv->property_lock);
+               return;
+       }
+
+       g_free (settings->priv->oauth2_endpoint_host);
+       settings->priv->oauth2_endpoint_host = e_util_strdup_strip (endpoint_host);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       g_object_notify (G_OBJECT (settings), "oauth2-endpoint-host");
+}
+
 guint
 camel_m365_settings_get_concurrent_connections (CamelM365Settings *settings)
 {
diff --git a/src/Microsoft365/common/camel-m365-settings.h b/src/Microsoft365/common/camel-m365-settings.h
index b2c6835f..7e88963e 100644
--- a/src/Microsoft365/common/camel-m365-settings.h
+++ b/src/Microsoft365/common/camel-m365-settings.h
@@ -115,6 +115,13 @@ gchar *            camel_m365_settings_dup_oauth2_redirect_uri
 void           camel_m365_settings_set_oauth2_redirect_uri
                                                (CamelM365Settings *settings,
                                                 const gchar *redirect_uri);
+const gchar *  camel_m365_settings_get_oauth2_endpoint_host
+                                               (CamelM365Settings *settings);
+gchar *                camel_m365_settings_dup_oauth2_endpoint_host
+                                               (CamelM365Settings *settings);
+void           camel_m365_settings_set_oauth2_endpoint_host
+                                               (CamelM365Settings *settings,
+                                                const gchar *endpoint_host);
 guint          camel_m365_settings_get_concurrent_connections
                                                (CamelM365Settings *settings);
 void           camel_m365_settings_set_concurrent_connections
diff --git a/src/Microsoft365/common/e-oauth2-service-microsoft365.c 
b/src/Microsoft365/common/e-oauth2-service-microsoft365.c
index 18c12f17..d456f79a 100644
--- a/src/Microsoft365/common/e-oauth2-service-microsoft365.c
+++ b/src/Microsoft365/common/e-oauth2-service-microsoft365.c
@@ -59,8 +59,10 @@ eos_microsoft365_cache_string (EOAuth2ServiceMicrosoft365 *oauth2_microsoft365,
        if (!str)
                return NULL;
 
-       if (!*str)
+       if (!*str) {
+               g_free (str);
                return "";
+       }
 
        g_mutex_lock (&oauth2_microsoft365->priv->string_cache_lock);
 
@@ -77,6 +79,24 @@ eos_microsoft365_cache_string (EOAuth2ServiceMicrosoft365 *oauth2_microsoft365,
        return cached_str;
 }
 
+static const gchar *
+eos_microsoft365_get_endpoint_host (EOAuth2ServiceMicrosoft365 *oauth2_microsoft365,
+                                   CamelM365Settings *m365_settings)
+{
+       if (m365_settings && camel_m365_settings_get_override_oauth2 (m365_settings)) {
+               gchar *endpoint_host;
+
+               endpoint_host = camel_m365_settings_dup_oauth2_endpoint_host (m365_settings);
+
+               if (endpoint_host && *endpoint_host)
+                       return eos_microsoft365_cache_string (oauth2_microsoft365, endpoint_host);
+
+               g_free (endpoint_host);
+       }
+
+       return MICROSOFT365_ENDPOINT_HOST;
+}
+
 static CamelM365Settings *
 eos_microsoft365_get_camel_settings (ESource *source)
 {
@@ -163,7 +183,8 @@ eos_microsoft365_get_authentication_uri (EOAuth2Service *service,
                }
 
                res = eos_microsoft365_cache_string (oauth2_microsoft365,
-                       g_strdup_printf ("https://login.microsoftonline.com/%s/oauth2/v2.0/authorize";,
+                       g_strdup_printf ("https://%s/%s/oauth2/v2.0/authorize";,
+                               eos_microsoft365_get_endpoint_host (oauth2_microsoft365, m365_settings),
                                tenant ? tenant : MICROSOFT365_TENANT));
 
                g_free (tenant);
@@ -171,7 +192,10 @@ eos_microsoft365_get_authentication_uri (EOAuth2Service *service,
                return res;
        }
 
-       return "https://login.microsoftonline.com/"; MICROSOFT365_TENANT "/oauth2/v2.0/authorize";
+       return eos_microsoft365_cache_string (oauth2_microsoft365,
+               g_strdup_printf ("https://%s/%s/oauth2/v2.0/authorize";,
+                       eos_microsoft365_get_endpoint_host (oauth2_microsoft365, m365_settings),
+                       MICROSOFT365_TENANT));
 }
 
 static const gchar *
@@ -193,7 +217,8 @@ eos_microsoft365_get_refresh_uri (EOAuth2Service *service,
                }
 
                res = eos_microsoft365_cache_string (oauth2_microsoft365,
-                       g_strdup_printf ("https://login.microsoftonline.com/%s/oauth2/v2.0/token";,
+                       g_strdup_printf ("https://%s/%s/oauth2/v2.0/token";,
+                               eos_microsoft365_get_endpoint_host (oauth2_microsoft365, m365_settings),
                                tenant ? tenant : MICROSOFT365_TENANT));
 
                g_free (tenant);
@@ -201,7 +226,10 @@ eos_microsoft365_get_refresh_uri (EOAuth2Service *service,
                return res;
        }
 
-       return "https://login.microsoftonline.com/"; MICROSOFT365_TENANT "/oauth2/v2.0/token";
+       return eos_microsoft365_cache_string (oauth2_microsoft365,
+               g_strdup_printf ("https://%s/%s/oauth2/v2.0/token";,
+                       eos_microsoft365_get_endpoint_host (oauth2_microsoft365, m365_settings),
+                       MICROSOFT365_TENANT));
 }
 
 static const gchar *
@@ -225,13 +253,21 @@ eos_microsoft365_get_redirect_uri (EOAuth2Service *service,
 
                if (redirect_uri)
                        return eos_microsoft365_cache_string (oauth2_microsoft365, redirect_uri);
+
+               if (e_util_strcmp0 (camel_m365_settings_get_oauth2_endpoint_host (m365_settings), NULL) != 0) 
{
+                       return eos_microsoft365_cache_string (oauth2_microsoft365,
+                               g_strdup_printf ("https://%s/common/oauth2/nativeclient";,
+                                       eos_microsoft365_get_endpoint_host (oauth2_microsoft365, 
m365_settings)));
+               }
        }
 
        res = MICROSOFT365_REDIRECT_URI;
        if (res && *res)
                return res;
 
-       return "https://login.microsoftonline.com/common/oauth2/nativeclient";;
+       return eos_microsoft365_cache_string (oauth2_microsoft365,
+               g_strdup_printf ("https://%s/common/oauth2/nativeclient";,
+                       eos_microsoft365_get_endpoint_host (oauth2_microsoft365, m365_settings)));
 }
 
 static void
diff --git a/src/Microsoft365/evolution/e-mail-config-m365-backend.c 
b/src/Microsoft365/evolution/e-mail-config-m365-backend.c
index 8da11fb4..8184617a 100644
--- a/src/Microsoft365/evolution/e-mail-config-m365-backend.c
+++ b/src/Microsoft365/evolution/e-mail-config-m365-backend.c
@@ -27,6 +27,7 @@ struct _EMailConfigM365BackendPrivate {
        GtkWidget *oauth2_tenant_entry;
        GtkWidget *oauth2_client_id_entry;
        GtkWidget *oauth2_redirect_uri_entry;
+       GtkWidget *oauth2_endpoint_host_entry;
 };
 
 G_DEFINE_DYNAMIC_TYPE_EXTENDED (EMailConfigM365Backend, e_mail_config_m365_backend, 
E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, 0,
@@ -85,6 +86,10 @@ mail_config_m365_backend_insert_widgets (EMailConfigServiceBackend *backend,
        GtkLabel *label;
        GtkWidget *widget;
        GtkWidget *container;
+       GtkWidget *expander;
+       GtkWidget *advanced_help;
+       GtkWidget *endpoint_host_label;
+       GtkWidget *redirect_uri_label;
        const gchar *extension_name;
        const gchar *text;
        gchar *markup;
@@ -260,11 +265,62 @@ mail_config_m365_backend_insert_widgets (EMailConfigServiceBackend *backend,
                _("There is not set any default application ID"),
                g_strdup_printf (_("Default application ID is “%s”"), MICROSOFT365_CLIENT_ID));
 
+       container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, container, 0, 3, 2, 1);
+
+       widget = gtk_expander_new_with_mnemonic (_("_Advanced Settings"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       expander = widget;
+
+       e_binding_bind_property (
+               m365_backend->priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       markup = g_markup_printf_escaped ("(<a 
href=\"https://wiki.gnome.org/Apps/Evolution/EWS/OAuth2#Alternative_endpoints\";>%s</a>)", _("Help…"));
+       widget = gtk_label_new (markup);
+       gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       g_free (markup);
+       advanced_help = widget;
+
+       widget = gtk_label_new_with_mnemonic (_("_Endpoint host:"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, widget, 0, 4, 1, 1);
+       label = GTK_LABEL (widget);
+       endpoint_host_label = widget;
+
+       e_binding_bind_property (
+               m365_backend->priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       widget = gtk_entry_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, widget, 1, 4, 1, 1);
+       m365_backend->priv->oauth2_endpoint_host_entry = widget;
+
+       e_binding_bind_property (
+               m365_backend->priv->oauth2_override_check, "active",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       markup = g_strdup_printf (_("Default endpoint host is “%s”"), "login.microsoftonline.com");
+       mail_config_m365_backend_set_oauth2_tooltip (widget, OFFICE365_ENDPOINT_HOST,
+               markup,
+               g_strdup_printf (_("Default endpoint host is “%s”"), OFFICE365_ENDPOINT_HOST));
+       g_free (markup);
+
        widget = gtk_label_new_with_mnemonic (_("_Redirect URI:"));
        gtk_widget_set_margin_left (widget, 12);
        gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
-       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, widget, 0, 3, 1, 1);
+       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, widget, 0, 5, 1, 1);
        label = GTK_LABEL (widget);
+       redirect_uri_label = widget;
 
        e_binding_bind_property (
                m365_backend->priv->oauth2_override_check, "active",
@@ -274,7 +330,7 @@ mail_config_m365_backend_insert_widgets (EMailConfigServiceBackend *backend,
        widget = gtk_entry_new ();
        gtk_widget_set_hexpand (widget, TRUE);
        gtk_label_set_mnemonic_widget (label, widget);
-       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, widget, 1, 3, 1, 1);
+       gtk_grid_attach (m365_backend->priv->oauth2_settings_grid, widget, 1, 5, 1, 1);
        m365_backend->priv->oauth2_redirect_uri_entry = widget;
 
        e_binding_bind_property (
@@ -290,6 +346,35 @@ mail_config_m365_backend_insert_widgets (EMailConfigServiceBackend *backend,
 
        gtk_widget_show_all (GTK_WIDGET (m365_backend->priv->oauth2_settings_grid));
 
+       gtk_expander_set_expanded (GTK_EXPANDER (expander),
+               e_util_strcmp0 (camel_m365_settings_get_oauth2_endpoint_host (CAMEL_M365_SETTINGS 
(settings)), NULL) != 0 ||
+               e_util_strcmp0 (camel_m365_settings_get_oauth2_redirect_uri (CAMEL_M365_SETTINGS (settings)), 
NULL) != 0);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               advanced_help, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               endpoint_host_label, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               m365_backend->priv->oauth2_endpoint_host_entry, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               redirect_uri_label, "visible",
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               expander, "expanded",
+               m365_backend->priv->oauth2_redirect_uri_entry, "visible",
+               G_BINDING_SYNC_CREATE);
+
        e_binding_bind_object_text_property (
                settings, "user",
                m365_backend->priv->user_entry, "text",
@@ -315,11 +400,17 @@ mail_config_m365_backend_insert_widgets (EMailConfigServiceBackend *backend,
                G_BINDING_SYNC_CREATE);
 
        e_binding_bind_object_text_property (
-               settings, "oauth2-redirect_uri",
+               settings, "oauth2-redirect-uri",
                m365_backend->priv->oauth2_redirect_uri_entry, "text",
                G_BINDING_BIDIRECTIONAL |
                G_BINDING_SYNC_CREATE);
 
+       e_binding_bind_object_text_property (
+               settings, "oauth2-endpoint-host",
+               m365_backend->priv->oauth2_endpoint_host_entry, "text",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE);
+
        extension_name = E_SOURCE_EXTENSION_COLLECTION;
        source = e_mail_config_service_backend_get_collection (backend);
        extension = e_source_get_extension (source, extension_name);



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