using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Outlook = Microsoft.Office.Interop.Outlook; namespace BulkArchiveMailer.AddIn { /// Read-only snapshot of one Outlook.Account, taken once while the COM object was still alive - safe to hold onto and display after the Account RCW itself has been released. public sealed class OutlookAccountInfo { public string DisplayName { get; set; } = ""; public string SmtpAddress { get; set; } = ""; } /// /// Enumerates Outlook.Application.Session.Accounts for UI purposes /// (the "Отправлять от:" picker in SettingsForm) without leaking any /// COM references - mirrors the release-what-you-touch convention used /// in MailSender/SignatureReader. Never throws: on any failure it /// returns an empty list so a picker can simply fall back to "default /// account only" instead of crashing the Settings window. /// public static class OutlookAccounts { public static List ListAccounts(Outlook.Application application) { var result = new List(); if (application == null) { return result; } Outlook.Accounts accounts = null; try { accounts = application.Session.Accounts; foreach (Outlook.Account account in accounts) { try { result.Add(new OutlookAccountInfo { DisplayName = account.DisplayName ?? "", SmtpAddress = account.SmtpAddress ?? "", }); } catch { // Skip an individual account we couldn't read // rather than losing the rest of the list. } finally { Marshal.ReleaseComObject(account); } } } catch { return new List(); } finally { if (accounts != null) { Marshal.ReleaseComObject(accounts); } // application.Session (NameSpace) is a long-lived object // owned by Outlook itself - never released here, same as // in MailSender. } return result; } } }