The conversation graph
The signature view: messages as nodes, a lane per person, animated reply edges, and a separate per-contact graph of everything you’ve exchanged with someone.
Every thread is a flat, confusing wall of quoted replies. NodeMail draws it the way it actually happened — each message a node on a timeline, a lane for every person, edges showing who replied to whom and the exact moment each contact joined the chain.
A real, interactive recreation of NodeMail’s thread graph. Click nodes, flip the layout, switch the accent.
One client for every account you have —
A reply list flattens a branching, multi-person discussion into one scroll. You lose the branches, you lose who answered whom, and you can’t see when someone was looped in. NodeMail keeps the shape.
Q3 launch plan 🚀
Re: Q3 launch plan
Re: Q3 launch plan
Re: Q3 launch plan
Re: Q3 launch plan
Re: Q3 launch plan
Who replied to Priya? When did Sam join? You can’t tell.
Branches, replies and the moment each person entered — at a glance.
NodeMail lays each conversation along a time axis and gives every participant their own lane. The result is a map you can read in a second: the spine of the discussion, the replies that branched off it, and the precise point where each new person was pulled in.
In-Reply-To → References → chronological fallback — so the tree is correct even when a client mangles the headers.In-Reply-To header?
Link straight to that exact message. Most replies land here.
References chain?
Walk the chain and attach to the nearest known ancestor.
Reconnect chronologically so the chain never breaks — shown as a dashed “reconnected” edge.
A parent is always older than its replies — the timeline can’t lie.
NodeMail isn’t a toy. It syncs, reads, writes, files, searches and keeps your contacts and calendar — all wrapped around the conversation graph.
The signature view: messages as nodes, a lane per person, animated reply edges, and a separate per-contact graph of everything you’ve exchanged with someone.
Add as many Gmail and IMAP accounts as you like, each with its own avatar and color. Drag to reorder, or merge them all into one unified “All inboxes”.
One searchable list that merges your Google Contacts, the people you actually email, and entries you add yourself — with avatars, phones, orgs and notes. Bulk-edit and delete.
Google Calendar in agenda, week and month views. Toggle calendars on and off, expand recurring series, and create, edit or delete events — without leaving your mail.
HTML is sanitized with DOMPurify — no scripts, forms or tracking pixels. Remote images are blocked by default; load them once, or trust a sender to load them always.
Reply, reply-all and forward with correct In-Reply-To and References threading, so your sent message snaps right back into the graph where it belongs.
Inbox, Sent, Drafts, Trash, Spam, Starred and your own labels — each with live unread counts and a custom emoji icon you pick yourself.
Filter your cached mail as you type — subjects, snippets, bodies and people. Press enter to push the query to the server (Gmail q: operators or IMAP SEARCH) for everything else.
Accent color, text color, interface scale, four font families, gradient / solid / image / daily-Bing backgrounds, plus graph edge style and node radius — all live, all local.
NodeMail has no server of its own. It talks only to your email provider and caches everything locally. There’s no account to create, no analytics phoning home, nothing about your mail leaves your computer.
See the architecture →Threads, messages, contacts and calendar live in a local SQLite database — never in anyone’s cloud but your provider’s.
OAuth tokens and IMAP passwords are encrypted in your OS keychain via Electron safeStorage.
Context isolation on, Node integration off, full sandbox. The UI can’t touch the network or disk directly.
Mail HTML is scrubbed and remote images gated, so tracking pixels never tell a sender you opened their email.
Every control below re-themes this whole page in real time — the same engine that themes the app. Pick an accent, a font, a backdrop, and reshape the graph nodes.
⤺ Everything is saved to your machine and applied instantly — no server, no round-trip.
A clean split keeps the privileged work in the main process and the UI dumb about providers. Add a mail backend behind one interface and the graph just works.
The UI you see. Talks only to a narrow, typed window.api — no Node, no network, fully sandboxed.
All the real work: OAuth, the Gmail & IMAP providers, the sync engine, local SQLite, token storage.
NodeMail is local-first and talks to your mailbox with your own credentials — nothing routes through us. Connect Gmail with Google sign-in for the richest integration, or connect Gmail (or any other provider) over standard IMAP/SMTP. Either way, credentials are stored encrypted on your device.
The deepest integration: the official Gmail API gives fast delta sync, native labels and contacts. A one-time, few-minute setup of your own Google Cloud OAuth client.
Open the Google Cloud Console and create a new project (or select an existing one).
Under APIs & Services → Library, enable the Gmail API, People API (contacts) and Google Calendar API.
In OAuth consent screen, choose External, fill in the basics, and add your own Google address under Test users. While the app stays in “testing” you don't need Google verification.
Go to Credentials → Create credentials → OAuth client ID and pick application type Desktop app. Copy the generated Client ID and Client secret.
On NodeMail's connect screen, paste the Client ID and secret, then Connect Gmail. They're stored encrypted on your device and never leave it.
No Google Cloud project required. Works with Gmail, Fastmail, Yahoo, iCloud, Outlook or any custom host — one-click presets fill in the server settings for you.
On NodeMail's connect screen switch to IMAP and tap a preset — Gmail, Fastmail, Yahoo, iCloud or Outlook — to fill the hosts and ports automatically. For anything else, type the IMAP and SMTP host yourself (see the table below).
Providers with two-factor sign-in — Gmail, Yahoo, iCloud (and Fastmail) — need a generated app password, not your normal login password. For Gmail, create one here (2-Step Verification must be on) and enable IMAP in your Gmail settings.
Fill in your email address and that password, confirm the IMAP port (993) and SMTP port (465 for implicit TLS, or 587 for STARTTLS), then Connect. Everything is stored encrypted on your device.
| Provider | IMAP host · port | SMTP host · port |
|---|---|---|
| Gmail | imap.gmail.com · 993 | smtp.gmail.com · 465 |
| Fastmail | imap.fastmail.com · 993 | smtp.fastmail.com · 465 |
| Yahoo | imap.mail.yahoo.com · 993 | smtp.mail.yahoo.com · 465 |
| iCloud | imap.mail.me.com · 993 | smtp.mail.me.com · 587 |
| Outlook | outlook.office365.com · 993 | smtp.office365.com · 587 |
Why your own credentials? Whichever route you pick, your mail stays in your account and on your own quota — NodeMail is just a local client. Google requires a client secret even for desktop apps and ties API quota & verification to the project that owns it, so option A uses your own; option B uses your provider's standard IMAP/SMTP. More on privacy →
A free, local-first desktop email client for macOS, Windows and Linux. Connect a Gmail or IMAP account and watch your first thread unfold as a graph.
Prefer to build it yourself? Clone the repo and run npm run build.