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.
This commit is contained in:
@@ -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<ICriterion> 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<ReceivedEmailContext>(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<EmailAttachmentContext>();
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user