feat: sync IsRead from IMAP \Seen / Graph isRead - #501
Open
fhalamzie wants to merge 1 commit into
Open
Conversation
Add IsRead boolean column to ArchivedEmails to track read state synced from the mail provider. IMAP sync batch-fetches \Seen flags per UID batch via MailKit FetchAsync; Graph sync adds isRead to all lists. EML/MBox import defaults to false (no reliable read state in file imports). - Entity: ArchivedEmail.IsRead (bool, default false) - DbContext: HasDefaultValue(false) config - Migration: 20260806120000_MigrateV2607_4 (idempotent DO 3361622 style) - EmailCoreService: ArchiveEmailAsync gains isRead param; both raw SQL SELECT branches and reader hydration updated - ImapMailSyncService: batch FetchAsync(MessageSummaryItems.Flags), UID→isRead map passed to ArchiveEmailAsync - GraphMailSyncService: isRead added to all 4 lists - GraphMailArchiver: IsRead = message.IsRead ?? false in entity init - MailImporter: explicit IsRead = false for EML/MBox path - EmailSummaryDto + EmailDetailDto: expose IsRead via FromEntity Existing emails default to IsRead=false (migration default); a full resync updates them going forward.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an
IsReadboolean column toArchivedEmailsto track the read state synced from the mail provider.Motivation: The archive currently has no way to distinguish read from unread emails. This blocks downstream tools (search UIs, dashboards) from showing unread badges or filtering by read state.
Changes
Schema
IsRead boolean NOT NULL DEFAULT falsecolumn onArchivedEmails(idempotentDO $$ ... IF NOT EXISTSmigration, house style)HasDefaultValue(false))IMAP sync (
ImapMailSyncService)\Seenflags per UID batch viafolder.FetchAsync(batch, MessageSummaryItems.Flags | MessageSummaryItems.UniqueId)— one extra round-trip per batch, not per messageUID → isReadmap, threads it through toArchiveEmailAsyncfalseif the flag fetch failsGraph sync (
GraphMailSyncService+GraphMailArchiver)"isRead"added to all 4$selectlists (primary, reduced-fields fallback, no-filter fallback, single-message enrichment)IsRead = message.IsRead ?? falsein entity constructionEML/MBox import (
MailImporter)IsRead = false(no reliable read state in file imports)API + MCP
IsReadexposed inEmailSummaryDtoandEmailDetailDtoviaFromEntity— the REST API, MCP server, and web UI all flow through theseSearch (
EmailCoreService)e."IsRead"ArchiveEmailAsyncgains optionalbool isRead = falseparameterBackward compatibility
IsRead = false(column default). A full resync updates them going forward.ArchiveEmailAsyncsignature change is backward-compatible (new param has a default value).IF NOT EXISTS) and can be safely re-run.Testing
dotnetSDK was available locally to run a build check — the maintainer's CI will validate compilation.FetchAsync(IList<UniqueId>, MessageSummaryItems.Flags | MessageSummaryItems.UniqueId)) is standard MailKit API.isReadproperty already exists on theMicrosoft.Graph.Models.Messagetype (used atGraphMailRestorer.cs:148).Out of scope (potential follow-ups)
?isRead=true/falsefilter parameterGraphMailRestorerhardcodesIsRead = false,ImapMailRestoreralways appends withMessageFlags.Seen)