← Back to Skills Marketplace
openlark

imapflow

by OpenLark · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ✓ Security Clean
8
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install imapflow
Description
Modern Node.js IMAP client library (imapflow) for email integration.Covers authentication, mailbox locking, streaming fetches, async iterators, reconnection...
README (SKILL.md)

\r \r

ImapFlow\r

\r

Overview\r

\r ImapFlow is a modern, promise-based IMAP client for Node.js. It auto-detects and handles IMAP extensions (CONDSTORE, QRESYNC, IDLE, COMPRESS, etc.) so the same code works across servers.\r \r Key features: async/await API, async iterators for message streaming, built-in mailbox locking, TypeScript support, SOCKS/HTTP proxy support, Gmail X-GM-EXT-1 support.\r \r

Trigger Scene\r

\r Use when building email features: connecting to IMAP servers, fetching/reading emails, searching mailboxes, managing folders, monitoring new messages via IDLE, working with Gmail labels and Gmail-specific extensions, or any IMAP-based email automation. \r \r

Quick Start\r

\r

const { ImapFlow } = require('imapflow');\r
\r
const client = new ImapFlow({\r
    host: 'imap.example.com',\r
    port: 993,\r
    secure: true,\r
    auth: { user: '[email protected]', pass: 'password' }\r
});\r
\r
await client.connect();\r
\r
let lock = await client.getMailboxLock('INBOX');\r
try {\r
    // Fetch latest message\r
    let msg = await client.fetchOne(client.mailbox.exists, { source: true });\r
    console.log(msg.source.toString());\r
\r
    // Stream all messages\r
    for await (let msg of client.fetch('1:*', { envelope: true })) {\r
        console.log(`${msg.uid}: ${msg.envelope.subject}`);\r
    }\r
} finally {\r
    lock.release();\r
}\r
\r
await client.logout();\r
```\r
\r
## Core Tasks\r
\r
### 1. Connecting\r
\r
```js\r
const client = new ImapFlow({\r
    host: 'imap.example.com',\r
    port: 993,\r
    secure: true,\r
    auth: { user: '[email protected]', pass: 'password' }\r
});\r
await client.connect();\r
```\r
\r
**Provider-specific configs** → See [references/connection.md](references/connection.md) for Gmail, Outlook, Yahoo, iCloud, and other common providers.\r
\r
**OAuth2 / XOAUTH2:**\r
```js\r
auth: {\r
    user: '[email protected]',\r
    accessToken: 'ya29.xxx...'\r
}\r
```\r
\r
**Common options:**\r
- `logger`: Pass a logger object (`console`, pino, etc.) for debug output. Set `logger: false` to disable.\r
- `emitLogs`: Set `true` to emit 'log' events instead of using a logger.\r
- `clientInfo`: Custom client identification `{ name: 'myapp', version: '1.0.0' }`.\r
- `disableAutoIdle`: Disable automatic IDLE when mailbox is selected.\r
\r
**Disconnect:** Call `client.logout()` for graceful disconnect. Handle `client.close()` for abrupt close.\r
\r
### 2. Fetching Messages\r
\r
**Always acquire a mailbox lock before fetching:**\r
```js\r
let lock = await client.getMailboxLock('INBOX');\r
try {\r
    // ... fetch operations ...\r
} finally {\r
    lock.release();\r
}\r
```\r
\r
**Fetch one message:**\r
```js\r
let msg = await client.fetchOne('*', { source: true });\r
// or by sequence number: client.fetchOne(42, { source: true })\r
// or by UID (append `uid` flag):\r
let msg = await client.fetchOne('12345', { uid: true, source: true });\r
```\r
\r
**Fetch query options** (what data to retrieve — choose only what you need):\r
- `source` — Full RFC822 message source (as Buffer)\r
- `envelope` — Parsed envelope (subject, from, to, date, message-id)\r
- `bodyStructure` — MIME structure tree\r
- `flags` — Array of flags (\\Seen, \\Answered, etc.)\r
- `internalDate` — Internal server date\r
- `size` — Message size in bytes\r
- `uid` — UID (always included)\r
- `threadId` — THREAD=ORDEREDSUBJECT reference (Gmail)\r
- `labels` — Gmail labels (X-GM-LABELS)\r
- `headers` — Raw headers as Buffer\r
- `bodyParts` — Array of MIME part paths to fetch, e.g. `['1.1', '1.2']`\r
\r
**Stream/iterate messages:**\r
```js\r
// Range: sequence numbers\r
for await (let msg of client.fetch('1:100', { envelope: true, flags: true })) {\r
    console.log(`${msg.seq}: ${msg.envelope.subject}`);\r
}\r
\r
// All messages: '1:*'\r
for await (let msg of client.fetch('1:*', { envelope: true })) { /* ... */ }\r
\r
// By UID range\r
for await (let msg of client.fetch('1000:2000', { uid: true, envelope: true })) { /* ... */ }\r
```\r
\r
**Fetch specific body parts:**\r
```js\r
let msg = await client.fetchOne('*', {\r
    bodyParts: ['1.1', '1.2'],  // MIME part paths\r
    source: true\r
});\r
// msg.bodyParts.get('1.1') → Buffer\r
// msg.text.toString() → decoded text content\r
```\r
\r
**Download attachments:**\r
```js\r
let msg = await client.fetchOne('*', { source: true, bodyStructure: true });\r
for (let attachment of msg.attachments) {\r
    let buf = await client.download(msg.uid, attachment.part, { uid: true });\r
    // buf contains the attachment data\r
}\r
```\r
\r
**Common envelope fields:** `msg.envelope.subject`, `msg.envelope.from[0].address`, `msg.envelope.to[0].address`, `msg.envelope.date`, `msg.envelope.messageId`, `msg.envelope.inReplyTo`.\r
\r
### 3. Searching\r
\r
```js\r
let lock = await client.getMailboxLock('INBOX');\r
try {\r
    // Simple search\r
    let list = await client.search({ unseen: true });\r
\r
    // Complex query\r
    let list = await client.search({\r
        from: '[email protected]',\r
        subject: 'invoice',\r
        seen: false,\r
        since: new Date('2024-01-01'),\r
        before: new Date('2024-12-31'),\r
        larger: 1024 * 1024  // > 1MB\r
    });\r
\r
    // Text search (body)\r
    let list = await client.search({ body: 'important keyword' });\r
\r
    // Combine with OR\r
    let list = await client.search({\r
        or: [\r
            { from: '[email protected]' },\r
            { from: '[email protected]' }\r
        ]\r
    });\r
\r
    // Combine AND + OR\r
    let list = await client.search({\r
        subject: 'report',\r
        or: [\r
            { from: '[email protected]' },\r
            { from: '[email protected]' }\r
        ]\r
    });\r
\r
    // List is an array of sequence numbers. Use fetch() with those:\r
    for await (let msg of client.fetch(list, { envelope: true })) {\r
        console.log(msg.envelope.subject);\r
    }\r
} finally {\r
    lock.release();\r
}\r
```\r
\r
**Search keys** → See [references/searching.md](references/searching.md) for the full IMAP search key reference.\r
\r
**Gmail raw search (X-GM-RAW):**\r
```js\r
let list = await client.search({ 'x-gm-raw': 'has:attachment larger:10M' });\r
```\r
\r
### 4. Mailbox Management\r
\r
```js\r
// List all mailboxes\r
let mailboxes = await client.list();\r
for (let mb of mailboxes) {\r
    console.log(`${mb.name} (${mb.path})`);\r
}\r
// Filter by pattern: client.list({ path: 'INBOX/*' })\r
\r
// Status (message count, unseen, etc.)\r
let status = await client.status('INBOX', { messages: true, unseen: true, uidNext: true });\r
console.log(`${status.messages} total, ${status.unseen} unseen`);\r
\r
// Mailbox info (when a mailbox is selected)\r
console.log(client.mailbox.exists);    // total messages\r
console.log(client.mailbox.uidNext);   // next predicted UID (CONDSTORE)\r
console.log(client.mailbox.uidValidity);\r
\r
// Create / Rename / Delete\r
await client.mailboxCreate('Projects/NewProject');\r
await client.mailboxRename('Projects/Old', 'Projects/New');\r
await client.mailboxDelete('Projects/Archive');\r
\r
// Subscribe / Unsubscribe\r
await client.mailboxSubscribe('INBOX/Newsletters');\r
await client.mailboxUnsubscribe('INBOX/Newsletters');\r
\r
// Move messages\r
await client.messageMove('1:5', 'Archive', { uid: false });\r
// Copy messages\r
await client.messageCopy('100:200', 'Important', { uid: true });\r
\r
// Delete messages (set \Deleted flag + expunge)\r
await client.messageDelete('1:10');\r
// Or manually: flag + expunge\r
await client.messageFlagsAdd('1:10', ['\\Deleted']);\r
await client.messageExpunge('1:10');  // or expunge all: client.mailboxExpunge()\r
```\r
\r
### 5. IDLE (Push Notifications)\r
\r
ImapFlow automatically enters IDLE when there's an active mailbox lock and no pending commands. Use events to react to new messages:\r
\r
```js\r
client.on('exists', async (data) => {\r
    console.log(`New messages! Count: ${data.count}`);\r
    // Fetch new messages\r
    let lock = await client.getMailboxLock('INBOX');\r
    try {\r
        for await (let msg of client.fetch(`${data.prevCount + 1}:${data.count}`, { envelope: true })) {\r
            console.log(`New: ${msg.envelope.subject}`);\r
        }\r
    } finally {\r
        lock.release();\r
    }\r
});\r
\r
client.on('expunge', (data) => {\r
    console.log(`Message seq#${data.seq} was deleted`);\r
});\r
\r
client.on('flags', (data) => {\r
    console.log(`Flags changed for seq#${data.seq}: ${data.flags}`);\r
});\r
\r
// Connect and select mailbox — IDLE starts automatically\r
await client.connect();\r
let lock = await client.getMailboxLock('INBOX');\r
// Keep lock active — IDLE runs in background\r
```\r
\r
**Manual IDLE control:**\r
```js\r
client.on('idle', () => console.log('Entered IDLE'));\r
// To disable auto-IDLE: new ImapFlow({ disableAutoIdle: true })\r
```\r
\r
### 6. Gmail-Specific Operations\r
\r
```js\r
// Gmail labels\r
let msg = await client.fetchOne('*', { labels: true });\r
console.log(msg.labels); // ['\\Inbox', 'Important', 'Starred']\r
\r
// Set labels\r
await client.messageFlagsAdd('1', ['\\Starred', 'Important'], { uid: true });\r
await client.messageFlagsRemove('100', ['Important'], { uid: true });\r
await client.messageFlagsSet('42', ['\\Inbox', 'CustomLabel'], { uid: true });\r
\r
// Gmail raw search\r
let results = await client.search({ 'x-gm-raw': 'from:alice has:attachment newer_than:7d' });\r
\r
// Gmail thread ID\r
let msg = await client.fetchOne('*', { threadId: true });\r
console.log(msg.threadId); // Gmail thread identifier\r
```\r
\r
Gmail connection config:\r
```js\r
new ImapFlow({\r
    host: 'imap.gmail.com',\r
    port: 993,\r
    secure: true,\r
    auth: {\r
        user: '[email protected]',\r
        accessToken: 'oauth2-token'  // Use OAuth2\r
    }\r
})\r
```\r
\r
> **Note:** Gmail requires OAuth2 or App Passwords. Regular passwords won't work unless "Less secure app access" is enabled (deprecated).\r
\r
### 7. Error Handling & Reconnection\r
\r
**Connection events:**\r
```js\r
client.on('error', (err) => {\r
    console.error('IMAP error:', err.message);\r
    // Connection is likely closed after a fatal error\r
});\r
\r
client.on('close', () => {\r
    console.log('Connection closed');\r
    // Reconnect logic here\r
});\r
\r
client.on('connectionError', (err) => {\r
    console.error('Connection failed:', err.message);\r
});\r
```\r
\r
**Reconnection pattern:**\r
```js\r
async function connectWithRetry(config, maxRetries = 5) {\r
    for (let i = 0; i \x3C maxRetries; i++) {\r
        try {\r
            const client = new ImapFlow(config);\r
            await client.connect();\r
            return client;\r
        } catch (err) {\r
            console.error(`Connection attempt ${i + 1} failed: ${err.message}`);\r
            if (i \x3C maxRetries - 1) {\r
                await new Promise(r => setTimeout(r, Math.min(1000 * Math.pow(2, i), 30000)));\r
            }\r
        }\r
    }\r
    throw new Error('All connection attempts failed');\r
}\r
```\r
\r
**Mailbox locking best practices:**\r
- Always use `try/finally` to release locks\r
- Keep lock durations short — release between operations when possible\r
- Never hold a lock across network calls or long async operations\r
- Use separate locks for read vs write operations when safe\r
\r
```js\r
// BAD: lock held too long\r
let lock = await client.getMailboxLock('INBOX');\r
let results = await client.search({ unseen: true });\r
// ... process results (slow, lock held) ...\r
lock.release();\r
\r
// GOOD: release lock between operations\r
let results;\r
{\r
    let lock = await client.getMailboxLock('INBOX');\r
    results = await client.search({ unseen: true });\r
    lock.release();\r
}\r
// Process results without holding lock\r
for (let seq of results) { /* ... */ }\r
```\r
\r
**Timeouts and connection health:**\r
```js\r
// No operation timeout (blocks forever) — set one\r
const timeout = setTimeout(() => client.close(), 30000);\r
// ... your operation ...\r
clearTimeout(timeout);\r
\r
// Check if connected: client.usable → true/false\r
```\r
\r
## Reference Files\r
\r
- **[connection.md](references/connection.md)** — Provider-specific connection configs: Gmail, Outlook/Hotmail, Yahoo, iCloud, Zoho, Fastmail, custom servers. Includes TLS, OAuth2, App Passwords, and proxy setup.\r
- **[searching.md](references/searching.md)** — Complete IMAP search key reference: flags, dates, sizes, headers, text searches, logical operators, sequence sets, Gmail raw search.\r
- **[api_reference.md](references/api_reference.md)** — Key API methods summary: client methods, events, MailboxLock, FetchQueryObject options, and ImapFlow constructor options.
Usage Guidance
Use this skill only if you intend to let the agent help with IMAP email code. Keep mailbox credentials out of source code and logs, fetch the smallest needed set of messages, require confirmation before any delete/move/expunge/mailbox changes, and verify the external `imapflow` package before running generated code.
Capability Analysis
Type: OpenClaw Skill Name: imapflow Version: 1.0.0 The imapflow skill bundle provides comprehensive documentation and code examples for integrating the standard Node.js ImapFlow library. It covers authentication, message fetching, searching, and mailbox management without any evidence of malicious intent, data exfiltration, or prompt injection.
Capability Tags
cryptocan-make-purchasesrequires-oauth-tokenrequires-sensitive-credentials
Capability Assessment
Purpose & Capability
The documented capabilities fit the stated IMAP client purpose, including reading, searching, and managing mail, but references/api_reference.md also documents high-impact operations such as message and mailbox deletion.
Instruction Scope
The examples are user-directed API examples rather than automatic execution, but SKILL.md includes broad fetch examples such as full message source retrieval and all-message iteration.
Install Mechanism
There is no install spec or code in the skill, but SKILL.md examples rely on an external `imapflow` package while the registry source/homepage are unknown.
Credentials
Email passwords, app passwords, or OAuth access tokens are expected for IMAP access, but the registry metadata declares no primary credential or required environment variables.
Persistence & Privilege
No background service, autostart, persistence mechanism, or privileged installation is shown in the provided artifacts.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install imapflow
  3. After installation, invoke the skill by name or use /imapflow
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial release of the ImapFlow skill – a modern Node.js IMAP client for advanced email integration. - Provides comprehensive guides for connecting, authenticating (including provider-specific and OAuth2), and managing IMAP mailboxes. - Supports async/await and streaming/async iterator APIs for efficient email fetching. - Covers mailbox locking, searching, mailbox/label management, and downloading attachments. - Enables IDLE support for push notifications and outlines reconnection/proxy options. - Includes detailed usage recipes, common options, and references for major IMAP providers (e.g., Gmail, Outlook, Yahoo).
Metadata
Slug imapflow
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is imapflow?

Modern Node.js IMAP client library (imapflow) for email integration.Covers authentication, mailbox locking, streaming fetches, async iterators, reconnection... It is an AI Agent Skill for Claude Code / OpenClaw, with 8 downloads so far.

How do I install imapflow?

Run "/install imapflow" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is imapflow free?

Yes, imapflow is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does imapflow support?

imapflow is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created imapflow?

It is built and maintained by OpenLark (@openlark); the current version is v1.0.0.

💬 Comments