feat(imap): add markAsSeen option to fetch queries and interface

- IImapEmailService.FetchEmailsAsync / FetchEmailByUidAsync now accept
  a bool markAsSeen = true parameter
- FetchEmailsQuery and FetchEmailByUidQuery expose MarkAsSeen { init; } = true
- markAsSeen=true  uses BODY[]      (server sets \\Seen, legacy-compatible)
- markAsSeen=false uses BODY.PEEK[] (non-destructive read, flag untouched)
This commit is contained in:
2026-08-11 15:51:57 +02:00
parent 962cb52e0b
commit e840d026aa
3 changed files with 23 additions and 0 deletions

View File

@@ -13,10 +13,15 @@ public interface IImapEmailService
/// </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="filter">Filter to apply when fetching emails.</param> /// <param name="filter">Filter to apply when fetching emails.</param>
/// <param name="markAsSeen">
/// When <see langword="true"/> (default), fetched messages are marked as <c>\Seen</c> on the server.
/// Set to <see langword="false"/> for a non-destructive read (uses <c>BODY.PEEK</c> internally).
/// </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,
MailSearchFilter filter, MailSearchFilter filter,
bool markAsSeen = true,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
/// <summary> /// <summary>
@@ -30,11 +35,16 @@ public interface IImapEmailService
/// <summary> /// <summary>
/// Fetches a single email by its UID. /// Fetches a single email by its UID.
/// </summary> /// </summary>
/// <param name="markAsSeen">
/// When <see langword="true"/> (default), the message is marked as <c>\Seen</c> on the server.
/// Set to <see langword="false"/> for a non-destructive read.
/// </param>
Task<ReceivedEmailContext?> FetchEmailByUidAsync( Task<ReceivedEmailContext?> FetchEmailByUidAsync(
EmailAccountDto account, EmailAccountDto account,
long uid, long uid,
string folder = "INBOX", string folder = "INBOX",
bool withAttachments = false, bool withAttachments = false,
bool markAsSeen = true,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
/// <summary> /// <summary>

View File

@@ -36,6 +36,11 @@ public record FetchEmailByUidQuery : IRequest<ReceivedEmailContext?>
/// When <see langword="true"/>, attachment data is included in the result. /// When <see langword="true"/>, attachment data is included in the result.
/// </summary> /// </summary>
public bool WithAttachments { get; init; } = false; public bool WithAttachments { get; init; } = false;
/// <summary>
/// When <see langword="true"/> (default), the message is marked as <c>\Seen</c> on the server.
/// Set to <see langword="false"/> for a non-destructive peek.
/// </summary>
public bool MarkAsSeen { get; init; } = true;
} }
public class FetchEmailByUidQueryHandler( public class FetchEmailByUidQueryHandler(
@@ -57,6 +62,7 @@ public class FetchEmailByUidQueryHandler(
(long)request.Uid!, (long)request.Uid!,
request.Folder, request.Folder,
request.WithAttachments, request.WithAttachments,
request.MarkAsSeen,
cancellationToken); cancellationToken);
} }
} }

View File

@@ -21,6 +21,12 @@ public record FetchEmailsQuery : IRequest<IEnumerable<ReceivedEmailContext>>
/// Mail query used to filter and limit the emails retrieved. /// Mail query used to filter and limit the emails retrieved.
/// </summary> /// </summary>
public MailSearchFilter Mail { get; init; } = new(); public MailSearchFilter Mail { get; init; } = new();
/// <summary>
/// When <see langword="true"/> (default), fetched messages are marked as <c>\Seen</c> on the server.
/// Set to <see langword="false"/> for a non-destructive peek.
/// </summary>
public bool MarkAsSeen { get; init; } = true;
} }
public class FetchEmailsQueryHandler( public class FetchEmailsQueryHandler(
@@ -40,6 +46,7 @@ public class FetchEmailsQueryHandler(
return await ImapService.FetchEmailsAsync( return await ImapService.FetchEmailsAsync(
account, account,
request.Mail, request.Mail,
request.MarkAsSeen,
cancellationToken); cancellationToken);
} }
} }