Skip to main content

ImapConnection

Struct ImapConnection 

Source
pub struct ImapConnection { /* private fields */ }
Expand description

An IMAP client connection (RFC 3501 Section 2 / RFC 9051 Section 2).

Manages a single TCP (or TLS) connection to an IMAP server. All operations are async and require a caller-supplied timeout — there are no hardcoded defaults and no infinite waits.

§Connection state

RFC 3501 Section 3 defines four session states: Not Authenticated, Authenticated, Selected, and Logout. Each command method validates that the connection is in an allowed state before sending, returning Error::Protocol if not. For example, uid_fetch() requires the Selected state and will fail if called before select().

Implementations§

Source§

impl ImapConnection

Source

pub async fn append( &self, mailbox: &str, flags: &[Flag], date: Option<&str>, message: &[u8], timeout: Duration, ) -> Result<Option<(u32, u32)>, Error>

APPEND a message to a mailbox (RFC 3501 Section 6.3.11).

Handles literal synchronization: sends header with {count}\r\n, waits for + continuation, then sends literal data. Uses LITERAL+ (RFC 7888 Section 4) {count+} when the server advertises it.

Returns Some((uid_validity, uid)) when the server supports UIDPLUS (RFC 4315) and includes an [APPENDUID] response code, otherwise None.

Source

pub async fn multi_append( &self, mailbox: &str, messages: &[AppendMessage], timeout: Duration, ) -> Result<Vec<(u32, u32)>, Error>

MULTIAPPEND — append multiple messages in a single APPEND command (RFC 3502).

Sends all messages as consecutive literals in one APPEND command. Each message carries its own flags and optional internal date. The first message includes the mailbox name; subsequent messages follow immediately with their own flag/date/literal (RFC 3502 Section 3).

Checks APPENDLIMIT (RFC 7889) per message and uses LITERAL+ (RFC 7888 Section 4) when the server advertises it.

Returns a Vec<(uid_validity, uid)> extracted from [APPENDUID] response codes (RFC 4315 UIDPLUS). The vec may be empty if the server does not support UIDPLUS.

Source§

impl ImapConnection

Source

pub async fn login( &self, user: &str, pass: &str, timeout: Duration, ) -> Result<(), Error>

Authenticate with LOGIN command (RFC 3501 Section 6.2.3).

Note: LOGIN is deprecated in IMAP4rev2 (RFC 9051 Section 2.2). Prefer authenticate_plain when the server advertises AUTH=PLAIN, which is the standard SASL mechanism and works with all servers including those that don’t support LOGIN (e.g. Stalwart).

Source

pub async fn authenticate_plain( &self, user: &str, pass: &str, timeout: Duration, ) -> Result<(), Error>

Authenticate with SASL PLAIN mechanism (RFC 4616).

Constructs the PLAIN payload (\0user\0pass) and sends it via AUTHENTICATE PLAIN, using SASL-IR (RFC 4959) when available.

Source

pub async fn authenticate_xoauth2( &self, user: &str, token: &str, timeout: Duration, ) -> Result<(), Error>

Authenticate with XOAUTH2 SASL mechanism (Google-defined, not an IETF RFC).

Uses SASL-IR (RFC 4959 Section 3) if the server advertises it.

Source

pub async fn unauthenticate(&self, timeout: Duration) -> Result<(), Error>

UNAUTHENTICATE — reset to unauthenticated state (RFC 8437 Section 2).

Resets the IMAP session to Not Authenticated without closing the TLS connection. After success, the client can LOGIN or AUTHENTICATE as a different user — enabling connection pooling across users.

Clears all per-user state: selected mailbox, NOTIFY registrations, and ENABLE’d extensions. The TLS layer remains intact.

After unauthentication, issues an explicit CAPABILITY command to refresh the cached capabilities, since the server’s advertised capabilities may differ between authenticated and unauthenticated states (RFC 8437 Section 2).

§Stale events

Events buffered before this call may contain stale data from the previous session (e.g., EXISTS, EXPUNGE for a previously selected mailbox). Callers should drain the event channel before re-authenticating.

§Errors
Source

pub async fn logout(&self) -> Result<(), Error>

Graceful logout (RFC 3501 Section 6.1.3 / RFC 9051 Section 6.1.3).

Sends LOGOUT via the driver task and validates the required response sequence: the server MUST send * BYE followed by a tagged OK.

State transitions are handled by apply_side_effects inside the driver task:

  • * BYELogout (via apply_untagged)
  • Tagged OK with in_logoutLogout (via apply_tagged)

The driver sets in_logout automatically when it sees Command::Logout.

Source§

impl ImapConnection

Source

pub async fn compress(&self, timeout: Duration) -> Result<(), Error>

COMPRESS DEFLATE — negotiate and activate compression (RFC 4978 Section 4).

Sends the COMPRESS DEFLATE command. If the server accepts, wraps the current transport stream in a deflate compression layer using raw deflate (RFC 1951) as required by RFC 4978 Section 3.

After successful return, all subsequent I/O on this connection is compressed. Any already-buffered post-OK compressed bytes are preserved so the first compressed server response is not lost.

Requires the COMPRESS=DEFLATE capability. RFC 4978 Section 3 permits COMPRESS to be negotiated either before or after TLS; the effective on-the-wire layering is still compression before encryption.

The upgrade is atomic via the Poisoned sentinel pattern (I9, I10) — handled entirely by the driver task.

Source

pub async fn notify_set( &self, params: NotifySetParams, timeout: Duration, ) -> Result<(), Error>

NOTIFY SET — register interest in mailbox and message events (RFC 5465 Section 3).

Replaces any previous NOTIFY configuration. A successful NOTIFY SET has an implicit NOOP effect: the server flushes any pending changes to the selected mailbox before the tagged OK (RFC 5465 Section 3).

Notifications arrive as typed events on the event queue and can be retrieved via the event receiver.

§Errors
  • Error::MissingCapability if the server does not advertise NOTIFY.
  • Error::Protocol if the command is issued in an invalid state.
  • Error::No if the server rejects the request (e.g. [BADEVENT] for unsupported event types, RFC 5465 Section 5).
Source

pub async fn notify_none(&self, timeout: Duration) -> Result<(), Error>

NOTIFY NONE — cancel all event subscriptions (RFC 5465 Section 3).

Reverts to baseline IMAP behavior where the server only sends notifications during command processing, and only for the selected mailbox.

§Errors
Source

pub async fn enable_utf8(&self, timeout: Duration) -> Result<bool, Error>

ENABLE UTF8=ACCEPT — negotiate UTF-8 support (RFC 6855 Section 3).

Convenience wrapper around enable that sends ENABLE UTF8=ACCEPT and returns true if the server confirmed the extension, false if the server did not include it in its ENABLED response.

Must be issued in authenticated state before SELECT/EXAMINE (RFC 5161 Section 2).

Source

pub async fn enable( &self, capabilities: &[&str], timeout: Duration, ) -> Result<Vec<String>, Error>

ENABLE — request the server to activate one or more IMAP extensions (RFC 5161 Section 3 / RFC 9051 Section 6.3.1).

Sends the ENABLE command with the given capability atoms and returns the list of extensions the server actually activated (per the untagged ENABLED response).

§State requirement

RFC 5161 Section 2: ENABLE is valid only in the Authenticated state, before any mailbox is selected. Attempting to ENABLE in the Selected state returns Error::Protocol.

§Ordering constraint

RFC 5161 Section 2.2: ENABLE MUST be issued before any command that depends on the extension (e.g. SELECT with QRESYNC requires ENABLE QRESYNC first).

§Return value

Returns only the extensions the server activated in this call. The server may return a subset of the requested capabilities. Already- enabled extensions are included in the cached state but may not appear in the per-call return value.

§Snapshot timing

The enabled list in the cached state snapshot is updated by the driver after the tagged OK is processed.

Source

pub async fn namespace( &self, timeout: Duration, ) -> Result<NamespaceResponse, Error>

NAMESPACE — query the server’s namespace configuration (RFC 2342 Section 4 / RFC 9051 Section 6.3.11).

Returns the server’s personal, other-users, and shared namespace descriptors.

Requires the NAMESPACE capability or an IMAP4rev2 connection (RFC 9051 folds NAMESPACE into the base protocol).

Source

pub async fn id( &self, params: &[(&str, Option<&str>)], timeout: Duration, ) -> Result<Vec<(String, Option<String>)>, Error>

ID — exchange client/server identification (RFC 2971 Section 3.1).

Sends client identification parameters to the server and returns the server’s identification parameters. Each parameter is a (field_name, value) pair; a None value encodes as NIL on the wire (RFC 2971 Section 3.1).

Valid in any state (RFC 2971 Section 3.1).

Source

pub async fn get_metadata( &self, mailbox: &str, entries: &[&str], max_size: Option<u64>, depth: Option<&str>, timeout: Duration, ) -> Result<MetadataResult, Error>

GETMETADATA — retrieve mailbox or server metadata (RFC 5464 Section 4.2).

Fetches metadata entries for the given mailbox. Use an empty string "" for server-level metadata (RFC 5464 Section 4.2).

max_size limits the size of returned values in bytes (RFC 5464 Section 4.2.2). depth controls entry hierarchy traversal: "0" (default), "1", or "infinity" (RFC 5464 Section 4.2.2).

Requires METADATA or METADATA-SERVER capability (RFC 5464 Section 1).

Source

pub async fn set_metadata( &self, mailbox: &str, entries: &[(&str, Option<&[u8]>)], timeout: Duration, ) -> Result<(), Error>

SETMETADATA — set or delete mailbox/server metadata entries (RFC 5464 Section 4.3).

Each entry is a (name, value) pair. A None value deletes the entry (RFC 5464 Section 4.3).

Requires METADATA or METADATA-SERVER capability (RFC 5464 Section 1).

Source

pub async fn get_quota( &self, root: &str, timeout: Duration, ) -> Result<Vec<QuotaResource>, Error>

GETQUOTA — query quota resources for a quota root (RFC 2087 Section 4.2 / RFC 9208 Section 4.2).

Returns the resource limits and usage for the specified quota root.

Requires the QUOTA capability (RFC 2087 Section 5.1).

Source

pub async fn get_quota_root( &self, mailbox: &str, timeout: Duration, ) -> Result<QuotaRootResponse, Error>

GETQUOTAROOT — query quota roots for a mailbox (RFC 2087 Section 4.3 / RFC 9208 Section 4.3).

Returns the quota root names and their associated quota resources for the given mailbox.

Requires the QUOTA capability (RFC 2087 Section 5.1).

Source

pub async fn set_quota( &self, root: &str, resources: &[(&str, u64)], timeout: Duration, ) -> Result<Vec<QuotaResource>, Error>

SETQUOTA — set resource limits on a quota root (RFC 2087 Section 4.1 / RFC 9208 Section 4.1).

Each element of resources is a (resource_name, limit) pair — e.g. ("STORAGE", 51200).

Requires the QUOTASET capability (RFC 9208 Section 3.2).

Source

pub async fn set_acl( &self, mailbox: &str, identifier: &str, rights: &str, timeout: Duration, ) -> Result<(), Error>

SETACL — set access control list entries for a mailbox (RFC 4314 Section 3.1).

Sets the rights for identifier on mailbox. The rights string uses the format defined in RFC 4314 Section 2 (e.g., "+lrswipkxte" to add rights, "-d" to remove, or a bare string to replace).

Requires the ACL capability (RFC 4314 Section 1).

Source

pub async fn delete_acl( &self, mailbox: &str, identifier: &str, timeout: Duration, ) -> Result<(), Error>

DELETEACL — remove an access control list entry for a mailbox (RFC 4314 Section 3.2).

Removes all rights for identifier on mailbox.

Requires the ACL capability (RFC 4314 Section 1).

Source

pub async fn get_acl( &self, mailbox: &str, timeout: Duration, ) -> Result<Vec<AclEntry>, Error>

GETACL — retrieve the access control list for a mailbox (RFC 4314 Section 3.3).

Returns the list of identifier/rights pairs for the given mailbox.

Requires the ACL capability (RFC 4314 Section 1).

Source

pub async fn list_rights( &self, mailbox: &str, identifier: &str, timeout: Duration, ) -> Result<ListRightsResponse, Error>

LISTRIGHTS — query the set of rights grantable to an identifier on a mailbox (RFC 4314 Section 3.4).

Returns the required (always-granted) rights and the groups of optional rights that can be independently granted or revoked.

Requires the ACL capability (RFC 4314 Section 1).

Source

pub async fn my_rights( &self, mailbox: &str, timeout: Duration, ) -> Result<String, Error>

MYRIGHTS — query the logged-in user’s rights on a mailbox (RFC 4314 Section 3.5).

Returns the rights string for the current user on the given mailbox.

Requires the ACL capability (RFC 4314 Section 1).

Source§

impl ImapConnection

Source

pub fn session_state(&self) -> SessionState

Current session state (RFC 3501 §3 / RFC 9051 §3).

Returns a snapshot of the session state as last observed by the driver task. State transitions are driven by command responses (e.g., SELECT moves to Selected, LOGOUT moves to Logout).

Source

pub fn capabilities(&self) -> Vec<Capability>

Cached server capabilities (RFC 3501 §7.2.1 / RFC 9051 §7.2.1).

Returns a clone of the capability list as last observed by the driver task. Updated automatically when the server advertises new capabilities (e.g., post-STARTTLS, post-LOGIN).

Source

pub async fn noop(&self, timeout: Duration) -> Result<(), Error>

NOOP — no operation (RFC 3501 Section 6.1.2 / RFC 9051 Section 6.1.2).

Sends a NOOP command to the server. Since the NOOP command can include unsolicited responses from the server, this is the recommended method for polling for new messages or status updates.

Valid in any state (RFC 3501 Section 6.1.2). Returns an error only if the connection is closed (e.g. after LOGOUT).

Source

pub async fn check(&self, timeout: Duration) -> Result<(), Error>

CHECK — request a checkpoint of the currently selected mailbox (RFC 3501 Section 6.4.1).

Implementation-defined server action; typically flushes internal state to persistent storage.

IMAP4rev1 only. RFC 9051 removed the CHECK command from IMAP4rev2. On a pure rev2 connection, use noop instead — this method returns Error::Protocol.

Source

pub async fn capability( &self, timeout: Duration, ) -> Result<Vec<Capability>, Error>

CAPABILITY — force a capability round-trip (RFC 3501 Section 6.1.1 / RFC 9051 Section 6.1.1).

Sends an explicit CAPABILITY command and returns the server’s response. Unlike capabilities, which returns the cached capability list, this method always performs a network round-trip and updates the cached state.

Valid in any state (RFC 3501 Section 6.1.1).

Source§

impl ImapConnection

Source

pub async fn idle( &self, timeout: Duration, cancel: CancellationToken, ) -> Result<IdleEvent, Error>

Enter IDLE mode and wait for the first server event (RFC 2177).

Sends the IDLE command to the driver task, then waits for the first event, a timeout, or cancellation. On any of these, sends DONE to end the IDLE session and returns the result.

§Cancellation safety

Dropping the future returned by this method is safe — the driver task owns the stream and will eventually detect that the handle is gone (channel close). However, if the IDLE command was already sent on the wire, the connection may be left in an inconsistent state until the driver task exits. Prefer using the cancel token instead of dropping the future.

§Filtered events

Some server responses are handled transparently and do not interrupt the IDLE wait:

  • Capability changes (* OK [CAPABILITY ...]) — already applied by [ProtocolState::apply_side_effects]; observe via state_rx (RFC 3501 Section 7.2.1).
  • Informational keepalives (* OK text with no response code) — purely informational per RFC 3501 Section 7.1; servers like Dovecot send these periodically to keep the TCP connection alive.
§Arguments
  • timeout — maximum time to wait for an event.
  • cancel — cancellation token; firing this exits IDLE early.
§Errors

Returns Error::DriverGone if the driver task has exited, or any I/O or protocol error from the IDLE session.

Source§

impl ImapConnection

Source

pub async fn connect( host: &str, port: u16, tls_mode: TlsMode, timeout: Duration, ) -> Result<Self, Error>

Connect to an IMAP server.

Performs the TCP connection (with optional TLS), reads the server greeting, and parses initial capabilities per RFC 3501 Section 6.1.1.

Source

pub async fn connect_with_tls_config( host: &str, port: u16, tls_mode: TlsMode, tls_config: Arc<ClientConfig>, timeout: Duration, ) -> Result<Self, Error>

Connect with a custom TLS configuration (RFC 3501 Section 6.1.1 / RFC 9051 Section 6.1.1).

Accepts an Arc<rustls::ClientConfig> for use cases like self-signed certificates in integration tests.

Establishes the TCP/TLS connection, reads the server greeting, fetches initial capabilities, then spawns the driver task and returns a handle-based ImapConnection.

Source

pub async fn set_keepalive(&self, keepalive: TcpKeepalive) -> Result<(), Error>

Set TCP keepalive on the underlying socket (RFC 1122 Section 4.2.3.6).

Configures the operating system’s TCP keepalive probes via the driver task. This does not send any data on the IMAP wire — it sets socket options on the underlying file descriptor via setsockopt(2).

§Errors

Returns Error::Io if the setsockopt call fails. Returns Error::DriverGone if the driver task has exited.

Source

pub async fn starttls(&self, timeout: Duration) -> Result<(), Error>

Upgrade to TLS via STARTTLS (RFC 3501 Section 6.2.1).

Only valid if TlsMode::StartTls was used and connect did not already perform the upgrade. Errors if the server doesn’t advertise STARTTLS.

The upgrade is atomic via the Poisoned sentinel pattern (I9, I10) — handled entirely by the driver task.

Source

pub async fn starttls_with_config( &self, tls_config: Arc<ClientConfig>, timeout: Duration, ) -> Result<(), Error>

STARTTLS with a custom TLS configuration (RFC 3501 Section 6.2.1 / RFC 9051 Section 6.2.1).

The upgrade is atomic via the Poisoned sentinel pattern (I9, I10):

  1. Send STARTTLS, await tagged OK.
  2. Verify the wire buffer is empty (no injected bytes — B10 fix).
  3. mem::replace the reader with a Poisoned-stream reader.
  4. TLS handshake (may suspend). If it fails or the future is cancelled, the reader stays wrapping Poisoned forever.
  5. Install a fresh WireReader on the new TLS stream.
  6. Re-fetch capabilities (RFC 3501 §6.2.1).

All steps are executed by the driver task. The caller submits the upgrade command and awaits the result.

Source§

impl ImapConnection

Source

pub async fn list( &self, reference: &str, pattern: &str, timeout: Duration, ) -> Result<Vec<MailboxInfo>, Error>

LIST mailboxes (RFC 3501 Section 6.3.8).

For LIST-EXTENDED selection or return options, use ImapConnection::list_extended.

Source

pub async fn list_extended( &self, reference: &str, patterns: &[&str], selection_options: &[&str], return_options: &[&str], timeout: Duration, ) -> Result<Vec<MailboxInfo>, Error>

LIST mailboxes with RFC 5258 selection options, multiple patterns, and return options (RFC 5258 Section 3 / RFC 9051 Section 6.3.9).

Examples:

  • selection_options = &["SUBSCRIBED"]
  • return_options = &["CHILDREN"]
  • return_options = &["STATUS (MESSAGES UNSEEN)"]

On IMAP4rev1, the connection enforces capability gates for the requested options:

  • LIST-EXTENDED for RFC 5258 syntax such as selection options, multiple patterns, and all return options, including extension forms like SPECIAL-USE and STATUS (...)
  • LIST-STATUS for STATUS (...)
  • SPECIAL-USE for SPECIAL-USE
Source

pub async fn list_status( &self, reference: &str, pattern: &str, status_items: &str, timeout: Duration, ) -> Result<Vec<(MailboxInfo, Vec<StatusItem>)>, Error>

LIST with STATUS return option (RFC 5819 Section 2).

Returns mailbox information paired with STATUS data for each mailbox. status_items is the raw status items string, e.g. "MESSAGES UNSEEN". The server returns interleaved LIST and STATUS untagged responses; this method correlates them by mailbox name.

Source

pub async fn select( &self, mailbox: &str, timeout: Duration, ) -> Result<SelectedMailbox, Error>

SELECT a mailbox (RFC 3501 Section 6.3.1).

For CONDSTORE or QRESYNC options, use select_with.

Source

pub async fn select_with( &self, mailbox: &str, options: &SelectOptions, timeout: Duration, ) -> Result<SelectedMailbox, Error>

SELECT a mailbox with extension options (RFC 3501 Section 6.3.1, RFC 7162 Sections 3.1.8 and 3.2.5.2).

Pass SelectOptions::default() for a plain SELECT, or use the convenience constructors:

Source

pub async fn examine( &self, mailbox: &str, timeout: Duration, ) -> Result<SelectedMailbox, Error>

EXAMINE a mailbox (read-only SELECT, RFC 3501 Section 6.3.2).

For CONDSTORE or QRESYNC options, use examine_with.

Source

pub async fn examine_with( &self, mailbox: &str, options: &SelectOptions, timeout: Duration, ) -> Result<SelectedMailbox, Error>

EXAMINE a mailbox with extension options (RFC 3501 Section 6.3.2, RFC 7162 Sections 3.1.8 and 3.2.5.2).

Read-only variant of select_with. Pass SelectOptions::default() for a plain EXAMINE, or use the convenience constructors:

  • SelectOptions::condstore() for EXAMINE <mailbox> (CONDSTORE)
  • [SelectOptions::qresync(params)] for EXAMINE <mailbox> (QRESYNC ...)
Source

pub async fn create( &self, mailbox: &str, timeout: Duration, ) -> Result<(), Error>

CREATE a mailbox (RFC 3501 Section 6.3.3).

Source

pub async fn create_with_mailbox_id( &self, mailbox: &str, timeout: Duration, ) -> Result<Option<String>, Error>

CREATE a mailbox and return the server-assigned MAILBOXID when present (RFC 8474 Section 4.1).

RFC 8474 Section 4.1: a server advertising OBJECTID MUST include a tagged MAILBOXID response code on successful CREATE. Servers without OBJECTID support, or non-conformant servers, may omit it, so this method returns Ok(None) in that case.

Source

pub async fn create_special_use( &self, mailbox: &str, special_use: &[MailboxAttribute], timeout: Duration, ) -> Result<(), Error>

CREATE a mailbox with special-use attributes (RFC 6154 Section 3).

RFC 6154 Section 3 / Section 6 ABNF: create-param =/ "USE" SP "(" [use-attr *(SP use-attr)] ")" where use-attr = "\All" / "\Archive" / "\Drafts" / "\Flagged" / "\Junk" / "\Sent" / "\Trash" / use-attr-ext

Requires the server to advertise CREATE-SPECIAL-USE capability. RFC 6154 Section 3: “Clients MUST NOT use the USE parameter unless the server advertises the CREATE-SPECIAL-USE capability.”

Source

pub async fn create_special_use_with_mailbox_id( &self, mailbox: &str, special_use: &[MailboxAttribute], timeout: Duration, ) -> Result<Option<String>, Error>

CREATE a mailbox with special-use attributes and return the server’s MAILBOXID when present (RFC 6154 Section 3, RFC 8474 Section 4.1).

Source

pub async fn delete( &self, mailbox: &str, timeout: Duration, ) -> Result<(), Error>

DELETE a mailbox (RFC 3501 Section 6.3.4).

Source

pub async fn rename( &self, mailbox: &str, new_name: &str, timeout: Duration, ) -> Result<(), Error>

RENAME a mailbox (RFC 3501 Section 6.3.5).

Source

pub async fn subscribe( &self, mailbox: &str, timeout: Duration, ) -> Result<(), Error>

SUBSCRIBE to a mailbox (RFC 3501 Section 6.3.6).

Adds the mailbox to the server’s set of “active” or “subscribed” mailboxes returned by LSUB.

Source

pub async fn unsubscribe( &self, mailbox: &str, timeout: Duration, ) -> Result<(), Error>

UNSUBSCRIBE from a mailbox (RFC 3501 Section 6.3.7).

Source

pub async fn lsub( &self, reference: &str, pattern: &str, timeout: Duration, ) -> Result<Vec<MailboxInfo>, Error>

LSUB — list subscribed mailboxes (RFC 3501 Section 6.3.9).

Obsoleted by LIST-EXTENDED (RFC 5258) but still required for servers that don’t support \Subscribed attribute in LIST.

Source

pub async fn close(&self, timeout: Duration) -> Result<(), Error>

CLOSE the selected mailbox (RFC 3501 Section 6.4.2).

Permanently removes all messages with the \Deleted flag and returns to the authenticated state. Use unselect to deselect without expunging.

State transition to Authenticated is handled by the driver task via the in_close flag in ProtocolState::apply_tagged.

Source

pub async fn unselect(&self, timeout: Duration) -> Result<(), Error>

UNSELECT — deselect the current mailbox without expunging (RFC 3691 Section 3).

Closes the currently selected mailbox and returns to the Authenticated state, but unlike close does NOT permanently remove messages with the \Deleted flag.

Requires the UNSELECT capability or an IMAP4rev2 connection (RFC 9051 folds UNSELECT into the base protocol).

State transition to Authenticated is handled by the driver task via the in_close flag in ProtocolState::apply_tagged.

§Snapshot timing

The state snapshot transitions to Authenticated only after the tagged OK is received and processed by the driver.

Source

pub async fn status( &self, mailbox: &str, items: &str, timeout: Duration, ) -> Result<StatusResult, Error>

STATUS of a mailbox without selecting it (RFC 3501 Section 6.3.10).

items may be either a raw status item list such as "MESSAGES UNSEEN UIDNEXT" or an already parenthesized "(MESSAGES UNSEEN UIDNEXT)" list.

Returns a StatusResult that includes any ambiguous same-mailbox STATUS responses when NOTIFY is active — see its documentation for details on the inherent protocol ambiguity (RFC 5465 Section 4).

Source§

impl ImapConnection

Source

pub fn pipeline(&self) -> Pipeline<'_, ()>

Begin building a pipelined command batch (RFC 3501 §5.5).

Returns a [Pipeline] builder. Chain command methods to accumulate commands, then call [Pipeline::execute] to submit them all in one batch.

Only commands that are safe to pipeline have methods on Pipeline. State-changing commands (SELECT, STARTTLS, IDLE, LOGOUT, AUTHENTICATE, etc.) are intentionally absent — the sealed Pipelinable trait enforces this at compile time.

Source§

impl ImapConnection

Source

pub async fn fetch( &self, sequence_set: &SequenceSet, items: &[FetchAttr], timeout: Duration, ) -> Result<Vec<FetchResponse>, Error>

FETCH by sequence number (RFC 3501 Section 6.4.5).

Prefer uid_fetch for stable message references.

Source

pub async fn fetch_changed_since( &self, sequence_set: &SequenceSet, items: &[FetchAttr], mod_seq: u64, timeout: Duration, ) -> Result<Vec<FetchResponse>, Error>

FETCH with CHANGEDSINCE modifier by sequence number (RFC 7162 Section 3.1.4).

Returns only messages whose mod-sequence is greater than mod_seq. Requires the server to support CONDSTORE (RFC 7162). Prefer uid_fetch_changed_since for stable message references.

Source

pub async fn fetch_streaming( &self, sequence_set: &SequenceSet, items: &[FetchAttr], tx: Sender<Result<FetchResponse, Error>>, timeout: Duration, ) -> Result<(), Error>

FETCH streaming by sequence number (RFC 3501 Section 6.4.5).

Pushes each FetchResponse through the provided tx channel as it arrives from the server, rather than buffering the entire result set in memory. The channel is closed when the tagged OK is received.

Prefer uid_fetch_streaming for stable message references.

Source

pub async fn search( &self, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<SearchResult, Error>

SEARCH by sequence number (RFC 3501 Section 6.4.4).

Returns a SearchResult containing matching sequence numbers and an optional MODSEQ value (RFC 7162 Section 3.1.5). Prefer uid_search for stable message references. Handles both SEARCH and ESEARCH responses. For ESEARCH, the ALL uid-set is expanded into individual sequence numbers for backward compatibility.

Accepts anything that implements AsRef<str>, including &str, String, and SearchCriteria.

Source

pub async fn search_esearch( &self, criteria: impl AsRef<str>, return_opts: &[&str], timeout: Duration, ) -> Result<EsearchResponse, Error>

SEARCH with RETURN options (RFC 4731 Section 3.2).

Returns the full EsearchResponse with MIN, MAX, COUNT, and ALL fields. Requires the server to advertise the ESEARCH capability.

RFC 4731 Section 3.2: an extended SEARCH with RETURN options causes the server to return a single ESEARCH response instead of a SEARCH response.

Accepts anything that implements AsRef<str>, including &str, String, and SearchCriteria.

Source

pub async fn search_save( &self, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<(), Error>

SEARCH RETURN (SAVE) by sequence number (RFC 5182 Section 2).

Saves the search results server-side as $ for use in subsequent commands. Does not return UIDs — the results are stored on the server.

Accepts anything that implements AsRef<str>, including &str, String, and SearchCriteria.

Source

pub async fn uid_search_save( &self, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<(), Error>

UID SEARCH RETURN (SAVE) (RFC 5182 Section 2).

Saves the search results server-side as $ for use in subsequent commands. Does not return UIDs — the results are stored on the server.

Accepts anything that implements AsRef<str>, including &str, String, and SearchCriteria.

Source

pub async fn store( &self, sequence_set: &SequenceSet, operation: StoreOperation, flags: &[Flag], unchanged_since: Option<u64>, timeout: Duration, ) -> Result<StoreResult, Error>

STORE by sequence number (RFC 3501 Section 6.4.6).

Prefer uid_store for stable message references.

\Recent and \* are silently filtered per RFC 3501 Section 2.3.2 (they are not valid in STORE flag lists).

Source

pub async fn copy( &self, sequence_set: &SequenceSet, mailbox: &str, timeout: Duration, ) -> Result<CopyResult, Error>

COPY by sequence number (RFC 3501 Section 6.4.7, RFC 4315 Section 3).

Prefer uid_copy for stable message references.

On success, returns the server’s response code, which SHOULD be [COPYUID uid-validity source-uids dest-uids] per RFC 4315 Section 3.

Source

pub async fn move_messages( &self, sequence_set: &SequenceSet, mailbox: &str, timeout: Duration, ) -> Result<MoveResult, Error>

MOVE by sequence number (RFC 6851 Section 3, RFC 6851 Section 4.3).

Prefer uid_move_messages for stable message references.

Returns a MoveResult containing:

  • code: the server’s response code, typically [COPYUID ...] per RFC 6851 Section 4.3.
  • expunged: the EXPUNGE or VANISHED responses sent before the tagged OK (RFC 6851 Section 3). When QRESYNC is enabled (RFC 7162 Section 3.2.10), the server sends VANISHED instead of EXPUNGE.
Source§

impl ImapConnection

Source

pub async fn sort( &self, sort_criteria: &str, charset: &str, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<SearchResult, Error>

SORT — server-side sorting by sequence number (RFC 5256 Section 2).

Returns matching sequence numbers sorted by the given sort keys, along with an optional MODSEQ value (RFC 7162 Section 3.1.5).

sort_criteria is a space-separated list of sort keys (e.g. "REVERSE DATE SUBJECT"). The encoder wraps them in parentheses per the SORT ABNF: sort-criteria = "(" sort-key *(SP sort-key) ")".

Requires the SORT capability (RFC 5256 Section 1).

Source

pub async fn uid_sort( &self, sort_criteria: &str, charset: &str, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<SearchResult, Error>

UID SORT — server-side sorting returning UIDs (RFC 5256 Section 2).

Like sort but returns UIDs instead of sequence numbers.

Requires the SORT capability (RFC 5256 Section 1).

Source

pub async fn thread( &self, algorithm: &str, charset: &str, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<Vec<ThreadNode>, Error>

THREAD — server-side threading by sequence number (RFC 5256 Section 3).

Returns a tree of ThreadNodes representing the threading structure of matching messages.

algorithm is the threading algorithm (e.g. "REFERENCES", "ORDEREDSUBJECT"). Requires the server to advertise THREAD=<algorithm> (RFC 5256 Section 1).

Source

pub async fn uid_thread( &self, algorithm: &str, charset: &str, criteria: impl AsRef<str>, timeout: Duration, ) -> Result<Vec<ThreadNode>, Error>

UID THREAD — server-side threading returning UIDs (RFC 5256 Section 3).

Like thread but returns UIDs instead of sequence numbers in the ThreadNode tree.

Requires the server to advertise THREAD=<algorithm> (RFC 5256 Section 1).

Source§

impl ImapConnection

Source

pub async fn uid_fetch( &self, sequence_set: &SequenceSet, items: &[FetchAttr], timeout: Duration, ) -> Result<Vec<FetchResponse>, Error>

UID FETCH (RFC 3501 Section 6.4.5).

Thin wrapper around uid_fetch_streaming that collects all responses into a Vec. Logs a warning when the buffered data exceeds 10 MB to nudge callers toward the streaming variant for large result sets.

Source

pub async fn uid_fetch_changed_since( &self, sequence_set: &SequenceSet, items: &[FetchAttr], mod_seq: u64, timeout: Duration, ) -> Result<Vec<FetchResponse>, Error>

UID FETCH with CHANGEDSINCE modifier (RFC 7162 Section 3.1.4).

Returns only messages whose mod-sequence is greater than mod_seq. Requires the server to support CONDSTORE (RFC 7162).

Source

pub async fn uid_fetch_vanished( &self, sequence_set: &SequenceSet, items: &[FetchAttr], mod_seq: u64, timeout: Duration, ) -> Result<(Vec<FetchResponse>, Vec<UidRange>), Error>

UID FETCH with CHANGEDSINCE and VANISHED modifiers (RFC 7162 Section 3.2.6).

Issues UID FETCH <set> (<items>) (CHANGEDSINCE <mod_seq> VANISHED). The server returns VANISHED (EARLIER) responses for UIDs in the requested set that have been expunged since mod_seq, plus regular FETCH responses for messages whose flags changed.

VANISHED (EARLIER) UIDs are defensively filtered to only include UIDs within the requested sequence_set — non-conformant servers may return UIDs outside the set (RFC 7162 Section 3.2.6). When the sequence set contains $ (RFC 5182 search result reference), filtering is best-effort (skipped, since $ cannot be resolved client-side).

Requires:

  • QRESYNC must have been ENABLEd (RFC 7162 Section 3.2.6).
  • The mailbox must be selected.
Source

pub async fn uid_fetch_streaming( &self, sequence_set: &SequenceSet, items: &[FetchAttr], tx: Sender<Result<FetchResponse, Error>>, timeout: Duration, ) -> Result<(), Error>

UID FETCH streaming (RFC 3501 Section 6.4.5).

Pushes each FetchResponse through the provided tx channel as it arrives from the server, rather than buffering the entire result set in memory. The channel is closed when the tagged OK is received (the consumer drops tx in [finalize]).

Callers should read from the corresponding rx concurrently or drain it after this method returns — responses are sent via try_send, so the channel buffer must be large enough to hold in-flight data.

Prefer this over uid_fetch when the result set may be large enough to cause memory pressure.

UID SEARCH (RFC 3501 Section 6.4.4).

criteria is the raw IMAP search criteria string, e.g. "UNSEEN" or "FROM \"alice\" SINCE 1-Mar-2026". Returns a SearchResult containing matching UIDs and an optional MODSEQ value (RFC 7162 Section 3.1.5). Handles both SEARCH and ESEARCH responses. For ESEARCH, the ALL uid-set is expanded into individual UIDs for backward compatibility.

Accepts anything that implements AsRef<str>, including &str, String, and SearchCriteria.

Source

pub async fn uid_search_esearch( &self, criteria: impl AsRef<str>, return_opts: &[&str], timeout: Duration, ) -> Result<EsearchResponse, Error>

UID SEARCH with RETURN options (RFC 4731 Section 3.2).

Returns the full EsearchResponse with MIN, MAX, COUNT, and ALL fields. Requires the server to advertise the ESEARCH capability.

RFC 4731 Section 3.2: an extended SEARCH with RETURN options causes the server to return a single ESEARCH response instead of a SEARCH response.

Accepts anything that implements AsRef<str>, including &str, String, and SearchCriteria.

Source

pub async fn uid_store( &self, sequence_set: &SequenceSet, operation: StoreOperation, flags: &[Flag], unchanged_since: Option<u64>, timeout: Duration, ) -> Result<StoreResult, Error>

UID STORE (RFC 3501 Section 6.4.6).

If unchanged_since is Some, uses CONDSTORE (RFC 7162 Section 3.1.3) to avoid overwriting concurrent flag changes.

\Recent and \* are silently filtered per RFC 3501 Section 2.3.2 (they are not valid in STORE flag lists).

Source

pub async fn uid_move_messages( &self, sequence_set: &SequenceSet, mailbox: &str, timeout: Duration, ) -> Result<MoveResult, Error>

UID MOVE (RFC 6851 Section 3, RFC 9051 Appendix E item 2).

Falls back to COPY + Store \Deleted + UID EXPUNGE (RFC 6851 Section 4) when the server doesn’t advertise the MOVE capability and isn’t IMAP4rev2. The fallback requires UIDPLUS (RFC 4315) — plain EXPUNGE is never used because it can delete unrelated \Deleted messages (data-loss risk).

Returns a MoveResult containing:

  • code: the server’s response code, typically [COPYUID ...] per RFC 6851 Section 4.3 / RFC 4315 Section 3.
  • expunged: the EXPUNGE or VANISHED responses (RFC 6851 Section 3). When QRESYNC is enabled (RFC 7162 Section 3.2.10), the server sends VANISHED instead of EXPUNGE.
Source

pub async fn uid_copy( &self, sequence_set: &SequenceSet, mailbox: &str, timeout: Duration, ) -> Result<CopyResult, Error>

UID COPY (RFC 3501 Section 6.4.7, RFC 4315 Section 3).

On success, returns the server’s response code, which SHOULD be [COPYUID uid-validity source-uids dest-uids] per RFC 4315 Section 3.

Source

pub async fn uid_expunge( &self, sequence_set: &SequenceSet, timeout: Duration, ) -> Result<ExpungeResult, Error>

UID EXPUNGE (RFC 4315 UIDPLUS / RFC 9051 Section 6.4.9).

Source

pub async fn expunge(&self, timeout: Duration) -> Result<ExpungeResult, Error>

EXPUNGE (RFC 3501 Section 6.4.3 / RFC 7162 Section 3.2.10).

Without QRESYNC, returns ExpungeResult::Expunged with the sequence numbers of removed messages (* n EXPUNGE, RFC 3501 Section 7.4.1).

After ENABLE QRESYNC (RFC 7162 Section 3.2.10), the server sends VANISHED responses instead of EXPUNGE, and this method returns ExpungeResult::Vanished with UID ranges.

Source§

impl ImapConnection

Source

pub async fn drain_events(&self) -> Vec<TypedEvent>

Drain all pending events from the typed event queue.

Returns every [TypedEvent] that has accumulated since the last call to drain_events or next_event. Non-blocking — returns an empty Vec when no events are pending.

This is the primary way to observe asynchronous server data (ALERTs, EXISTS/EXPUNGE, NOTIFY events, BYE, etc.) outside of an active command or IDLE session.

Source

pub async fn next_event( &self, timeout: Duration, ) -> Result<Option<TypedEvent>, Error>

Wait for the next event from the typed event queue, with a timeout.

Returns Ok(Some(event)) when an event arrives, Ok(None) when timeout elapses without an event, or Err(Error::DriverGone) when the driver task has exited (channel closed).

RFC 3501 §5.3: servers may send untagged data at any time. This method surfaces that data as [TypedEvent]s, enabling callers to react to mailbox state changes, ALERTs, and NOTIFY events.

Trait Implementations§

Source§

impl Debug for ImapConnection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Prints connection metadata useful for logging and diagnostics, without exposing internal stream state or buffers.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more