npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

n8n-nodes-imap-agent

v0.4.0

Published

n8n community node for IMAP mailbox access with first-class AI Agent (usableAsTool) support. Read, search, move, flag and download emails from any IMAP server via imapflow + mailparser.

Readme

n8n-nodes-imap-agent

An n8n community node for IMAP mailbox access with first-class AI Agent support (usableAsTool: true). Read, search, move, flag and download emails from any IMAP server — either as a regular workflow node or as a tool driven by the n8n AI Agent node.

Built on top of imapflow (modern, Promise-based IMAP) and mailparser for RFC822 MIME parsing.


Why another IMAP node?

The existing community node n8n-nodes-imap works well for classic workflows, but was not designed for the n8n AI Agent tool protocol. This package is an independent implementation with three priorities:

  1. AI-ergonomic descriptions. Every resource, operation and parameter has a description written for an LLM: what the tool does, when to pick it, what each filter means.
  2. Flat, JSON-shaped search input. IMAP search criteria (SINCE, UNSEEN, FROM, etc.) are exposed as a collection with one field per criterion — the LLM fills a JSON object, the node translates it to an IMAP query.
  3. Binary-clean downloads. Attachments and .eml files come through as n8n binary data, ready to hand off to Paperless-ngx, S3, a file node, or back to the agent.

Installation

In the n8n UI (self-hosted)

Settings → Community Nodes → Install → package name n8n-nodes-imap-agent → Install.

As a custom node (link or manual install)

# in your n8n instance
cd ~/.n8n/custom
npm install n8n-nodes-imap-agent
# restart n8n

Docker

Mount the custom directory and install inside the container, or extend the image:

FROM n8nio/n8n:latest
USER root
RUN cd /home/node/.n8n/custom && npm install n8n-nodes-imap-agent
USER node

Credentials

Create a credential of type IMAP API.

| Field | Description | Example | | --- | --- | --- | | Authentication | Password or OAuth2 (XOAUTH2) | Password | | Host | IMAP server hostname | imap.gmail.com | | Port | 993 (implicit TLS) or 143 | 993 | | Use TLS | enable for port 993 | true | | User | mailbox user / email | [email protected] | | Password | account or app password | xxxx-xxxx-xxxx-xxxx | | Access Token | OAuth2 token (only in OAuth2 mode) | — | | TLS Options → Allow Self-Signed | set false for self-hosted Dovecot with a private CA | true | | TLS Options → Min Version | lowest TLS version to negotiate | TLSv1.2 | | Advanced → Connection Timeout | socket timeout in ms | 30000 | | Advanced → Disable Compression | turn off IMAP COMPRESS=DEFLATE | false |

Gmail / Google Workspace

  • Enable 2FA and use an App Password — Google refuses plain passwords over IMAP since 2022.
  • Alternatively use OAuth2 (XOAUTH2) and hand over a fresh access token. ⚠️ This node does not refresh tokens on its own — access tokens typically expire after 1 hour. Pair with an upstream HTTP Request / OAuth2 node that refreshes, then pass the token in via expression like ={{ $json.access_token }}. A stale token surfaces as "authentication failed".

Microsoft 365 / Outlook.com

  • Basic auth is deprecated. Use OAuth2 (XOAUTH2) with a Graph-registered app (IMAP.AccessAsUser.All scope).

Self-hosted (Dovecot, Stalwart, Mailcow)

  • Plain password + TLS 1.2 on port 993.
  • For internal CAs: set Allow Self-Signed Certificates to false only after you've installed your CA root in the n8n container — otherwise use true.

Operations

Resource: Email (10)

| Operation | What it does | Typical AI use | | --- | --- | --- | | Search | IMAP SEARCH with FROM/SUBJECT/SINCE/UNSEEN/FLAGGED/TEXT/BODY filters | "Find ungelesene Mails mit 'Rechnung' von letzter Woche" | | Get | Fetch one message by UID, parsed subject/body/headers, optional attachments | "Lies Mail 4217 und fasse zusammen" | | Move | Move UIDs → folder (batch-fähig) | "Verschiebe alle 12 Rechnungen nach /Archive/2026/Rechnungen" | | Copy | Copy UIDs → folder (batch) | — | | Delete | \Deleted + best-effort EXPUNGE (batch, returns {deleted, expunged, uids, requestedCount}expunged: false means the server rejected UID EXPUNGE, flag is set, server expunges on next folder close) | — | | Mark Read / Mark Unread | \Seen flag toggle (batch) | — | | Flag / Unflag | \Flagged (star) or custom keyword (batch) | "Markiere als Important" | | Append | Upload raw RFC822 to a folder (from text or binary input) | "Save draft" |

Resource: Mailbox (7)

List, Create, Delete, Rename, Status, Quota, Test Connection.

Agents should run Mailbox: List once before addressing specific folders, so they know the separator (/, ., /[Gmail]/) and which folders exist.

Batch UIDs

All write operations (Move, Copy, Delete, Mark Read, Mark Unread, Flag, Unflag) accept the batch UIDs field — a single number, a comma list, or an IMAP range:

| Input | Meaning | | --- | --- | | 42 | single message | | 1,5,9 | three messages | | 100:200 | 101 messages (range, inclusive) | | 1:* | all messages in the folder | | 1,5,9:12,20 | mixed |

One call → one IMAP round-trip. A classification workflow that moves 50 mails no longer needs 50 execute() iterations.

Error Handling

When the node is set to Continue On Fail, error items now include full context so a downstream IF / Switch node can branch cleanly:

{
  "error": "IMAP flag add failed: no messages matched \"4217\" in \"INBOX\"",
  "resource": "email",
  "operation": "flag",
  "mailbox": "INBOX",
  "uids": "4217"
}

Trigger: IMAP Trigger

Separate node (group trigger) that starts a workflow when the watched mailbox changes. Uses IDLE when the server supports it, polling otherwise.

| Property | Default | Notes | | --- | --- | --- | | Mailbox | INBOX | Folder path (server delimiter) | | Events | newMessage | Multi-select: newMessage (EXISTS), expunged (EXPUNGE), flagsChanged | | Mode | auto | auto picks IDLE if advertised, else poll. idle forces (errors if unsupported). poll forces polling. | | Poll Interval | 60 s | Only used in poll mode | | Filters | — | Optional client-side from / to / subject substring filter applied AFTER fetch | | Fetch Options | — | includeBody, includeHeaders, includeAttachments, maxAttachmentSizeMB (default 25) | | Manual Trigger Sample Size | 5 | When you click "Execute Node" in the editor, emit N recent messages for testing |

Behaviour:

  • No backlog replay. On first activation (or after UIDVALIDITY change), the trigger sets its watermark to the current UIDNEXT and only emits subsequent messages.
  • State persistence. lastUidNext + uidValidity survive workflow restarts via getWorkflowStaticData. UIDVALIDITY change (mailbox re-indexed) resets the watermark without replaying.
  • Reconnect. Exponential backoff (250 ms → 30 s cap) on connection loss. client.on('close' | 'error') triggers a re-connect; the catch-up fetch after reconnect emits anything that arrived while offline.
  • Manual test. Clicking "Execute Node" in the editor emits the N most recent messages without touching production state — safe to test an activated workflow.

Resource: Download (2)

  • Download Attachments — all attachments of a UID into binary slots, with optional filters:
    • Filename Contains — case-insensitive substring match on the attachment filename.
    • MIME Type — exact (application/pdf), type-wildcard (image/*), or full-wildcard (* / */*). A bare type like image does not match — always include a subtype or wildcard.
    • Max Attachment Size (MB) — default 25. Guards n8n workers against OOM when a mail carries a 500 MB file. Set 0 to disable.
  • Download EML — full raw RFC822 message as a single .eml binary.

Example AI Agent workflow

Paste the JSON below into Workflows → Import from clipboard. It's a minimal "triage my inbox" agent: the AI Agent is wired to an OpenAI chat model and is given the IMAP node as a tool. The system prompt is kept short on purpose — the tool descriptions in this package do the heavy lifting.

Replace imap-ai / openai-cred with your actual credential IDs after import.

{
  "name": "IMAP AI Triage (demo)",
  "nodes": [
    {
      "parameters": {},
      "id": "1a",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "typeVersion": 1,
      "position": [240, 300]
    },
    {
      "parameters": {
        "options": {
          "systemMessage": "Du bist ein E-Mail-Assistent. Nutze das Tool 'IMAP (AI)' um Mails zu suchen, zu lesen oder zu verschieben. Antworte knapp auf Deutsch."
        }
      },
      "id": "1b",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [520, 300]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "id": "1c",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1,
      "position": [520, 500],
      "credentials": { "openAiApi": { "id": "openai-cred", "name": "OpenAI" } }
    },
    {
      "parameters": {
        "resource": "email",
        "operation": "search",
        "mailbox": "INBOX",
        "searchFilters": { "unseen": true },
        "options": { "limit": 20, "newestFirst": true }
      },
      "id": "1d",
      "name": "IMAP (AI)",
      "type": "n8n-nodes-imap-agent.imap",
      "typeVersion": 1,
      "position": [800, 500],
      "credentials": { "imapApi": { "id": "imap-ai", "name": "My IMAP" } }
    }
  ],
  "connections": {
    "When chat message received": {
      "main": [[{ "node": "AI Agent", "type": "main", "index": 0 }]]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [[{ "node": "AI Agent", "type": "ai_languageModel", "index": 0 }]]
    },
    "IMAP (AI)": {
      "ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
    }
  }
}

Example chat turns once the workflow is running:

  • "Habe ich neue Rechnungen seit Montag?" → Agent calls Email / Search with { subject: "Rechnung", since: "2026-04-20", unseen: true }.
  • "Zeig mir Mail 1423"Email / Get with uid: 1423.
  • "Verschiebe sie nach Archive/2026/Rechnungen"Email / Move with that UID and the target folder.

Local development

git clone https://github.com/Daisytwo/n8n-nodes-imap-ai.git
cd n8n-nodes-imap-ai
npm install
npm run build          # tsc + gulp build:icons
npm run lint           # ESLint with n8n-nodes-base rules
npm test               # Jest unit tests for helpers
npm run dev            # tsc --watch

CI runs lint, build and test on every push and PR against main via GitHub Actions (.github/workflows/ci.yml, Node 20 & 22).

Then link into a local n8n instance:

# inside this repo
npm link

# in your n8n custom-nodes dir (create if missing)
mkdir -p ~/.n8n/custom && cd ~/.n8n/custom
npm init -y 2>/dev/null || true
npm link n8n-nodes-imap-agent

# start n8n — it auto-discovers linked packages
n8n start

Open http://localhost:5678, create an IMAP API credential, add an IMAP (AI) node, or wire it as a tool under an AI Agent node.


Implemented / omitted / known limits

Implemented (19 operations + trigger)

  • Mailbox (7): List, Create, Delete, Rename, Status, Quota, Test Connection
  • Email (10): Search, Get, Move, Copy, Delete, Mark Read, Mark Unread, Flag, Unflag, Append
  • Download (2): Download Attachments (with filename/MIME/size filter), Download EML
  • Trigger: IMAP Trigger with IDLE (push) + polling fallback, watermark-based dedupe via UIDNEXT/UIDVALIDITY

Deliberately not included

  • Gmail-only thread ops (X-GM-THRID). Non-portable across servers.
  • OAuth2 refresh flow. Credentials take a pre-issued access token — pair with an upstream OAuth2 credential node for refresh.

Known limits

  • hasAttachment filter is a size heuristic (> 50 KB), not an exact BODYSTRUCTURE scan.
  • No connection pool across execute() runs — a fresh IMAP connection per node execution, one socket shared across all items inside that execution.
  • Unit tests cover the pure helpers (buildSearchQuery, parseRawEmail, matchesMime). Integration testing against Gmail / Dovecot / Stalwart is manual — there is no mock IMAP server in the suite.
  • Delete issues \Deleted + best-effort EXPUNGE (expunged: false in the return when the server refuses UID EXPUNGE — the flag is still set). Gmail behaviour differs (moves to Trash).
  • Attachment size cap defaults to 25 MB — larger attachments are silently skipped during Download Attachments. Override via Max Attachment Size (MB) = 0 to disable.

License

MIT ©