SkynetLabs
Back to journal
AutomationSeptember 24, 20267 min read

The n8n Shared Inbox Router: Rules Sort the Mail, a Model Reads What Is Left

By , Founder, SkynetLabs

An n8n workflow sorted 12 of 13 test messages with rules before any model saw them, 92.3%, clearing the 60% ship gate. Drafts only, no send node.

On this page

On a 13-row test set we wrote ourselves, rules sorted 12 of the messages before any model saw them. Episode 07 is the workflow behind that number: a shared inbox router that runs a deterministic rules engine ahead of a model, and never sends anything on its own.

A small consulting or agency inbox mixes leads, technical questions, spam and existing-client mail in one place, and every hour spent sorting it by hand is an hour not spent on the work itself. This workflow polls one mailbox, runs a known-client allowlist, a spam check and a set of regex intent patterns ahead of anything else, and only sends the messages none of those rules can call to one model, which classifies the message and drafts a reply. There is no send node anywhere on the canvas. The only write this workflow can make is a label inside the mailbox, and that write sits behind a whitelist gate that throws on any other shape.

If iframes are blocked where you are reading this, the video is at the Episode 07 video.

DRAFTS ONLY · LABEL WRITE: DRY RUN · 13 TEST EMAILS, WRITTEN BY US. Our own mailbox (skynetlabsai.com) holds only 8 messages as of this recording, too few to run a real hold-out measurement, so every count below comes from a 13-row test fixture we wrote ourselves, disclosed here and on every card in the video. The label-write step ships in dry run: no label was applied to a real message during this recording.

What does the inbox router actually do?

An IMAP poll reads the inbox (disabled by default here; the recorded run used the manual test path). A masking step hashes the sender and truncates the subject before anything is stored. A deterministic rules router then checks, in order: a known-client allowlist, a spam and bounce pattern, a technical-question pattern, and a lead pattern. Anything none of those rules can call is routed to a model over OpenRouter, which classifies the message as lead, technical, spam or existing client, and drafts a reply. Every row lands in Postgres. A whitelist gate reads the write's own shape before it can reach the mailbox and refuses anything that is not a label — a label is the only write this workflow can ever make.

What did the test run actually show?

On the 13-row fixture (samples/inbox-sample.json: 12 clean rows plus one deliberate edge case built to reach the model), the rules router handled 12 of 13 messages without a model ever seeing them — measured by extracting the router's own stored code and running it against the fixture directly, not by reading the logic and guessing.

Metric Observed
Messages in the test fixture 13
Rules-handled 12 of 13 (92.3%)
Model-handled 1 of 13 (the deliberate edge case)
Ship gate 60% or more rules-handled — cleared at 92.3%
Real mailbox size at recording 8 messages, too few for a live hold-out
Messages sent by the workflow 0 — there is no send node
Labels applied 0 — the label write ships in dry run
RULES 12, MODEL 1. On our own written test set, rules sorted the mail before any model read a message, clearing the 60%-or-more ship gate at 92.3%. THERE IS NO SEND NODE, and the label write ran in dry run for this recording.

Read the small mailbox honestly: our own inbox at skynetlabsai.com has too little real traffic yet to run the 14-day hold-out the workflow was designed around. A read-only smoke test confirmed the mailbox credential works and can read a real message, masked before anything left the terminal — that is a connection proof, not a volume proof. A production install against a live agency inbox should re-run the hold-out once real volume exists.

The cap sheet

THE CAP SHEET. 50 messages per run, 40 model calls per day (a real Postgres count checked before every call, not a number kept in memory), a 300-second execution timeout, and a breaker that trips after 3 consecutive errors. None of these are outputs of this run; they are thresholds set on the caps row before the poller ran.

Gotchas worth knowing before you fork this

No core n8n node applies a label or flag over plain IMAP — only the trigger node exists in core. The label-write node ships as a Gmail node, disabled, as the deliberate swap point: a production fork against Gmail would enable it for real, and a fork that stays on plain IMAP needs a community IMAP action node or a raw IMAP call in a Code node instead. Either way, this repo's reference deployment ships dry_run: true and that node disabled, so nothing is ever actually labelled by the copy you clone.

A whitelist gate reads any caller-supplied write shape before it builds anything, and throws on any item that is not a label. A crafted item asking to send a reply was fed into that gate directly and it threw, refusing to write — the real pipeline never produces a send-shaped item upstream at all, so this is a genuine refusal path, not a check that never fires.

How do I import it and where are the swap points?

The free workflow JSON is MIT-licensed at github.com/waseemnasir2k26/n8n-workflows/tree/main/workflows/07-inbox-router-drafts-only. Create the Data Table for the caps row, run the schema against your own Postgres, import the workflow and the error workflow, set your own IMAP, Postgres and OpenRouter credentials, then run the manual test path before ever pointing the IMAP trigger at a live mailbox.

Three swap points are built into the canvas on purpose:

  1. The IMAP poll trigger, shipped disabled — the manual test path drives a sample-inbox fixture instead until you are ready for a real mailbox.
  2. The label-write node, shipped disabled — a Gmail node as the reference swap point, since core n8n has no plain-IMAP label action.
  3. A dry_run flag on the caps row, defaulted true, so the workflow can decide and log a row without ever touching the mailbox. Flip it only once you know exactly which mailbox that row points at.

Frequently asked questions

Does this workflow send anything?

No. There is no send node anywhere on the canvas. The only write it can make is a mailbox label, and that write sits behind a whitelist gate that refuses any other shape. Every draft the model writes stays in a review table for a person to read.

Why did you test on 13 written messages instead of the real mailbox?

Because the real mailbox only held 8 messages at recording time, too few for the 14-day hold-out the workflow was designed around. The 13-row fixture is disclosed on every card and in this article rather than left as a quiet substitution.

What happens to the messages rules cannot sort?

They reach a single model node over OpenRouter, capped at 40 calls a day behind a real Postgres count, which classifies the message and drafts a reply. The draft carries a confidence score; anything under the threshold is downgraded to needs review before it ever reaches a label.

What stops the workflow from running away on errors?

A separate error workflow counts consecutive failures and trips a breaker after 3 in a row, independent of the message rules. Once tripped, the workflow processes zero items until a person resets it by hand.

The rest of the series

One workflow per video, the JSON given away under an MIT license each time, built by Waseem Nasir at SkynetLabs.

Want an inbox router tuned for your own mailbox? Message me on WhatsApp.

WhatsApp +92 300 1001957 · Waseem Nasir, SkynetLabs

Hire SkynetLabs, our Top Rated agency on Fiverr: https://www.fiverr.com/agencies/skynetjoellc