From 48796d9917d60c7d28f7a25cb75bc726c8443614 Mon Sep 17 00:00:00 2001 From: TekH Date: Wed, 12 Aug 2026 13:41:35 +0200 Subject: [PATCH] Refactor email filtering logic in LimilabsImapEmailService Simplify email filtering by removing server-side filtering logic and replacing it with in-process filtering after email retrieval. Eliminate the use of `ICriterion` and `Expression` constructs, and move all filtering conditions (e.g., `UnseenOnly`, `SubjectContains`, `SenderContains`, etc.) into the processing loop. Add an `IsSeen` property to `ReceivedEmailContext` to track email read status. Apply `filter.MaxCount` after all filtering and processing are complete. Update `filter.WithAttachments` logic to conditionally include attachments in results. Improve code readability and maintainability by consolidating filtering logic into a single location, ensuring consistent application of all filters. --- .../Services/LimilabsImapEmailService.cs | 83 ++++++++++--------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs index 43d7487..9aba1e5 100644 --- a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs +++ b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs @@ -37,35 +37,9 @@ public class LimilabsImapEmailService( try { #region Find UIDs + // Server-side: only date range; all other filters are applied in-process after cache retrieval List criterions = []; - if (filter.UnseenOnly) - criterions.Add(Expression.HasFlag(Flag.Unseen)); - - if (filter.SubjectContains is not null) - criterions.Add(Expression.Subject(filter.SubjectContains)); - - if (filter.SenderContains is not null) - criterions.Add(Expression.From(filter.SenderContains)); - - if (filter.RecipientContains is not null) - criterions.Add(Expression.To(filter.RecipientContains)); - - if (filter.BodyContains is not null) - criterions.Add(Expression.Body(filter.BodyContains)); - - if (filter.Uid is UidFilter uidF) - { - if (uidF.Absolute is long exactUid) - criterions.Add(Expression.UID(new Limilabs.Client.IMAP.Range(exactUid, exactUid))); - else - { - long lo = uidF.Min ?? 1L; - long? hi = uidF.Max; - criterions.Add(Expression.UID(new Limilabs.Client.IMAP.Range(lo, hi))); - } - } - if (filter.Date is DateFilter dateF) { if (dateF.After is DateTime after) @@ -81,14 +55,11 @@ public class LimilabsImapEmailService( if (filter.SortOrder == MailSortOrder.NewestFirst) uids.Reverse(); - - if (filter.MaxCount is int maxCount && maxCount > 0 && uids.Count > maxCount) - uids = [.. uids.Take(maxCount)]; #endregion if (uids.Count == 0) return []; - + var results = new List(uids.Count); foreach (var uid in uids) @@ -97,7 +68,6 @@ public class LimilabsImapEmailService( try { - #region Read email var email = await Cache.GetOrCreateAsync( CacheKeyPrefix + uid, @@ -105,6 +75,7 @@ public class LimilabsImapEmailService( { var eml = await imap.GetMessageByUIDAsync(uid, cancellationToken); var mail = new MailBuilder().CreateFromEml(eml); + var flags = await imap.GetFlagsByUIDAsync(uid, cancellationToken); var attachments = new List(); @@ -142,19 +113,53 @@ public class LimilabsImapEmailService( TextBody = mail.Text ?? string.Empty, HtmlBody = mail.Html ?? string.Empty, Date = mail.Date ?? DateTime.MinValue, + IsSeen = flags.Contains(Flag.Seen), Attachments = attachments, }; }); #endregion Read email - if(email is not null) + if (email is null) + continue; + + if (filter.UnseenOnly && email.IsSeen) + continue; + + if (filter.SubjectContains is string subject && + !email.Subject.Contains(subject, StringComparison.OrdinalIgnoreCase)) + continue; + + if (filter.SenderContains is string sender && + !email.From.Contains(sender, StringComparison.OrdinalIgnoreCase)) + continue; + + if (filter.RecipientContains is string recipient && + !email.To.Any(t => t.Contains(recipient, StringComparison.OrdinalIgnoreCase)) && + !email.Cc.Any(c => c.Contains(recipient, StringComparison.OrdinalIgnoreCase))) + continue; + + if (filter.BodyContains is string body && + !email.TextBody.Contains(body, StringComparison.OrdinalIgnoreCase) && + !email.HtmlBody.Contains(body, StringComparison.OrdinalIgnoreCase)) + continue; + + if (filter.Uid is UidFilter uidF) { - if (filter.WithAttachments) - results.Add(email); - else - results.Add(email with { Attachments = [] }); + if (uidF.Absolute is long exactUid && email.Uid != exactUid) + continue; + + if (uidF.Min is long min && email.Uid < min) + continue; + + if (uidF.Max is long max && email.Uid > max) + continue; } + if (filter.WithAttachments) + results.Add(email); + else + results.Add(email with { Attachments = [] }); + } catch (Exception ex) { @@ -165,6 +170,10 @@ public class LimilabsImapEmailService( } await imap.CloseAsync(cancellationToken); + + if (filter.MaxCount is int maxCount && maxCount > 0 && results.Count > maxCount) + return results.Take(maxCount); + return results; } catch (Limilabs.Client.ServerException ex)