From 7ffaddc77f75cd9e8fc0f2581b9ec80a59a76398 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 3 Apr 2026 18:54:10 +0200 Subject: [PATCH] Use reflection-based SafeGet for Outlook COM property reading Dynamic COM with ?? operator can fail silently for properties that return COM null vs .NET null. Use GetType().InvokeMember() which reliably reads any Outlook property and catches COM errors per field instead of crashing the whole contact read. Fixes Fax and other fields that may not have been read correctly. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Services/OutlookContactsService.cs | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/StarfaceOutlookSync/Services/OutlookContactsService.cs b/src/StarfaceOutlookSync/Services/OutlookContactsService.cs index be693544..9259869c 100644 --- a/src/StarfaceOutlookSync/Services/OutlookContactsService.cs +++ b/src/StarfaceOutlookSync/Services/OutlookContactsService.cs @@ -394,29 +394,40 @@ namespace StarfaceOutlookSync.Services } } + private static string SafeGet(dynamic ci, string property) + { + try + { + object val = ci.GetType().InvokeMember(property, + System.Reflection.BindingFlags.GetProperty, null, ci, null); + return val?.ToString() ?? ""; + } + catch { return ""; } + } + private UnifiedContact MapFromOutlook(dynamic ci) { return new UnifiedContact { - OutlookEntryId = (string)(ci.EntryID ?? ""), - FirstName = (string)(ci.FirstName ?? ""), - LastName = (string)(ci.LastName ?? ""), - Company = (string)(ci.CompanyName ?? ""), - JobTitle = (string)(ci.JobTitle ?? ""), - Email = (string)(ci.Email1Address ?? ""), - EmailSecondary = (string)(ci.Email2Address ?? ""), - PhoneWork = (string)(ci.BusinessTelephoneNumber ?? ""), - PhoneMobile = (string)(ci.MobileTelephoneNumber ?? ""), - PhoneHome = (string)(ci.HomeTelephoneNumber ?? ""), - Fax = (string)(ci.BusinessFaxNumber ?? ""), - Street = (string)(ci.BusinessAddressStreet ?? ""), - City = (string)(ci.BusinessAddressCity ?? ""), - PostalCode = (string)(ci.BusinessAddressPostalCode ?? ""), - State = (string)(ci.BusinessAddressState ?? ""), - Country = (string)(ci.BusinessAddressCountry ?? ""), - Website = (string)(ci.WebPage ?? ""), - Notes = (string)(ci.Body ?? ""), - Salutation = (string)(ci.Title ?? ""), + OutlookEntryId = SafeGet(ci, "EntryID"), + FirstName = SafeGet(ci, "FirstName"), + LastName = SafeGet(ci, "LastName"), + Company = SafeGet(ci, "CompanyName"), + JobTitle = SafeGet(ci, "JobTitle"), + Email = SafeGet(ci, "Email1Address"), + EmailSecondary = SafeGet(ci, "Email2Address"), + PhoneWork = SafeGet(ci, "BusinessTelephoneNumber"), + PhoneMobile = SafeGet(ci, "MobileTelephoneNumber"), + PhoneHome = SafeGet(ci, "HomeTelephoneNumber"), + Fax = SafeGet(ci, "BusinessFaxNumber"), + Street = SafeGet(ci, "BusinessAddressStreet"), + City = SafeGet(ci, "BusinessAddressCity"), + PostalCode = SafeGet(ci, "BusinessAddressPostalCode"), + State = SafeGet(ci, "BusinessAddressState"), + Country = SafeGet(ci, "BusinessAddressCountry"), + Website = SafeGet(ci, "WebPage"), + Notes = SafeGet(ci, "Body"), + Salutation = SafeGet(ci, "Title"), Birthday = GetBirthdayString(ci) }; } @@ -425,8 +436,9 @@ namespace StarfaceOutlookSync.Services { try { - DateTime bday = ci.Birthday; - if (bday.Year > 1900 && bday != DateTime.MinValue) + object val = ci.GetType().InvokeMember("Birthday", + System.Reflection.BindingFlags.GetProperty, null, ci, null); + if (val is DateTime bday && bday.Year > 1900 && bday != DateTime.MinValue) return bday.ToString("yyyy-MM-dd"); } catch { }