ImapFlow

repository·master·Indexed 19 days ago

https://github.com/postalsys/imapflow

A modern, promise-based IMAP client library for Node.js featuring an async/await API and automatic handling of IMAP extensions such as CONDSTORE, QRESYNC, IDLE, and COMPRESS. It supports message streaming via async iterators, built-in mailbox locking for concurrent access, TypeScript, and specialized support for Gmail labels and raw searches.

Tokens
11.1K
Snippets
34
Records
48
Agent score
69%

What's inside imapflow

  1. What is ImapFlow?

    master
    ImapFlow is a modern, easy-to-use IMAP client library for Node.js. It features an async/await API, automatic handling of IMAP extensions (like CONDSTORE, QRESYNC, IDLE, and COMPRESS), and supports message streaming via async iterators. It also includes built-in mailbox locking for safe concurrent access, TypeScript support, proxy support (SOCKS and HTTP CONNECT), and specialized support for Gmail (labels and raw search via X-GM-EXT-1).
  2. Quick start with ImapFlow

    master

    ImapFlow provides a promise-based API for interacting with IMAP servers. To use it, instantiate ImapFlow with connection details, call .connect(), and use mailbox locks to ensure safe concurrent access to mailboxes. Always release locks in a finally block to prevent deadlocks.

    const { ImapFlow } = require('imapflow');
    
    const client = new ImapFlow({
        host: 'imap.example.com',
        port: 993,
        secure: true,
        auth: {
            user: 'user@example.com',
            pass: 'password'
        }
    });
    
    const main = async () => {
        await client.connect();
    
        let lock = await client.getMailboxLock('INBOX');
        try {
            // fetch latest message
            let message = await client.fetchOne(client.mailbox.exists, { source: true });
            console.log(message.source.toString());
    
            // list subjects for all messages
            for await (let message of client.fetch('1:*', { envelope: true })) {
                console.log(`${message.uid}: ${message.envelope.subject}`);
            }
        } finally {
            // always release the lock
            lock.release();
        }
    
        await client.logout();
    };
    
    main().catch(console.error);
  3. Enable IMAP extensions and compression

    master

    ImapFlow automatically negotiates several extensions during the session startup to optimize performance:

    • Compression: If supported by the server and not explicitly disabled via disableCompression: true, ImapFlow negotiates the COMPRESS command and uses zlib DEFLATE (RFC 4978) for both incoming and outgoing data.
    • Automatic Extension Enabling: ImapFlow attempts to enable extensions like CONDSTORE, UTF8=ACCEPT, and QRESYNC (if qresync: true is in options). It also attempts to enable IMAP4rev2 by default.
    • IMAP4rev2 Fallback: If a server rejects IMAP4rev2 but supports other extensions, ImapFlow will retry the ENABLE command without IMAP4rev2 to ensure other features are not lost.
  4. Handle socket timeouts and IDLE recovery

    master

    ImapFlow uses an inactivity watchdog to monitor the socket. If a socket timeout occurs:

    • During IDLE: ImapFlow attempts to recover the connection by sending a NOOP command and then returning to the IDLE state. If recovery fails, the connection is closed.
    • During other operations: The connection is closed immediately, and an error with code: 'ETIMEOUT' is emitted.

    This mechanism ensures that long-running IDLE sessions are maintained or gracefully recovered if the transport becomes inactive.

  5. How mailbox locks work and how to release them

    master

    A mailbox lock provides exclusive access to a specific mailbox path. When you call getMailboxLock(), the request is queued. Once the previous lock is released, the next lock in the queue is granted.

    When a lock is granted, it returns an object containing the path and a release function. Calling release() allows the next queued operation to proceed.

    Diagnostic Warning: If a lock is held longer than the configured maxLockHoldTime, ImapFlow will emit a warning log indicating the lock was held for a long time. This is controlled by the maxLockHoldTime option in the client configuration.

    let lock = await client.getMailboxLock('INBOX');
    // ... perform operations ...
    lock.release();
  6. Handle MS365/Office 365 throttling errors

    master

    When interacting with Microsoft 365 (Office 365) servers, the server may return a BAD response indicating rate limiting. ImapFlow detects this and parses the suggested backoff time from the response text (e.g., "tag BAD Request is throttled. Suggested Backoff Time: 92415 milliseconds").

    If throttling is detected, the command will fail with an error containing:

    • code: ETHROTTLE
    • throttleReset: The number of milliseconds to wait before retrying.

    Note: ImapFlow caps the automatic wait at 5 minutes to prevent connections from hanging indefinitely.

  7. Handle connection errors and BYE reasons

    master

    When a connection is lost or closed by the server, ImapFlow may emit a close event. If the server sent an untagged BYE response, the error thrown during subsequent operations or the connection teardown will include a reason property containing the server's explanation (e.g., "Too many connections").

    Common error codes include:

    • NoConnection: The connection is not available.
    • GREETING_TIMEOUT: Failed to receive a greeting from the server within the configured greetingTimeout.
  8. Manage mailbox locks with getMailboxLock()

    master

    To perform operations on a mailbox that require exclusive access (to prevent state conflicts), use getMailboxLock(path). This returns a MailboxLockObject which contains a release function. You must call release() to free the mailbox for other operations.

    Important: Always use a try...finally block to ensure the lock is released even if an error occurs during your operations.

    let lock = await client.getMailboxLock('INBOX');
    try {
      // perform mailbox operations here
    } finally {
      // ensure the lock is released
      lock.release();
    }
  9. Configure the ImapFlow client connection options

    master

    When instantiating ImapFlow, you can provide an options object to configure the connection, authentication, and behavior.

    Connection & Security

    • host: Hostname of the IMAP server (defaults to 'localhost').
    • port: Port number (defaults to 993 if secure: true, otherwise 143).
    • secure: If true, establishes a direct TLS connection. If false, attempts to upgrade via STARTTLS.
    • doSTARTTLS:
      • true: Forces STARTTLS upgrade. Fails if not supported.
      • false: Disables STARTTLS entirely.
      • undefined (default): Attempts STARTTLS if supported; otherwise continues unencrypted.
    • servername: Server name for SNI or when using an IP address as host.
    • proxy: Proxy URL (supports http://, https://, socks://, socks4://, socks4a://, socks5://).
    • connectionTimeout: Max time (ms) for DNS, proxy, and TCP/TLS handshake (default: 90000).
    • greetingTimeout: Max time (ms) to wait for server greeting (default: 16000).
    • socketTimeout: Max inactivity period (ms) before terminating connection (default: 300000).

    Authentication

    • auth.user: Username.
    • auth.pass: Password.
    • auth.accessToken: OAuth2 access token.
    • auth.loginMethod: Optional method (e.g., "LOGIN", "AUTH=LOGIN", "AUTH=PLAIN").
    • auth.authzid: Authorization identity for SASL PLAIN (admin impersonation).

    Advanced & Extensions

    • qresync: Enables QRESYNC support.
    • disableBinary: If true, ignores the BINARY extension.
    • disableIMAP4rev2: If true, opts out of IMAP4rev2 mode.
    • maxIdleTime: Breaks and restarts IDLE every X milliseconds.
    • missingIdleCommand: Command to use if server lacks IDLE (default: "NOOP").
    • disableAutoIdle: If true, does not start IDLE automatically.
    • disableAutoEnable: If true, does not automatically enable supported extensions.
    • disableCompression: If true, does not use COMPRESS=DEFLATE.
  10. Configure ImapFlow connection options

    master

    When instantiating the ImapFlow client, you provide an ImapFlowOptions object to define connection, authentication, and protocol behavior.

    Key configuration areas include:

    • Connection: host, port, secure (use true for TLS), and proxy (supports http:, https:, socks:, socks4:, socks4a:, socks5:).
    • Authentication: The auth object requires user and either pass (for regular auth) or accessToken (for OAuth2). You can also specify loginMethod (e.g., 'LOGIN', 'AUTH=LOGIN', 'AUTH=PLAIN') and authzid for SASL PLAIN delegation.
    • Timeouts: Control connection lifecycle with connectionTimeout (DNS/TCP/TLS handshake), greetingTimeout, and socketTimeout.
    • Protocol Extensions: Enable or disable specific behaviors like qresync, disableCompression, disableBinary, or disableIMAP4rev2.
    const client = new ImapFlow({
        host: 'imap.example.com',
        port: 993,
        secure: true,
        auth: {
            user: 'user@example.com',
            pass: 'your-password'
        }
    });
  11. Configure STARTTLS and secure connections

    master

    ImapFlow supports two ways to establish a secure connection:

    1. Direct TLS: Set secure: true in your configuration. This establishes a TLS connection immediately upon connecting.
    2. STARTTLS: Set doSTARTTLS: true in your configuration. This starts a plaintext connection and then upgrades it to TLS using the IMAP STARTTLS command.

    Important Constraints:

    • You cannot set both secure: true and doSTARTTLS: true. Doing so will throw a misconfiguration error.
    • If doSTARTTLS: true is set and the server does not support the STARTTLS capability, the connection attempt will fail.