Skip to content

Add ENABLE and QRESYNC mailbox synchronization - #236

Open
thatjuan wants to merge 4 commits into
Cocoanetics:mainfrom
thatjuan:feature/enable-qresync
Open

thatjuan wants to merge 4 commits into
Cocoanetics:mainfrom
thatjuan:feature/enable-qresync

Conversation

@thatjuan

@thatjuan thatjuan commented Sep 17, 2026

Copy link
Copy Markdown

Summary

Add support for incremental mailbox synchronization using IMAP ENABLE and QRESYNC.

  • Add public ENABLE APIs for primary and named connections, validating capability atoms before sending.
  • Add QRESYNC mailbox selection that returns selection metadata, historical and live vanished UIDs, and complete flag replacements.
  • Account for live deletions in the returned message count and exclude deleted UIDs from flag updates.
  • Preserve HIGHESTMODSEQ in mailbox selections and support storing checkpoints with Codable.
  • Handle connection replacement, capability checks, rejected selections, and CLOSED response boundaries, clearing old mailbox state for ordinary and QRESYNC selections.
  • Document the QRESYNC workflow, checkpoint validation, fallback requirements, and supported scope.

Testing

  • swift build
  • swift test (494 tests across 72 suites)
  • Strict SwiftLint (328 files, zero violations)

@odrobnik odrobnik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for four correctness/security defects in the new ENABLE/QRESYNC paths plus one contradictory public documentation entry. UIDONLY flag updates and concurrent VANISHED deletions can be silently lost, arbitrary Capability strings can inject extra IMAP commands, and ordinary SELECT does not honor the CLOSED mailbox boundary after QRESYNC is enabled. No builds or tests were run, per review instructions.

One review with 5 findings — those on changed lines are detailed in inline comments:

  • HIGH Sources/SwiftMail/IMAP/IMAP/Handler/ResyncSelectHandler.swift:83
  • HIGH Sources/SwiftMail/IMAP/IMAP/Handler/ResyncSelectHandler.swift:68
  • MEDIUM Sources/SwiftMail/IMAP/IMAP/Commands/EnableCommand.swift:12
  • MEDIUM Sources/SwiftMail/IMAP/IMAP/Handler/SelectHandler.swift:56
  • LOW README.md — The public capability matrix still marks both ENABLE and QRESYNC as unsupported by IMAPServer even though this PR adds and documents those APIs. A user relying on the primary README will incorrectly conclude the new synchronization feature is unavailable.

To unblock the merge, address every finding: react with 👍 if it is accurate (👎 if not), reply with a brief comment on what was fixed, and mark the item as resolved.

Comment thread Sources/SwiftMail/IMAP/IMAP/Handler/ResyncSelectHandler.swift Outdated
Comment thread Sources/SwiftMail/IMAP/IMAP/Handler/ResyncSelectHandler.swift
Comment thread Sources/SwiftMail/IMAP/IMAP/Commands/EnableCommand.swift
Comment thread Sources/SwiftMail/IMAP/IMAP/Handler/SelectHandler.swift
@thatjuan

Copy link
Copy Markdown
Author

Thanks for the review, @odrobnik. Those all make sense to me. I’ve pushed fixes in 23fdb8f and 3d15849:

  • Preserve the UID from startUID so UIDONLY flag updates reach changedFlags.
  • Retain live and historical VANISHED sets separately, update message counts in response order, and exclude deleted UIDs from flag updates.
  • Clear old mailbox state at CLOSED for both ordinary and QRESYNC selections.
  • Validate ENABLE capability atoms before sending to prevent command injection.
  • Corrected the README capability matrix and RFC reference, and clarify deletion handling and checkpoint fallback in DocC.

I also added tests for these cases. The local build, all tests, and strict SwiftLint pass..

@thatjuan
thatjuan requested a review from odrobnik September 18, 2026 17:20
@odrobnik

Copy link
Copy Markdown
Contributor

@thatjuan you have to resolve the review comments for a re-review to occur

@odrobnik

Copy link
Copy Markdown
Contributor

MissionControl review timed out for head 3d1584939bcb. Auto-merge remains blocked; human review is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants