Sand Inbox
A local SMTP Server, to preview e-mails without sending them to the Internet.
Features
Inbox & UI
- Local inbox that keeps every test email on your Mac.
- Preview HTML or plain text and inspect MIME parts, headers, and raw.
- Mark messages read/unread and export any message as
.eml. - Search/filter by sender, subject, or date to find mail fast.
- Mac-native UI with dark mode.
SMTP Server
- Receive-only SMTP server that runs locally on your Mac.
- Live session log while clients connect and send mail.
- End active sessions from the UI when needed.
- Listens on port 2525 by default (configurable).
- Jump between a session and its delivered emails.
- Session rows show remote host, start/end, duration, and message count.
- Optional Apple Mail profile to route Mail app traffic through Sand Inbox.
- Works fully offline—no relays, no external services.
And much more. Sand Inbox is still in development, available only to internal beta testers, and features may change abruptly—what you see here may not match the current build.
Integration
Point your app at Sand Inbox by setting SMTP_HOST and SMTP_PORT (default 127.0.0.1:2525). No username or password required unless you enabled auth in Sand Inbox. Pick a stack for a working snippet.
// .env.development
SMTP_HOST=127.0.0.1
SMTP_PORT=2525
// configure in configure.swift
import Vapor
import VaporSMTP // or your SMTP package
app.smtp.configuration = .init(
hostname: Environment.get("SMTP_HOST") ?? "127.0.0.1",
port: Int(Environment.get("SMTP_PORT") ?? "2525") ?? 2525,
security: .none,
credentials: nil
)
// send (async); consider queueing for production
try await req.smtp.send(.init(
from: "dev@example.test",
to: ["you@example.test"],
subject: "Hello from Vapor",
body: .plain("Sent through Sand Inbox")
))
# app.py
import os
import smtplib
from email.message import EmailMessage
from flask import Flask
app = Flask(__name__)
SMTP_HOST = os.environ.get("SMTP_HOST", "127.0.0.1")
SMTP_PORT = int(os.environ.get("SMTP_PORT", 2525))
def send_mail():
msg = EmailMessage()
msg["From"] = "dev@example.test"
msg["To"] = "you@example.test"
msg["Subject"] = "Hello from Flask"
msg.set_content("Sent through Sand Inbox via Flask")
with smtplib.SMTP(host=SMTP_HOST, port=SMTP_PORT) as smtp:
smtp.send_message(msg)
@app.route("/send")
def send_route():
send_mail()
return "Sent!"
if __name__ == "__main__":
app.run(debug=True)
# install (macOS)
brew install swaks
# send through Sand Inbox
SMTP_HOST=127.0.0.1
SMTP_PORT=2525
swaks --to you@example.test \
--from dev@example.test \
--server "$SMTP_HOST" \
--port "$SMTP_PORT" \
--h-Subject "Hello from swaks" \
--body "Sent through Sand Inbox (plain text)"
# send HTML
swaks --to you@example.test \
--from dev@example.test \
--server "$SMTP_HOST" \
--port "$SMTP_PORT" \
--h-Subject "Hello from swaks (HTML)" \
--header "Content-Type: text/html" \
--body "Hi there
Sent through Sand Inbox.
"
# send a simple message via netcat (nc) with proper CRLF
SMTP_HOST=127.0.0.1
SMTP_PORT=2525
FROM="dev@example.test"
TO="you@example.test"
printf 'EHLO localhost\r\n'\
'MAIL FROM:<%s>\r\n'\
'RCPT TO:<%s>\r\n'\
'DATA\r\n'\
'Subject: Hello from nc\r\n'\
'From: %s\r\n'\
'To: %s\r\n'\
'\r\n'\
'Sent through Sand Inbox via nc.\r\n'\
'.\r\n'\
'QUIT\r\n' \
"$FROM" "$TO" "$FROM" "$TO" | nc "$SMTP_HOST" "$SMTP_PORT"
# Docker set host to host.docker.internal
docker run --rm \
-e SMTP_HOST=host.docker.internal \
-e SMTP_PORT=2525 \
alpine sh -c '
apk add --no-cache python3 &&
python3 - <<'\''PY'\''
import os, smtplib
from email.message import EmailMessage
host = os.environ.get("SMTP_HOST", "127.0.0.1")
port = int(os.environ.get("SMTP_PORT", "2525"))
msg = EmailMessage()
msg["From"] = "dev@example.test"
msg["To"] = "you@example.test"
msg["Subject"] = "Hello from Docker (python3)"
msg.set_content("Sent through Sand Inbox from Docker")
with smtplib.SMTP(host=host, port=port) as smtp:
smtp.send_message(msg)
print("Sent via", host, port)
PY
'