Skip to content

Commit 02ae35e

Browse files
authored
Merge pull request #10 from ReleasedGroup/claude/office365-contact-extractor-I4vgl
Fix GAL extraction and make extraction resilient to errors
2 parents 5530db3 + 7f21a33 commit 02ae35e

2 files changed

Lines changed: 50 additions & 38 deletions

File tree

src/FindMyContacts/Services/ContactExtractionService.cs

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,83 +40,95 @@ public async Task<ExtractionResult> ExtractContactsAsync(ExtractionOptions optio
4040

4141
_logger.LogInformation("Starting contact extraction...");
4242

43-
try
43+
// Extract from inbox
44+
if (options.IncludeInbox)
4445
{
45-
// Extract from inbox
46-
if (options.IncludeInbox)
46+
await ExtractWithErrorHandling("inbox", result, async () =>
4747
{
48-
_logger.LogInformation("Extracting contacts from inbox...");
4948
await foreach (var contact in _emailExtractor.ExtractFromInboxAsync(options, cancellationToken))
5049
{
5150
_aggregator.AddContact(contact);
5251
result.Statistics.TotalEmailsProcessed++;
5352
}
54-
}
53+
});
54+
}
5555

56-
// Extract from sent items
57-
if (options.IncludeSentItems)
56+
// Extract from sent items
57+
if (options.IncludeSentItems)
58+
{
59+
await ExtractWithErrorHandling("sent items", result, async () =>
5860
{
59-
_logger.LogInformation("Extracting contacts from sent items...");
6061
await foreach (var contact in _emailExtractor.ExtractFromSentItemsAsync(options, cancellationToken))
6162
{
6263
_aggregator.AddContact(contact);
6364
}
64-
}
65+
});
66+
}
6567

66-
// Extract from calendar events
67-
_logger.LogInformation("Extracting contacts from calendar events...");
68+
// Extract from calendar events
69+
await ExtractWithErrorHandling("calendar events", result, async () =>
70+
{
6871
await foreach (var contact in _meetingExtractor.ExtractFromEventsAsync(options, cancellationToken))
6972
{
7073
_aggregator.AddContact(contact);
7174
result.Statistics.TotalMeetingsProcessed++;
7275
}
76+
});
7377

74-
// Extract from Outlook personal contacts
75-
if (options.IncludeOutlookContacts)
78+
// Extract from Outlook personal contacts
79+
if (options.IncludeOutlookContacts)
80+
{
81+
await ExtractWithErrorHandling("Outlook contacts", result, async () =>
7682
{
77-
_logger.LogInformation("Extracting Outlook personal contacts...");
7883
await foreach (var contact in _outlookExtractor.ExtractContactsAsync(options, cancellationToken))
7984
{
8085
_aggregator.AddContact(contact);
8186
result.Statistics.TotalOutlookContactsProcessed++;
8287
}
83-
}
88+
});
89+
}
8490

85-
// Extract from Global Address List
86-
if (options.IncludeGal)
91+
// Extract from Global Address List
92+
if (options.IncludeGal)
93+
{
94+
await ExtractWithErrorHandling("Global Address List", result, async () =>
8795
{
88-
_logger.LogInformation("Extracting contacts from Global Address List...");
8996
await foreach (var contact in _galExtractor.ExtractContactsAsync(options, cancellationToken))
9097
{
9198
_aggregator.AddContact(contact);
9299
result.Statistics.TotalGalContactsProcessed++;
93100
}
94-
}
101+
});
102+
}
95103

96-
// Get deduplicated contacts
97-
result.Contacts = _aggregator.GetDeduplicatedContacts().ToList();
98-
result.Statistics.TotalContactsFound = _aggregator.TotalContactsAdded;
99-
result.Statistics.UniqueContactsAfterDeduplication = _aggregator.UniqueContactCount;
104+
// Always calculate final statistics
105+
result.Contacts = _aggregator.GetDeduplicatedContacts().ToList();
106+
result.Statistics.TotalContactsFound = _aggregator.TotalContactsAdded;
107+
result.Statistics.UniqueContactsAfterDeduplication = _aggregator.UniqueContactCount;
108+
CalculateStatistics(result);
100109

101-
// Calculate enrichment statistics
102-
CalculateStatistics(result);
110+
result.ExtractionCompletedUtc = DateTime.UtcNow;
103111

104-
_logger.LogInformation(
105-
"Extraction complete. Found {Total} contacts, {Unique} unique after deduplication",
106-
result.Statistics.TotalContactsFound,
107-
result.Statistics.UniqueContactsAfterDeduplication);
108-
}
109-
catch (Exception ex)
112+
_logger.LogInformation(
113+
"Extraction complete. Found {Total} contacts, {Unique} unique after deduplication",
114+
result.Statistics.TotalContactsFound,
115+
result.Statistics.UniqueContactsAfterDeduplication);
116+
117+
return result;
118+
}
119+
120+
private async Task ExtractWithErrorHandling(string source, ExtractionResult result, Func<Task> extractAction)
121+
{
122+
try
110123
{
111-
_logger.LogError(ex, "Error during contact extraction");
112-
result.Errors.Add(ex.Message);
124+
_logger.LogInformation("Extracting contacts from {Source}...", source);
125+
await extractAction();
113126
}
114-
finally
127+
catch (Exception ex)
115128
{
116-
result.ExtractionCompletedUtc = DateTime.UtcNow;
129+
_logger.LogError(ex, "Error extracting from {Source}", source);
130+
result.Errors.Add($"Error extracting from {source}: {ex.Message}");
117131
}
118-
119-
return result;
120132
}
121133

122134
private static void CalculateStatistics(ExtractionResult result)

src/FindMyContacts/Services/GalContactExtractor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public async IAsyncEnumerable<Contact> ExtractContactsAsync(
4040
requestConfig.QueryParameters.Top = 100;
4141
requestConfig.QueryParameters.Select =
4242
[
43-
"id", "displayName", "givenName", "surname", "emailAddresses",
43+
"id", "displayName", "givenName", "surname", "scoredEmailAddresses",
4444
"companyName", "jobTitle", "department", "officeLocation",
4545
"phones", "userPrincipalName"
4646
];

0 commit comments

Comments
 (0)