A self-hosted disposable email service built in Rust. It accepts inbound emails via a standards-compliant SMTP server, persists them to PostgreSQL, and exposes them through a simple REST API.
The workspace has three crates:
temp-mail/
├── smtp/ # Async SMTP server (port 25)
├── http/ # REST API server (port 3000)
└── database/ # Shared PostgreSQL client and schema
SMTP Client → smtp (port 25) → database → http (port 3000) → API Consumer
SMTP state machine: Initial → Greeted → AwaitingRecipient → AwaitingData → DataReceived
- Full SMTP handshake:
EHLO,HELO,MAIL FROM,RCPT TO,DATA,QUIT,RSET,AUTH - Up to 100 recipients per message
- 10 MB message size limit
- 30-second read timeout per command, 5-minute connection timeout
- Emails older than 7 days are pruned automatically
- REST API to fetch and delete emails by recipient address
- Auto-creates database schema on startup (no migrations needed)
- Rust (edition 2024)
- PostgreSQL
Create a .env file in the project root:
DB_HOST=localhost
DB_USER=postgres
DB_PASSWORD=secret
DB_NAME=tempmail# Build everything
cargo build --release
# Start the SMTP server (requires port 25, may need sudo)
cargo run -p smtp
# Start the HTTP API server
cargo run -p httpBoth servers connect to the same PostgreSQL database and can run independently.
mail (id, date, sender, recipients, data)
quota (id, address, quota_limit, completed)
user_config (id, mail, address, web_hook_address)Indexes are created on date, recipients, and (date, recipients) for fast lookups.
GET /api/emails/:address
{
"success": true,
"data": [
{
"id": 1,
"date": "2026-02-23 12:00:00.000",
"sender": "someone@example.com",
"recipients": "you@mail.jasscodes.in",
"data": "..."
}
],
"error": null
}GET /api/emails/:address/:id
DELETE /api/emails/:address/:id
Address ownership is verified before returning or deleting an email — you can only access emails sent to the address in the URL.
S: 220 Temp Mail Service Ready
C: EHLO sender.example.com
S: 250-mail.jasscodes.in greets mail.jasscodes.in
250-SIZE 10485760
250 8BITMIME
C: MAIL FROM:alice@example.com
S: 250 Ok
C: RCPT TO:inbox@mail.jasscodes.in
S: 250 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: Subject: Hello
...
.
S: 250 Ok
C: QUIT
S: 221 Goodbye
| File | Responsibility |
|---|---|
smtp/src/main.rs |
Loads .env, binds to 0.0.0.0:25, starts SMTP server |
smtp/src/lib.rs |
start_smtp_server(), is_email_valid() |
smtp/src/server.rs |
TCP connection handler, read/write loop |
smtp/src/smtp.rs |
SMTP state machine (HandleCurrentState) |
smtp/src/types.rs |
Email, CurrentStates, SMTPResult |
smtp/src/errors.rs |
SmtpErrorCode, SmtpResponseError |
http/src/main.rs |
Axum router, REST handlers |
database/src/database.rs |
DatabaseClient, schema init, query methods |
- Tokio — async runtime
- Axum — HTTP framework
- tokio-postgres — async PostgreSQL driver
- tracing — structured logging
- chrono — date/time handling