/install imapflow
\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.
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install imapflow - 安装完成后,直接呼叫该 Skill 的名称或使用
/imapflow触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
imapflow 是什么?
Modern Node.js IMAP client library (imapflow) for email integration.Covers authentication, mailbox locking, streaming fetches, async iterators, reconnection... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 8 次。
如何安装 imapflow?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install imapflow」即可一键安装,无需额外配置。
imapflow 是免费的吗?
是的,imapflow 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
imapflow 支持哪些平台?
imapflow 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 imapflow?
由 OpenLark(@openlark)开发并维护,当前版本 v1.0.0。