n8n-nodes-chh-imap
v0.1.0
Published
Minimal IMAP node for n8n: UIDVALIDITY-checked UID operations, native UID MOVE with COPYUID, partial body sections, a total deadline per operation.
Maintainers
Readme
n8n-nodes-chh-imap
A minimal IMAP community node for n8n, built for a mail router that must never lose or silently duplicate a message.
It is small on purpose: six operations over imapflow (pinned), each with an explicit result
contract and a total deadline.
Operations
| operation | what it returns |
|---|---|
| Folder State | per folder: uidValidity (decimal string), uidNext, exists; session capabilities move, uidplus |
| List UIDs | every UID of a folder >= fromUid, ascending — never "first N"; a failed or malformed UID SEARCH is an error, never an empty list |
| Lookup | one item per requested UID: found: true with size, envelope, flags (optionally BODYSTRUCTURE and raw header fields) or found: false |
| Fetch Part | the first maxBytes encoded bytes of one body section (BODY.PEEK[section]<0.n+1>); truncated: true is proven by one extra byte; decoding is left to the caller |
| Fetch Source | the whole raw message (base64) only when its size is known and within maxBytes (≤ 10 MB); otherwise tooLarge without downloading |
| Move | native UID MOVE of one message; outcome: 'moved' only with a valid COPYUID mapping of exactly that UID, otherwise 'unconfirmed' |
Guarantees
- Generation check in the same session. Every operation on a UID requires the expected
UIDVALIDITYand compares it with the folder's right afterSELECT, before the UID is used. A mismatch isUIDVALIDITY_MISMATCHand nothing else happens. - Plain JSON out.
BigIntbecomes a decimal string,Mapan array of pairs; nothing is serialised after a command has run. - No COPY+DELETE fallback. Without the
MOVEcapability the node refuses (MOVE_UNSUPPORTED). - Total deadline per operation (default 45 s, 1–300 s). On expiry the connection is closed and the operation fails with
TIMEOUT; the remaining items of that node run are not attempted (CONNECTION_CLOSED). Closing stops the waiting — a command the server already accepted may still complete there. commandSenton every Move error.falsemeans the MOVE was certainly never handed to the IMAP client (validation,SELECT, generation, capability, deadline before sending);truemeans it may have reached the server.
What it does not guarantee
UID MOVE is not exclusive between sessions: on Dovecot 2.4.5 two sessions moving the same UID at the same moment both received
COPYUID and OK, and the message existed twice (most rounds of a 40-round test, maildir and sdbox). moved proves that this session
created a copy — never that it was the only one. Mutual exclusion has to come from the caller (a lock), not from IMAP.
Dovecot answers an empty string for a body section the message does not have, so take section numbers from BODYSTRUCTURE.
Errors
With On Error → Continue an error becomes an item { op, error: { code, message, details } } with the input's pairedItem;
otherwise the node throws CODE: message. Codes: BAD_UID, BAD_PATH, BAD_UIDVALIDITY, BAD_SECTION, BAD_LIMIT, BAD_HEADERS,
BAD_DEADLINE, BAD_OPERATION, BAD_CREDENTIAL, CONNECT_FAILED, CONNECTION_CLOSED, OPEN_FAILED, NOT_SELECTED,
UIDVALIDITY_MISMATCH, SEARCH_FAILED, FETCH_FAILED, PART_MISSING, MOVE_UNSUPPORTED, MOVE_FAILED, TIMEOUT.
⚠ When the result of a Move matters, make it the only item of its node run and turn Continue on — an error on a later item would otherwise throw away the earlier result.
Credential
Uses n8n's built-in IMAP credential (user, password, host, port, SSL/TLS, allow self-signed certificates). Anyone who can edit a workflow can attach any IMAP credential of the instance to this node — and this node moves mail.
Install
Settings → Community Nodes → Install → n8n-nodes-chh-imap. No install scripts; the only dependency is imapflow (exact version).
Tests
npm test runs the unit tests (fake client), the wrapper tests (fake IMAP servers that hang) and — when a local Dovecot is reachable
on 127.0.0.1:31143 — the integration tests:
docker run -d --name chh-dovecot-test -e USER_PASSWORD=testpass -p 127.0.0.1:31143:31143 dovecot/dovecot:latestLicense
MIT
