mirror of
https://github.com/Cocoanetics/SwiftMail.git
synced 2026-03-17 20:02:25 +00:00
2.3 KiB
2.3 KiB
IMAP IDLE Implementation Plan
This document outlines the steps required to implement the IMAP IDLE command in SwiftMail while providing a modern, Swift‑concurrency–friendly API.
Goals
- Provide a clean Swift interface for starting and stopping IDLE sessions.
- Deliver notifications about mailbox changes using Swift async/await.
- Ensure compatibility with existing command handling infrastructure.
Proposed Interface
public actor IMAPServer {
/// Begin an IDLE session and receive server notifications.
/// - Returns: An `AsyncStream` of unsolicited responses such as new message arrival.
public func idle() throws -> AsyncStream<IMAPServerEvent>
/// Terminate the current IDLE session.
public func done() async throws
}
IMAPServerEvent would be an enum representing common events like new messages, expunges or flag changes.
Implementation Steps
-
Capability Check
- Extend capability parsing so that
IMAPServerrecords whether the server advertisesIDLE. - Throw
IMAPError.commandNotSupportedfromidle()if the capability is missing.
- Extend capability parsing so that
-
IdleCommand and Handler
- Create
IdleCommandandIdleHandlermirroring other command structures. - The handler listens for untagged responses until a
DONEcommand is sent.
- Create
-
AsyncStream Events
idle()returns anAsyncStreamthat yieldsIMAPServerEventvalues as the handler receives server notifications.done()completes the stream and removes the handler from the pipeline.
-
Cancellation Support
- Respect task cancellation: calling
cancel()on the task runningidle()should automatically sendDONEand clean up.
- Respect task cancellation: calling
-
Documentation and Samples
- Add a new article demonstrating how to use IDLE with Swift concurrency.
- Update
Implemented.mdonce the command is fully working.
Example Usage
let events = try imapServer.idle()
for await event in events {
switch event {
case .newMessage(let uid):
print("New message with UID \(uid)")
case .expunge(let sequence):
print("Message expunged: \(sequence)")
}
}
This plan focuses on exposing IDLE through an asynchronous stream so that client code can react to server events in real time while retaining SwiftMail’s actor-based design.