Refactor IMAP email fetching to use SearchFilter
Replaced individual parameters (`folder`, `unseenOnly`, `maxCount`) in `IImapEmailService` with a consolidated `SearchFilter` object to simplify method signatures and improve maintainability. Renamed `MailQuery` to `SearchFilter` in `FetchEmailsQuery` for better clarity. Updated `FetchEmailsQueryHandler` and `LimilabsImapEmailService` to use the new `SearchFilter` object, ensuring consistent handling of folder selection, unread message filtering, and message count limits. Improved logging in `LimilabsImapEmailService` to reflect the updated `SearchFilter` structure.
This commit is contained in:
@@ -11,15 +11,11 @@ public interface IImapEmailService
|
|||||||
/// Fetches emails from the specified mailbox folder.
|
/// Fetches emails from the specified mailbox folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="account">Account whose IMAP settings will be used.</param>
|
/// <param name="account">Account whose IMAP settings will be used.</param>
|
||||||
/// <param name="folder">Mailbox folder name (e.g. "INBOX"). Defaults to INBOX.</param>
|
/// <param name="filter">Filter to apply when fetching emails.</param>
|
||||||
/// <param name="unseenOnly">When <see langword="true"/> returns only unread messages.</param>
|
|
||||||
/// <param name="maxCount">Maximum number of messages to retrieve (most-recent first). 0 = unlimited.</param>
|
|
||||||
/// <param name="cancellationToken">Cancellation token.</param>
|
/// <param name="cancellationToken">Cancellation token.</param>
|
||||||
Task<IEnumerable<ReceivedEmailContext>> FetchEmailsAsync(
|
Task<IEnumerable<ReceivedEmailContext>> FetchEmailsAsync(
|
||||||
EmailAccountDto account,
|
EmailAccountDto account,
|
||||||
string folder = "INBOX",
|
FetchEmailsQuery.SearchFilter filter,
|
||||||
bool unseenOnly = false,
|
|
||||||
int maxCount = 50,
|
|
||||||
CancellationToken cancellationToken = default);
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ public record FetchEmailsQuery : IRequest<IEnumerable<ReceivedEmailContext>>
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mail query used to filter and limit the emails retrieved.
|
/// Mail query used to filter and limit the emails retrieved.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MailQuery Mail { get; init; } = new();
|
public SearchFilter Mail { get; init; } = new();
|
||||||
|
|
||||||
public record MailQuery
|
public record SearchFilter
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mailbox folder to read from (default: "INBOX").
|
/// Mailbox folder to read from (default: "INBOX").
|
||||||
@@ -56,9 +56,7 @@ public class FetchEmailsQueryHandler(
|
|||||||
|
|
||||||
return await ImapService.FetchEmailsAsync(
|
return await ImapService.FetchEmailsAsync(
|
||||||
account,
|
account,
|
||||||
request.Mail.Folder,
|
request.Mail,
|
||||||
request.Mail.UnseenOnly,
|
|
||||||
request.Mail.MaxCount,
|
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,28 +25,26 @@ public class LimilabsImapEmailService(
|
|||||||
// Public API
|
// Public API
|
||||||
public async Task<IEnumerable<ReceivedEmailContext>> FetchEmailsAsync(
|
public async Task<IEnumerable<ReceivedEmailContext>> FetchEmailsAsync(
|
||||||
EmailAccountDto account,
|
EmailAccountDto account,
|
||||||
string folder = "INBOX",
|
FetchEmailsQuery.SearchFilter filter,
|
||||||
bool unseenOnly = false,
|
|
||||||
int maxCount = 50,
|
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
using var imap = new Imap();
|
using var imap = new Imap();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ConnectAndAuthenticateAsync(imap, account);
|
await ConnectAndAuthenticateAsync(imap, account);
|
||||||
await SelectFolderAsync(imap, folder);
|
await SelectFolderAsync(imap, filter.Folder);
|
||||||
|
|
||||||
// Get UIDs to fetch
|
// Get UIDs to fetch
|
||||||
List<long> uids = unseenOnly
|
List<long> uids = filter.UnseenOnly
|
||||||
? [.. await imap.SearchAsync(Flag.Unseen, cancellationToken)]
|
? [.. await imap.SearchAsync(Flag.Unseen, cancellationToken)]
|
||||||
: [.. await imap.GetAllAsync(cancellationToken)];
|
: [.. await imap.GetAllAsync(cancellationToken)];
|
||||||
|
|
||||||
// Most-recent first; honour maxCount
|
// Most-recent first; honour maxCount
|
||||||
uids.Reverse();
|
uids.Reverse();
|
||||||
if (maxCount > 0 && uids.Count > maxCount)
|
if (filter.MaxCount > 0 && uids.Count() > filter.MaxCount)
|
||||||
uids = [.. uids.Take(maxCount)];
|
uids = [.. uids.Take(filter.MaxCount)];
|
||||||
|
|
||||||
var results = new List<ReceivedEmailContext>(uids.Count);
|
var results = new List<ReceivedEmailContext>(uids.Count());
|
||||||
|
|
||||||
foreach (var uid in uids)
|
foreach (var uid in uids)
|
||||||
{
|
{
|
||||||
@@ -62,7 +60,7 @@ public class LimilabsImapEmailService(
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogWarning(ex, "Failed to fetch IMAP message UID={Uid} from folder {Folder}. Skipping.", uid, folder);
|
logger.LogWarning(ex, "Failed to fetch IMAP message UID={Uid} from folder {Folder}. Skipping.", uid, filter.Folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user