Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package evolution-ews for openSUSE:Factory checked in at 2026-05-25 21:52:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/evolution-ews (Old) and /work/SRC/openSUSE:Factory/.evolution-ews.new.2084 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "evolution-ews" Mon May 25 21:52:18 2026 rev:158 rq:1354856 version:3.60.2 Changes: -------- --- /work/SRC/openSUSE:Factory/evolution-ews/evolution-ews.changes 2026-04-15 16:05:20.612905462 +0200 +++ /work/SRC/openSUSE:Factory/.evolution-ews.new.2084/evolution-ews.changes 2026-05-25 21:53:18.364333575 +0200 @@ -1,0 +2,16 @@ +Fri May 22 05:32:12 UTC 2026 - Bjørn Lie <[email protected]> + +- Update to version 3.60.2: + + Bug Fixes: + - m365: + . Skip Out of Office check for shared mailboxes + . GOA account can delay OAuth2 support addition + - Truncated file stored in the (mail) cache + + Miscellaneous: + - e-m365-connection: Ensure soup message body is filled on + retry + - Calendar: Use icaldurationtype_as_utc_seconds() for libical + 4.x + - OAuth2: Uses its own error domain + +------------------------------------------------------------------- Old: ---- evolution-ews-3.60.1.tar.xz New: ---- evolution-ews-3.60.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ evolution-ews.spec ++++++ --- /var/tmp/diff_new_pack.i1YbeW/_old 2026-05-25 21:53:20.000400854 +0200 +++ /var/tmp/diff_new_pack.i1YbeW/_new 2026-05-25 21:53:20.000400854 +0200 @@ -20,7 +20,7 @@ %define _version %(echo %{version} | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+') Name: evolution-ews -Version: 3.60.1 +Version: 3.60.2 Release: 0 Summary: Exchange Connector for Evolution, compatible with Exchange 2007 and later License: LGPL-2.1-only ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.i1YbeW/_old 2026-05-25 21:53:20.036402335 +0200 +++ /var/tmp/diff_new_pack.i1YbeW/_new 2026-05-25 21:53:20.040402499 +0200 @@ -1,6 +1,6 @@ -mtime: 1775827844 -commit: 1c71ec7c9334458cfcb45b92d04fc00339362dc3a120453bb9669a1794f33b01 +mtime: 1779428056 +commit: 09987044b377b9f9e34bfa641d17d2ab12b41a2d4f0c27e8c0dadaa778b1c48a url: https://src.opensuse.org/GNOME/evolution-ews -revision: 1c71ec7c9334458cfcb45b92d04fc00339362dc3a120453bb9669a1794f33b01 +revision: 09987044b377b9f9e34bfa641d17d2ab12b41a2d4f0c27e8c0dadaa778b1c48a projectscmsync: https://src.opensuse.org/GNOME/_ObsPrj ++++++ _service ++++++ --- /var/tmp/diff_new_pack.i1YbeW/_old 2026-05-25 21:53:20.064403486 +0200 +++ /var/tmp/diff_new_pack.i1YbeW/_new 2026-05-25 21:53:20.068403651 +0200 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://gitlab.gnome.org/GNOME/evolution-ews.git</param> - <param name="revision">3.60.1</param> + <param name="revision">3.60.2</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> <param name="versionrewrite-pattern">(.*)\+0</param> <param name="versionrewrite-replacement">\1</param> ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-05-22 07:34:16.000000000 +0200 @@ -0,0 +1,5 @@ +*.obscpio +*.osc +_build.* +.pbuild +osc-collab.* ++++++ evolution-ews-3.60.1.tar.xz -> evolution-ews-3.60.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/CMakeLists.txt new/evolution-ews-3.60.2/CMakeLists.txt --- old/evolution-ews-3.60.1/CMakeLists.txt 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/CMakeLists.txt 2026-05-22 06:08:29.000000000 +0200 @@ -4,7 +4,7 @@ cmake_policy(VERSION 3.15) project(evolution-ews - VERSION 3.60.1 + VERSION 3.60.2 LANGUAGES C) set(PROJECT_BUGREPORT "https://gitlab.gnome.org/GNOME/evolution-ews/issues/") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/NEWS new/evolution-ews-3.60.2/NEWS --- old/evolution-ews-3.60.1/NEWS 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/NEWS 2026-05-22 06:08:29.000000000 +0200 @@ -1,3 +1,16 @@ +Evolution-EWS 3.60.2 2026-05-22 +------------------------------- + +Bug Fixes: + I#333 - m365: Skip Out of Office check for shared mailboxes + I#335 - m365: GOA account can delay OAuth2 support addition + evo-I#3302 - Truncated file stored in the (mail) cache + +Miscellaneous: + e-m365-connection: Ensure soup message body is filled on retry + Calendar: Use icaldurationtype_as_utc_seconds() for libical 4.x + OAuth2: Uses its own error domain + Evolution-EWS 3.60.1 2026-04-10 ------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/EWS/calendar/e-cal-backend-ews-utils.c new/evolution-ews-3.60.2/src/EWS/calendar/e-cal-backend-ews-utils.c --- old/evolution-ews-3.60.1/src/EWS/calendar/e-cal-backend-ews-utils.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/EWS/calendar/e-cal-backend-ews-utils.c 2026-05-22 06:08:29.000000000 +0200 @@ -37,7 +37,7 @@ #if !ICAL_CHECK_VERSION(3, 99, 99) #define ICalPropertyClassenum ICalProperty_Class #define i_cal_duration_new_from_seconds i_cal_duration_new_from_int -#define i_cal_duration_as_seconds i_cal_duration_as_int +#define i_cal_duration_as_utc_seconds i_cal_duration_as_int #endif /* @@ -325,7 +325,7 @@ trigger = e_cal_component_alarm_get_trigger (alarm); if (trigger && e_cal_component_alarm_trigger_get_kind (trigger) == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START) { - dur_int = (i_cal_duration_as_seconds (e_cal_component_alarm_trigger_get_duration (trigger)) / SECS_IN_MINUTE) * -1; + dur_int = (i_cal_duration_as_utc_seconds (e_cal_component_alarm_trigger_get_duration (trigger)) / SECS_IN_MINUTE) * -1; } } e_cal_component_alarm_free (alarm); @@ -360,7 +360,7 @@ trigger = e_cal_component_alarm_get_trigger (alarm); if (trigger && e_cal_component_alarm_trigger_get_kind (trigger) == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START) { - dur_int = (i_cal_duration_as_seconds (e_cal_component_alarm_trigger_get_duration (trigger)) / SECS_IN_MINUTE) * -1; + dur_int = (i_cal_duration_as_utc_seconds (e_cal_component_alarm_trigger_get_duration (trigger)) / SECS_IN_MINUTE) * -1; e_ews_request_write_int_parameter (request, "ReminderMinutesBeforeStart", NULL, dur_int); if (with_due_by) { ICalTime *dtstart; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/EWS/camel/camel-ews-folder.c new/evolution-ews-3.60.2/src/EWS/camel/camel-ews-folder.c --- old/evolution-ews-3.60.1/src/EWS/camel/camel-ews-folder.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/EWS/camel/camel-ews-folder.c 2026-05-22 06:08:29.000000000 +0200 @@ -2650,6 +2650,7 @@ CamelMessageInfo *info; CamelMessageInfo *clone; const EwsId *id; + gchar *tmp_fname, *cur_fname, *dirname; if (e_ews_item_get_item_type (l->data) == E_EWS_ITEM_TYPE_ERROR) { if (!local_error) @@ -2664,8 +2665,11 @@ if (message == NULL) continue; + /* Write to "tmp" first; rename to "cur" only after the write + completes, so an interrupted copy never leaves a truncated + "cur" file that would be treated as a valid cached message. */ stream = ews_data_cache_add ( - CAMEL_EWS_FOLDER (destination)->cache, "cur", id->id, NULL); + CAMEL_EWS_FOLDER (destination)->cache, "tmp", id->id, NULL); if (stream == NULL) { g_object_unref (message); @@ -2675,14 +2679,32 @@ camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (message), stream, cancellable, NULL); + g_clear_object (&stream); + info = camel_folder_summary_get (camel_folder_get_folder_summary (source), uids->pdata[i]); if (info == NULL) { - g_object_unref (stream); + ews_data_cache_remove (CAMEL_EWS_FOLDER (destination)->cache, "tmp", id->id, NULL); g_object_unref (message); continue; } + tmp_fname = ews_data_cache_get_filename (CAMEL_EWS_FOLDER (destination)->cache, "tmp", id->id, NULL); + cur_fname = ews_data_cache_get_filename (CAMEL_EWS_FOLDER (destination)->cache, "cur", id->id, NULL); + dirname = g_path_get_dirname (cur_fname); + g_mkdir_with_parents (dirname, 0700); + g_free (dirname); + + if (g_rename (tmp_fname, cur_fname) != 0) { + gint errsv = errno; + g_warning ("%s: Failed to rename '%s' to '%s': %s", + G_STRFUNC, tmp_fname, cur_fname, g_strerror (errsv)); + } + + ews_data_cache_remove (CAMEL_EWS_FOLDER (destination)->cache, "tmp", id->id, NULL); + g_free (tmp_fname); + g_free (cur_fname); + clone = camel_message_info_clone (info, NULL); if (camel_ews_summary_add_message (camel_folder_get_folder_summary (destination), id->id, id->change_key, clone, message)) @@ -2690,7 +2712,6 @@ g_clear_object (&clone); g_clear_object (&info); - g_object_unref (stream); g_object_unref (message); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/EWS/common/e-ews-connection.c new/evolution-ews-3.60.2/src/EWS/common/e-ews-connection.c --- old/evolution-ews-3.60.1/src/EWS/common/e-ews-connection.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/EWS/common/e-ews-connection.c 2026-05-22 06:08:29.000000000 +0200 @@ -436,8 +436,8 @@ if (!pd.prepare_data) { if (error && (g_error_matches (*error, E_SOUP_SESSION_ERROR, SOUP_STATUS_UNAUTHORIZED) || - /* Returned by the OAuth2 service when the token cannot be refreshed */ - g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED))) { + g_error_matches (*error, E_OAUTH2_SERVICE_ERROR, E_OAUTH2_SERVICE_ERROR_TOKEN_EXPIRED) || + g_error_matches (*error, E_OAUTH2_SERVICE_ERROR, E_OAUTH2_SERVICE_ERROR_REFRESH_FAILED))) { (*error)->domain = EWS_CONNECTION_ERROR; (*error)->code = EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/calendar/e-cal-backend-m365-utils.c new/evolution-ews-3.60.2/src/Microsoft365/calendar/e-cal-backend-m365-utils.c --- old/evolution-ews-3.60.1/src/Microsoft365/calendar/e-cal-backend-m365-utils.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/calendar/e-cal-backend-m365-utils.c 2026-05-22 06:08:29.000000000 +0200 @@ -22,7 +22,7 @@ #if !ICAL_CHECK_VERSION(3, 99, 99) #define ICalPropertyClassenum ICalProperty_Class #define i_cal_duration_new_from_seconds i_cal_duration_new_from_int -#define i_cal_duration_as_seconds i_cal_duration_as_int +#define i_cal_duration_as_utc_seconds i_cal_duration_as_int #endif static void @@ -2097,7 +2097,7 @@ if (success) { new_duration = e_cal_component_alarm_trigger_get_duration (new_trigger); - success = new_duration && i_cal_duration_as_seconds (new_duration) <= 0; + success = new_duration && i_cal_duration_as_utc_seconds (new_duration) <= 0; } if (!success) { @@ -2141,7 +2141,7 @@ case I_CAL_VEVENT_COMPONENT: old_duration = e_cal_component_alarm_trigger_get_duration (old_trigger); - changed = !old_duration || i_cal_duration_as_seconds (new_duration) != i_cal_duration_as_seconds (old_duration); + changed = !old_duration || i_cal_duration_as_utc_seconds (new_duration) != i_cal_duration_as_utc_seconds (old_duration); break; case I_CAL_VTODO_COMPONENT: old_absolute_time = e_cal_component_alarm_trigger_get_absolute_time (old_trigger); @@ -2167,7 +2167,7 @@ switch (kind) { case I_CAL_VEVENT_COMPONENT: e_m365_event_add_is_reminder_on (builder, TRUE); - e_m365_event_add_reminder_minutes_before_start (builder, i_cal_duration_as_seconds (new_duration) / -60); + e_m365_event_add_reminder_minutes_before_start (builder, i_cal_duration_as_utc_seconds (new_duration) / -60); break; case I_CAL_VTODO_COMPONENT: izone = i_cal_time_get_timezone (new_absolute_time); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/camel/camel-m365-folder.c new/evolution-ews-3.60.2/src/Microsoft365/camel/camel-m365-folder.c --- old/evolution-ews-3.60.1/src/Microsoft365/camel/camel-m365-folder.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/camel/camel-m365-folder.c 2026-05-22 06:08:29.000000000 +0200 @@ -8,6 +8,7 @@ #include <string.h> #include <glib/gi18n-lib.h> +#include <glib/gstdio.h> #include "e-ews-common-utils.h" @@ -85,31 +86,6 @@ return checksum; } -static CamelStream * -m365_folder_cache_add (CamelM365Folder *m365_folder, - const gchar *id, - GError **error) -{ - GIOStream *base_stream; - CamelStream *stream = NULL; - GChecksum *checksum; - - checksum = m365_folder_cache_new_checksum (id); - - LOCK_CACHE (m365_folder); - base_stream = camel_data_cache_add (m365_folder->priv->cache, M365_LOCAL_CACHE_PATH, g_checksum_get_string (checksum), error); - UNLOCK_CACHE (m365_folder); - - g_checksum_free (checksum); - - if (base_stream) { - stream = camel_stream_new (base_stream); - g_object_unref (base_stream); - } - - return stream; -} - static gint m365_folder_cache_remove (CamelM365Folder *m365_folder, const gchar *id, @@ -324,7 +300,22 @@ g_mutex_unlock (&m365_folder->priv->get_message_lock); if (success && !message) { - cache_stream = m365_folder_cache_add (m365_folder, uid, error); + GChecksum *checksum; + GIOStream *base_stream; + gchar *tmp_filename, *cur_filename; + + /* Write to "tmp" first; rename to "cur" only on success so an + interrupted download never leaves a truncated "cur" file. */ + checksum = m365_folder_cache_new_checksum (uid); + + LOCK_CACHE (m365_folder); + base_stream = camel_data_cache_add (m365_folder->priv->cache, "tmp", g_checksum_get_string (checksum), error); + tmp_filename = camel_data_cache_get_filename (m365_folder->priv->cache, "tmp", g_checksum_get_string (checksum)); + cur_filename = camel_data_cache_get_filename (m365_folder->priv->cache, M365_LOCAL_CACHE_PATH, g_checksum_get_string (checksum)); + UNLOCK_CACHE (m365_folder); + + cache_stream = base_stream != NULL ? camel_stream_new (base_stream) : NULL; + g_clear_object (&base_stream); success = cache_stream != NULL; @@ -343,13 +334,35 @@ success = FALSE; } + /* Close the write stream before committing so the rename is safe + on all platforms and all data is flushed to disk. */ + g_clear_object (&cache_stream); + if (success) { - /* First free the cache stream, thus the follwing call opens a new instance, - which is rewinded at the beginning of the stream. */ - g_clear_object (&cache_stream); + gchar *dirname; + gint saved_errno; - message = m365_folder_get_message_from_cache (m365_folder, uid, cancellable, error); + dirname = g_path_get_dirname (cur_filename); + g_mkdir_with_parents (dirname, 0700); + g_free (dirname); + + if (g_rename (tmp_filename, cur_filename) == 0) { + camel_data_cache_remove (m365_folder->priv->cache, "tmp", g_checksum_get_string (checksum), NULL); + message = m365_folder_get_message_from_cache (m365_folder, uid, cancellable, error); + } else { + saved_errno = errno; + camel_data_cache_remove (m365_folder->priv->cache, "tmp", g_checksum_get_string (checksum), NULL); + g_set_error (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, + "Failed to store message '%s': %s", uid, g_strerror (saved_errno)); + success = FALSE; + } + } else { + camel_data_cache_remove (m365_folder->priv->cache, "tmp", g_checksum_get_string (checksum), NULL); } + + g_checksum_free (checksum); + g_free (tmp_filename); + g_free (cur_filename); } g_clear_object (&cache_stream); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/camel/camel-m365-store.c new/evolution-ews-3.60.2/src/Microsoft365/camel/camel-m365-store.c --- old/evolution-ews-3.60.1/src/Microsoft365/camel/camel-m365-store.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/camel/camel-m365-store.c 2026-05-22 06:08:29.000000000 +0200 @@ -508,6 +508,7 @@ CamelM365Store *self = user_data; EM365AutomaticRepliesSetting *setting = NULL; EM365Connection *cnc; + GError *local_error = NULL; cnc = camel_m365_store_ref_connection (self); if (!cnc) @@ -515,16 +516,47 @@ camel_operation_push_message (cancellable, _("Checking “Out of Office” settings")); - if (e_m365_connection_get_automatic_replies_setting_sync (cnc, NULL, &setting, cancellable, error) && setting) { + if (e_m365_connection_get_automatic_replies_setting_sync (cnc, NULL, &setting, cancellable, &local_error) && setting) { camel_m365_store_set_has_ooo_set (self, e_m365_automatic_replies_setting_get_status (setting) == E_M365_AUTOMATIC_REPLIES_STATUS_ALWAYS_ENABLED); g_clear_pointer (&setting, json_object_unref); } + /* This can be returned for shared mailboxes */ + if (g_error_matches (local_error, E_M365_ERROR, E_M365_ERROR_ACCESS_DENIED)) + g_clear_error (&local_error); + else if (local_error) + g_propagate_error (error, local_error); + camel_operation_pop_message (cancellable); g_clear_object (&cnc); } static gboolean +m365_store_is_shared_mailbox (CamelM365Store *self) +{ + CamelSettings *settings; + gboolean is_shared = FALSE; + + settings = camel_service_ref_settings (CAMEL_SERVICE (self)); + + if (CAMEL_IS_M365_SETTINGS (settings)) { + CamelM365Settings *m365_settings = CAMEL_M365_SETTINGS (settings); + + if (camel_m365_settings_get_use_impersonation (m365_settings)) { + const gchar *impersonate_user; + + impersonate_user = camel_m365_settings_get_impersonate_user (m365_settings); + + is_shared = impersonate_user && *impersonate_user; + } + } + + g_clear_object (&settings); + + return is_shared; +} + +static gboolean m365_store_connect_sync (CamelService *service, GCancellable *cancellable, GError **error) @@ -567,7 +599,7 @@ state = camel_m365_store_get_ooo_alert_state (m365_store); - if (state == CAMEL_M365_STORE_OOO_ALERT_STATE_UNKNOWN) { + if (state == CAMEL_M365_STORE_OOO_ALERT_STATE_UNKNOWN && !m365_store_is_shared_mailbox (m365_store)) { camel_session_submit_job ( session, _("Checking “Out of Office” settings"), m365_update_has_ooo_set, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/common/e-m365-connection.c new/evolution-ews-3.60.2/src/Microsoft365/common/e-m365-connection.c --- old/evolution-ews-3.60.1/src/Microsoft365/common/e-m365-connection.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/common/e-m365-connection.c 2026-05-22 06:08:29.000000000 +0200 @@ -966,6 +966,9 @@ } else if (g_strcmp0 (code, "ErrorInvalidIdMalformed") == 0) { domain = E_M365_ERROR; status_code = E_M365_ERROR_ID_MALFORMED; + } else if (g_strcmp0 (code, "ErrorAccessDenied") == 0) { + domain = E_M365_ERROR; + status_code = E_M365_ERROR_ACCESS_DENIED; } else if (g_strcmp0 (code, "SyncStateNotFound") == 0) { domain = E_M365_ERROR; status_code = E_M365_ERROR_SYNC_STATE_NOT_FOUND; @@ -1279,6 +1282,8 @@ if (need_retry) { success = FALSE; g_clear_error (error); + + g_signal_emit_by_name (message, "restarted"); } } @@ -1539,8 +1544,8 @@ } else if (e_soup_session_get_ssl_error_details (E_SOUP_SESSION (cnc->priv->soup_session), out_certificate_pem, out_certificate_errors)) { result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED; } else if (g_error_matches (local_error, E_SOUP_SESSION_ERROR, SOUP_STATUS_UNAUTHORIZED) || - /* Returned by the OAuth2 service when the token cannot be refreshed */ - g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { + g_error_matches (local_error, E_OAUTH2_SERVICE_ERROR, E_OAUTH2_SERVICE_ERROR_TOKEN_EXPIRED) || + g_error_matches (local_error, E_OAUTH2_SERVICE_ERROR, E_OAUTH2_SERVICE_ERROR_REFRESH_FAILED)) { LOCK (cnc); if (cnc->priv->impersonate_user) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/common/e-m365-connection.h new/evolution-ews-3.60.2/src/Microsoft365/common/e-m365-connection.h --- old/evolution-ews-3.60.1/src/Microsoft365/common/e-m365-connection.h 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/common/e-m365-connection.h 2026-05-22 06:08:29.000000000 +0200 @@ -54,7 +54,8 @@ typedef enum { E_M365_ERROR_ID_MALFORMED, E_M365_ERROR_SYNC_STATE_NOT_FOUND, - E_M365_ERROR_ITEM_NOT_FOUND + E_M365_ERROR_ITEM_NOT_FOUND, + E_M365_ERROR_ACCESS_DENIED } EM365Error; #define E_M365_ERROR e_m365_error_quark () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/evolution/e-mail-config-m365-notebook.c new/evolution-ews-3.60.2/src/Microsoft365/evolution/e-mail-config-m365-notebook.c --- old/evolution-ews-3.60.1/src/Microsoft365/evolution/e-mail-config-m365-notebook.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/evolution/e-mail-config-m365-notebook.c 2026-05-22 06:08:29.000000000 +0200 @@ -7,6 +7,8 @@ #include <mail/e-mail-config-notebook.h> +#include "common/camel-m365-settings.h" + #include "e-mail-config-m365-ooo-page.h" #include "e-mail-config-m365-notebook.h" @@ -22,6 +24,33 @@ return E_MAIL_CONFIG_NOTEBOOK (e_extension_get_extensible (E_EXTENSION (self))); } +static gboolean +mail_config_m365_notebook_is_shared_mailbox (ESource *collection_source) +{ + CamelSettings *settings; + CamelM365Settings *m365_settings; + ESourceCamel *extension; + const gchar *extension_name; + const gchar *impersonate_user; + + extension_name = e_source_camel_get_extension_name ("Microsoft365"); + extension = e_source_get_extension (collection_source, extension_name); + + settings = e_source_camel_get_settings (extension); + + if (!settings || !CAMEL_IS_M365_SETTINGS (settings)) + return FALSE; + + m365_settings = CAMEL_M365_SETTINGS (settings); + + if (!camel_m365_settings_get_use_impersonation (m365_settings)) + return FALSE; + + impersonate_user = camel_m365_settings_get_impersonate_user (m365_settings); + + return impersonate_user && *impersonate_user; +} + static void mail_config_m365_notebook_constructed (GObject *object) { @@ -53,7 +82,7 @@ backend_ext = e_source_get_extension (account_source, extension_name); backend_name = e_source_backend_get_backend_name (backend_ext); - if (g_strcmp0 (backend_name, "microsoft365") == 0) { + if (g_strcmp0 (backend_name, "microsoft365") == 0 && !mail_config_m365_notebook_is_shared_mailbox (collection_source)) { EMailConfigPage *page; page = e_mail_config_m365_ooo_page_new (registry, account_source, identity_source, collection_source); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.60.1/src/Microsoft365/registry/e-m365-backend.c new/evolution-ews-3.60.2/src/Microsoft365/registry/e-m365-backend.c --- old/evolution-ews-3.60.1/src/Microsoft365/registry/e-m365-backend.c 2026-04-10 09:42:23.000000000 +0200 +++ new/evolution-ews-3.60.2/src/Microsoft365/registry/e-m365-backend.c 2026-05-22 06:08:29.000000000 +0200 @@ -26,6 +26,7 @@ gboolean need_update_folders; gulong source_changed_id; + gulong oauth2_support_handler_id; }; G_DEFINE_DYNAMIC_TYPE_EXTENDED (EM365Backend, e_m365_backend, E_TYPE_COLLECTION_BACKEND, 0, @@ -55,6 +56,20 @@ static void m365_backend_populate (ECollectionBackend *backend); static void +m365_backend_oauth2_support_ready_cb (GObject *source, + GParamSpec *pspec, + EM365Backend *m365_backend) +{ + if (m365_backend->priv->oauth2_support_handler_id) { + g_signal_handler_disconnect (source, m365_backend->priv->oauth2_support_handler_id); + m365_backend->priv->oauth2_support_handler_id = 0; + } + + if (e_backend_get_online (E_BACKEND (m365_backend))) + e_backend_schedule_authenticate (E_BACKEND (m365_backend), NULL); +} + +static void m365_backend_source_changed_cb (ESource *source, EM365Backend *backend) { @@ -96,8 +111,35 @@ m365_backend_claim_old_resources (collection_backend); - if (e_backend_get_online (backend)) - e_backend_schedule_authenticate (backend, NULL); + if (e_backend_get_online (backend)) { + gboolean is_external = FALSE; + + if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) { + ESourceAuthentication *auth_extension; + + auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION); + is_external = e_source_authentication_get_is_external (auth_extension); + } + + /* For GOA-managed sources, oauth2_support is set asynchronously. If it hasn't + been set yet, wait for it before scheduling authentication to avoid a spurious + "does not support OAuth 2.0 authentication" error. */ + if (is_external && E_IS_SERVER_SIDE_SOURCE (source)) { + EOAuth2Support *oauth2_support; + + oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (source)); + if (oauth2_support) { + g_clear_object (&oauth2_support); + e_backend_schedule_authenticate (backend, NULL); + } else if (!m365_backend->priv->oauth2_support_handler_id) { + m365_backend->priv->oauth2_support_handler_id = g_signal_connect ( + source, "notify::oauth2-support", + G_CALLBACK (m365_backend_oauth2_support_ready_cb), m365_backend); + } + } else { + e_backend_schedule_authenticate (backend, NULL); + } + } e_collection_backend_thaw_populate (collection_backend); } @@ -957,6 +999,11 @@ m365_backend->priv->source_changed_id = 0; } + if (source && m365_backend->priv->oauth2_support_handler_id) { + g_signal_handler_disconnect (source, m365_backend->priv->oauth2_support_handler_id); + m365_backend->priv->oauth2_support_handler_id = 0; + } + /* Chain up to parent's method. */ G_OBJECT_CLASS (e_m365_backend_parent_class)->dispose (object); } ++++++ evolution-ews.obsinfo ++++++ --- /var/tmp/diff_new_pack.i1YbeW/_old 2026-05-25 21:53:20.824434741 +0200 +++ /var/tmp/diff_new_pack.i1YbeW/_new 2026-05-25 21:53:20.828434905 +0200 @@ -1,5 +1,5 @@ name: evolution-ews -version: 3.60.1 -mtime: 1775806943 -commit: 63370324044f652f016f82a8461d47cfd24ebd63 +version: 3.60.2 +mtime: 1779422909 +commit: e83b6a98572fe6e031f3b70355d98cdf06a62274
