A native macOS SMTP fake inbox for developers. Drop the app into /Applications, point your dev environment at localhost:1025, and every email your app tries to send is parsed, stored, and shown to you in real time inside a real Mac app — no browser, no HTTP server, no Chromium.
Full documentation: mpjhorner.github.io/MailboxUltra · Install · Quick start · Preferences · Changelog
Pointing your dev environment at a real SMTP relay is overkill, and a SaaS sandbox needs an account and an internet round-trip. MailBox Ultra is the local Mac alternative: a real SMTP server inside a real Mac app, on your machine, that catches every message your app tries to send without ever delivering one. HTML emails render inside the app via the system WebKit engine — the same one Mail.app uses.
curl -sSL https://raw.githubusercontent.com/MPJHorner/MailboxUltra/main/scripts/install.sh | bashDetects your arch, grabs the matching
.dmgfrom the latest release, dropsMailBox Ultra.appinto/Applications, and clears the Gatekeeper quarantine flag. That's it — launch it from Spotlight oropen /Applications/MailBox\ Ultra.app.
Prefer the manual route? Download the .dmg from the latest release, drag MailBox Ultra.app into /Applications, right-click → Open on first launch. Build-from-source, code-signing, and uninstall instructions are on the install page.
Launch the app. The toolbar shows the SMTP URL it bound (default smtp://127.0.0.1:1025). Send anything to it:
swaks --to dev@example.com --from app@example.com \
--server 127.0.0.1:1025 \
--header "Subject: Hello from MailBoxUltra" \
--body "It works."The message lands in the inbox in milliseconds. Click it to inspect the HTML, plain text, every header, attachments (with Save… to disk), and the full RFC 822 source.
| Light mode — order confirmation | Mobile (390) — Resort '26 order |
|---|---|
![]() |
![]() |
The HTML pane uses the system WKWebView to render captured email HTML pixel-perfectly. The Desktop / iPad / Mobile buttons resize the preview frame and swap the User-Agent so responsive emails (with @media (max-width: 540px) rules and a viewport meta tag) reflow exactly the way they would in iOS Mail.
- Real SMTP — HELO, EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT, AUTH PLAIN, AUTH LOGIN. Anything that speaks RFC 5321 just works.
- Native window — real Mac dock icon, native menus,
⌘,for Preferences,⌘Qto quit. Window position and theme persist across launches. - WebKit HTML preview — captured HTML emails render inside the app via
WKWebView. JavaScript disabled, links intercepted and shelled to your default browser. Sandboxed. - Device-size preview — Desktop / iPad (820px) / Mobile (390px) buttons resize the preview frame and switch the UA so
@mediaqueries fire correctly. - Relay mode — optional upstream
smtp://orsmtps://URL. Capture for inspection, then forward to a real MTA. Toggle without restarting the SMTP listener. - NDJSON log — optional path to a JSON-lines log file. Tail it from a script or pair it with a coding agent watching alongside you.
- Bundled icon — the .app ships with a hand-drawn icon that pops on the macOS dock. Source SVG in
icon/icon.svg.
Open Preferences with ⌘, (or the gear button in the toolbar). Every flag the old CLI binary had is now a Settings field, plus theme:
- Servers — SMTP port, bind address.
- SMTP — hostname, max message size, optional AUTH PLAIN / AUTH LOGIN credentials.
- Capture — buffer size (the inbox is a ring buffer; older messages are evicted past this).
- Relay — optional upstream
smtp:///smtps://URL. Each captured message is forwarded after capture. - Logging — optional path to an NDJSON log file (one JSON object per captured message, append-only, never truncated).
- Appearance — System / Dark / Light.
Click Apply and the relevant servers restart in place. Captured messages are preserved across an SMTP restart up to the new buffer size. Settings persist in ~/Library/Application Support/com.mpjhorner.MailBoxUltra/settings.json.
| Key | Action |
|---|---|
j / ↓ |
Next message |
k / ↑ |
Previous message |
g / G |
Jump to newest / oldest |
/ |
Focus search |
1 – 6 |
Switch detail tab (HTML / Text / Headers / Attachments / Source / Release) |
p |
Pause / resume capture display |
d |
Delete current message |
⇧⌘X |
Clear all |
t |
Toggle theme |
⌘, |
Open Preferences |
? |
Show shortcuts cheat sheet |
Esc |
Close dialog / blur search |
Working on the app itself? Three flows cover most of it:
# 1. iterate on the code with cargo run (debug, no .app bundle)
make run
# 2. build a release .app bundle and launch it like a real Mac install
make app
open target/aarch64-apple-darwin/release/MailBoxUltra.app
# 3. fire varied real-world-looking emails at the running app
./scripts/simulate.py # all scenarios except burst
./scripts/simulate.py mare-drop # one scenario
./scripts/simulate.py burst -n 200 # ring-buffer stress test
make simulate-list # show every scenarioscripts/simulate.py is stdlib-only Python 3.9+ (already on macOS) so it works on a fresh checkout — no pip install step. The default run interleaves work emails (Linear / GitHub / Figma / Stripe / Apple), newsletters, and ecommerce templates (a fictional bikini brand "MARÉ" with real Unsplash imagery, fully responsive) so the inbox looks like a real day's mail.
make check runs the full pre-commit gate (cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, cargo test --all-features) — the same thing CI runs.
The docs site is the canonical user-facing reference:
- Install — DMG, Gatekeeper, build-from-source, uninstall
- Quick start — first message in 30 seconds
- Preferences — every Settings field, every restart semantic
- SMTP — supported verbs, AUTH, message size limits
- Relay — capture + forward to upstream MTA
- Logging — NDJSON file format, schema, examples
- Use cases — the workflows it's built for
- Comparison — vs Mailpit, MailHog, MailCatcher, SaaS
- Contributing — workspace layout, test policy
- Changelog — every release
Issues and pull requests welcome. make check before submitting; if you're adding a feature, add a test alongside. gui/ and main.rs are coverage-exempt (egui is immediate-mode, the data structures it consumes are tested independently).
MIT © 2026 MPJHorner.


