Gmail-class webmail
for Stalwart.
ihasmail is a JMAP-first web client: mail, calendars, contacts, files, filters and every other modern feature Stalwart Mail Server exposes — in one responsive app that works as well on a phone as it does on a desktop monitor.
Features
Everything Stalwart exposes, and nothing it doesn't
One app for mail, calendars, contacts and files. Where a capability is missing from the server, the feature that needs it steps aside rather than breaking.
Mail that behaves like Gmail
Three-pane layout with a drag-to-resize splitter, conversation view, virtualised
infinite list, multi-select, drag & drop, context menus and the keyboard
shortcuts your fingers already know — j/k, e,
r/a/f, g i, /. Archive, label, move and
delete all come with Undo.
Calendar
Month, week, day and agenda views over JMAP Calendars. Recurrence with a custom rule builder, time zones, reminders, attendees with real invitations and RSVP, free/busy lookup, and Outlook-style colour categories that sync as JSCalendar.
Contacts & files
Address books with groups, a full contact editor, vCard import/export and a letter index. Files browses JMAP FileNode storage with drag-and-drop upload, folders, rename and move.
Search you can actually type
Gmail operators work as written — from:, subject:,
has:attachment, is:unread, label:,
before:, larger: — with an advanced panel for when
you'd rather click.
A composer that keeps up
Multiple floating composers, rich text with inline images and emoji, recipient chips autocompleting from contacts, the directory and recent recipients, multiple identities with HTML signatures, templates, undo send, and scheduled send that waits in the server's queue whether or not you're still online.
Sieve filters, built visually
Right-click a message and Filter messages like this… writes a Sieve rule pre-filled from the sender or list, creating target folders on the fly — and can apply it to the mail already sitting in the folder. There's a raw script editor with server-side validation underneath.
Private by default
Remote images are blocked until you say otherwise, with a per-sender allow-list and an optional proxy that fetches them without handing the sender your address. Mail renders sanitised inside a Shadow DOM. Read receipts are offered, never sent automatically.
Dates in your language
Every one of the ~620 locales CLDR knows about, each named in its own language and script, with your choice of date order and a 12- or 24-hour clock. Numerals follow the locale. Dates are entered through pickers in the same format, because browsers ignore the page's and use their own.
Installs like an app
A real PWA with a service worker, mobile layout, bottom tab bar and full-screen
composer. Register it as your mailto: handler and the operating
system will offer ihasmail wherever it asks for a mail client.
Screenshots
Light or dark, desktop or phone
The app follows your system theme by default, with a toggle in the top bar and a three-way choice in Settings — the same arrangement this site uses.
Inbox & conversation — dark
Three panes, collapsed conversation, labels with colours.
Inbox & conversation — light
The same screen, following a light system preference.
Reply composer
Identities, Reply-To, rich text, signature and quoted text.
Calendar
Month view, multiple calendars, colour categories.
Contacts
Address books, groups, and a full JSContact editor.
Sieve filter builder
Also reachable from a message's right-click menu.
Sign-in
Stalwart mailbox credentials, with TOTP where it's enabled.
Mobile layout
Bottom tab bar, drawer navigation, full-screen composer.
All screenshots are taken against the built-in mock server with sample data — no real mailbox involved.
Architecture
A client, not a second mail server
ihasmail holds no state of its own. Every mailbox, event, contact and file lives in Stalwart; the server in the middle exists to keep your password out of the browser and to speak JMAP on the page's behalf.
React SPA
JMAP client, push, and the zustand stores behind each view.
ihasmail server
Node + Hono. Session cookie in, sealed Basic auth out.
Stalwart
The only source of truth. Mail, calendars, contacts, files.
What the backend is for
It authenticates against Stalwart's JMAP session endpoint and stores those
credentials sealed with a key derived from the cookie secret — the server never
persists a plaintext password, and the browser never sees one at all. From there
it proxies /api/jmap, /api/blob, /api/upload,
/api/events and /api/image, and serves the SPA under a
strict CSP.
There is no database to install, back up or migrate. Stop the container and nothing has been lost but sessions.
Two generations of Stalwart
0.16 replaced the REST management API with JMAP registry objects, reshaped
FileNode, split its rights up and moved configuration into the
store. Where the two differ, ihasmail detects which server it is talking to
rather than assuming.
- Capabilities are negotiated, not presumed
- Missing capability means the feature steps aside, not an error
- Live push via EventSource, with polling as a fallback
- A built-in mock Stalwart for development and demos
Stack
What it's built on
Small, current, and boring where boring is a virtue.
| Layer | Choice | Why |
|---|---|---|
| web/ | Vite + React 19 + TypeScript | The SPA: src/jmap (client, push, types), src/store (zustand), src/views, src/lib. |
| server/ | Node + Hono | A thin proxy and session holder. Small enough to read in an afternoon. |
| protocol | JMAP | No IMAP, no POP3, no SMTP fallback path. One protocol, used properly. |
| storage | Stalwart | There is no second store. Nothing to keep in sync, nothing to reconcile. |
| sanitiser | DOMPurify + Shadow DOM | Sender HTML renders isolated from the app's own styles and scripts. |
| deployment | Docker | One container, configured entirely by environment variables. |
| licence | AGPL-3.0-or-later | Run it as a service for other people and they get the source too. |
Security & privacy
Your password never reaches the browser
A webmail client sits between someone's mailbox and the open internet. These are the parts that decision touches.
In the app
- Server-side sessions with per-session encrypted upstream credentials — no password in the browser, ever
- httpOnly, SameSite cookies; CSRF header plus
Sec-Fetch-Sitechecks - Strict Content-Security-Policy, sandboxed blob downloads
- Sender HTML sanitised with DOMPurify inside a Shadow DOM
- Remote images blocked by default, with an SSRF-safe proxy when you allow them
- Login rate limiting and the usual security headers
Self-service, in Settings
Change your password, manage app passwords — a separate one per device, revocable on its own — and turn two-factor authentication on or off by scanning a QR code.
Enrolment codes are verified before anything is stored, so a mistyped key can't lock you out, and switching 2FA on moves the current session onto a dedicated app password rather than signing you straight back out.
Read receipts are worth calling out: when a sender asks for one, ihasmail
offers to send a real RFC 8098 report — never automatically. Bulk mail,
mailing lists and anything marked Auto-Submitted aren't offered one
at all, and a receipt aimed somewhere other than the sender says so first.
License
AGPL-3.0-or-later, and why it changed
ihasmail was relicensed from GPL-3.0 to AGPL-3.0 in August 2026. Webmail is nearly always run as a network service rather than handed to anyone as a binary, and the AGPL's section 13 closes that gap: anyone running a modified ihasmail for other people has to offer them its source, which the GPL alone does not require.
That offer has to point at your source, not this one.
If you run a modified ihasmail, set SOURCE_URL to your own repository.
The sign-in page and Settings › About both show it, so the people using your
instance are told where the code they are actually running can be found.
Free software, no feature held back
There is no paid tier, no enterprise edition and nothing switched off behind a licence key. Copyright © 2026 LINUXexpert.org.
About
Built for one mailbox, then everyone else's
ihasmail exists because Stalwart is an excellent mail server with a genuinely modern protocol, and the web clients pointed at it were mostly IMAP clients wearing a JMAP hat. Building JMAP-first from the ground up turns out to change what the client can do: conversations, push, server-side scheduled send, free/busy lookup and Sieve round-tripping all stop being bolted on.
The current release is the 2.0 rewrite, in QA against a live Stalwart server. The earlier FastAPI/HTMX prototype has been removed entirely — only the logo survived.
A companion project, stalwart-migrator, handles the 0.15 → 0.16 upgrade: it checkpoints every phase, refuses to start on the things that cannot be fixed mid-migration, and validates the server afterwards. That path is treacherous by hand — the store is migrated in place with no way back, and Stalwart's own converter drops settings without saying so. The live instance made the jump in eight seconds of downtime with nothing lost.
ihasmail is written and maintained by LINUXexpert.org. Issues, feature requests and patches are all welcome on GitHub.