n8n-nodes-proton-hydroxide
v0.1.8
Published
Stable polling trigger and IMAP actions for Proton via Hydroxide in n8n
Downloads
299
Maintainers
Readme
n8n-nodes-proton-hydroxide
Stable polling community nodes for Proton via Hydroxide in n8n.
Account isolation and health monitoring
Version 0.1.8 prevents one Proton account with an expired session, invalid bridge
password, or required CAPTCHA from delaying successful accounts:
- successful account results are emitted immediately instead of waiting for the full cycle;
- authentication failures are counted per bridge and Proton username;
- an account is quarantined after five consecutive authentication failures;
- INBOX and Spam share the same quarantine state;
- recovery probes run after 5 minutes, 15 minutes, and then every 30 minutes;
- changing the account bridge password clears its quarantine immediately;
- successful recovery automatically resumes polling;
- health state survives n8n restarts in
.n8n/proton-health/quarantine.json. - bridge timeout and bridge cooldown events are also written to the same health file so the host-side Mattermost notifier can alert on transport stalls.
The health file contains labels, usernames, timestamps, status, and error messages. It does not contain account passwords or bridge tokens.
The optional host-side notifier is available at
ops/proton-health-notify.py. It sends new quarantine, recovery, bridge timeout,
bridge cooldown, stale-monitor, and six-hour reminder messages to a Mattermost incoming webhook. Configure it
using ops/proton-health-notify.env.example; never commit the real webhook URL.
Set MATTERMOST_CHANNEL when the webhook must override its default channel.
What is included
Proton Hydroxide Accountscredential- stores multiple Proton accounts in one credential
- keeps Hydroxide host, port, timeouts, and concurrency in one place
- defaults are tuned for the current stack:
n8n-hydroxide:1143
Proton Hydroxide Trigger- polling trigger without an external scheduler node
- default search rules:
["UNSEEN","UNFLAGGED"] - formats:
Resolved,Simple,Raw - optional
Flagged after read - optional
Mark as Read
Proton Hydroxide- action node with
Set Flags
- action node with
Architecture
This package talks to Proton through an existing Hydroxide bridge.
The current server model is:
n8nconnects ton8n-hydroxide:1143- Hydroxide handles Proton Bridge-style IMAP access
- Hydroxide itself continues to route traffic through Tor at the container level
This package does not change that server model in v1.
Important limitation for v1:
- this package improves stability and lifecycle control
- it does not promise hard per-account Tor isolation on the network layer
- one shared Hydroxide service is still one shared Hydroxide service
Stability goals
This package is intentionally polling-based instead of IDLE-based.
The main reason is stability:
- each polling cycle opens a short-lived IMAP session
- reads matching emails
- optionally updates flags
- closes the connection cleanly
- trigger startup is deterministically staggered to avoid all Proton workflows hammering one shared Hydroxide bridge at the same second
- one shared bridge scheduler now serializes real IMAP logins per
hydroxideHost:portacross Proton workflows inside onen8n-server - duplicate poll requests for the same
node + account + mailboxare coalesced instead of building an endless queue - one bridge timeout no longer turns into a storm of identical timeout attempts from every Proton workflow
- a canary probe now decides whether the shared bridge has recovered before normal polling resumes
- one account timeout no longer aborts the whole multi-account polling cycle
- legacy credentials saved with the original
20s / concurrency 3defaults are upgraded automatically at runtime to safer45s / concurrency 1behavior
Transient IMAP errors are logged and skipped instead of forcing n8n to reactivate the whole workflow. This is designed to reduce ghost trigger instances and runaway duplicate deliveries.
When n8n closes the trigger:
- the polling interval is stopped
- the node marks itself as closed
- late results from a stale poll cycle are not emitted
After you change the credential, restart the workflow so the trigger reloads the account list.
Concurrency Limit
Concurrency Limit is not the number of accounts in your list.
It only means how many Proton accounts may be checked in parallel during one polling cycle.
Examples:
Concurrency Limit = 3and2accounts in the credential -> it checks2Concurrency Limit = 3and50accounts in the credential -> it checks3at a time until all are done
The next account starts as soon as one active slot finishes. There is no fixed artificial delay between accounts.
Current defaults
v0.1.2 is conservative by design for a shared Hydroxide bridge:
Connection Timeout = 45000 msAuth Timeout = 45000 msSocket Timeout = 60000 msConcurrency Limit = 1
The goal is to reduce synchronized timeout storms against one shared hydroxide:1143.
Shared bridge behavior
This package assumes one shared hydroxide:1143 service can become unhealthy if too many Proton workflows hit it at once.
To keep the bridge calmer:
- only one real IMAP login/openBox flow is active per bridge at a time
- duplicate poll requests for the same mailbox are collapsed
- when the bridge times out, the node enters a short bridge cooldown instead of immediately hammering
1143again - one canary IMAP probe decides when the bridge is healthy enough to resume normal polling
This v1 does not auto-restart hydroxide.
Installing in n8n
In self-hosted n8n:
- open
Settings -> Community Nodes - install package:
n8n-nodes-proton-hydroxide
- refresh the editor after installation if needed
Configuring the credential
Create Proton Hydroxide Accounts and fill:
Hydroxide Host: usuallyn8n-hydroxideHydroxide Port: usually1143Connection Timeout (ms)Auth Timeout (ms)Socket Timeout (ms)Concurrency Limit
Inside Accounts, add as many Proton accounts as you want:
LabelUsername / LoginBridge PasswordNotes(optional)
Using the trigger
Typical setup:
- add
Proton Hydroxide Trigger - select
Proton Hydroxide Accounts - set:
Mailbox Name = INBOXFormat = ResolvedCustom Email Rules = ["UNSEEN","UNFLAGGED"]
- process the message downstream
Output fields
The trigger keeps fields needed for downstream processing, especially:
uidattributes.uidmailboxprotonHydroxide.accountKeyprotonHydroxide.accountEmail
Flagged after read
If Flagged after read is enabled, the trigger sets \\Flagged after the message has been fetched successfully.
This is intended for the common pattern:
- search only
UNSEEN + UNFLAGGED - verify in the mailbox that the mail was processed
- avoid pulling the same message twice
Action = Mark as Read stays separate and still controls \\Seen.
Using Set Flags
Proton Hydroxide can still be used as a separate action node when you want manual control over flags.
It uses:
uidmailboxprotonHydroxide.accountKey
from the upstream item whenever possible.
Credential test
Credential test:
- checks Hydroxide IMAP login for every configured account
- opens the mailbox list for each configured account
If the UI says "Connection tested successfully", every configured account in that credential passed.
Smoke test
Local helper script:
npm run smoke:testExpected env vars:
HYDROXIDE_HOST=127.0.0.1
HYDROXIDE_PORT=1143
[email protected]
PROTON_1_PASSWORD=...
[email protected]
PROTON_2_PASSWORD=...The script:
- logs into the configured accounts through Hydroxide
- performs IMAP search with
["UNSEEN","UNFLAGGED"] - prints the first matching UID
