Inbucket
Catch outbound email in a local Inbucket instance during development.
Catch outbound email in a local Inbucket instance while you develop. Use it for the welcome email or password-reset flow before you point at a production provider.
The one rule
Use Inbucket only in development — swap to a production transport before you deploy.
Vendor extras stay on the InbucketTransport instance — never on createMailer.
Quick start
Start Inbucket (SMTP 2500, UI 9000):
docker run -d --rm --name inbucket -p 9000:9000 -p 2500:2500 -p 1100:1100 inbucket/inbucketimport { createMailer } from "sently/mailer";
import { InbucketTransport } from "sently/transports/inbucket";
const inbucket = new InbucketTransport();
const mailer = await createMailer({ transport: inbucket });await mailer.send({
from: "dev@example.com",
to: "you@example.com",
subject: "Hello",
text: "Captured by Inbucket",
});Open http://localhost:9000, or list messages from code.
Stock Inbucket stores you@example.com under mailbox you:
const mailbox = inbucket.mailboxForAddress("you@example.com");
const inbox = await inbucket.listMailbox(mailbox);
console.log(inbox[0]?.subject);Configuration
| Option | Type | Default | Meaning |
|---|---|---|---|
host | string | "localhost" | SMTP hostname |
port | number | 2500 | SMTP port |
secure | boolean | false | Implicit TLS on connect |
requireTLS | boolean | false | Refuse AUTH without TLS |
auth | SMTPAuth | — | Optional SMTP credentials |
tls | TLSOptions | — | TLS options when TLS is enabled |
connectionTimeout | number | — | Socket connect timeout (ms) |
adapter | SocketAdapter | auto-detected | Runtime TCP adapter |
apiUrl | string | "http://localhost:9000" | Web UI / REST API base |
mailboxNaming | "local" | "full" | "domain" | "local" | How mailboxForAddress maps an email |
provider is "inbucket". verify() checks SMTP; close() closes the socket adapter.
webUrl is the UI base (same as apiUrl).
Features
Pick a branch. Channel send goes through mailer; everything else is called on inbucket.
Inbucket is mailbox-centric — pass a mailbox name (or derive it with mailboxForAddress).
Transactional send via the channel mailer (SMTP into Inbucket).
await mailer.send({
from: "dev@example.com",
to: "you@example.com",
subject: "Welcome",
html: "<h1>Hello</h1>",
text: "Hello",
});REST failures throw InbucketError (provider: "inbucket").
Empty mailbox / id arguments throw with status 400.
Troubleshooting
Inbucket is not running, or the SMTP port is remapped. Start the container above, or set host / port to match your install.
Check mailbox naming. Stock Inbucket uses the local-part (you for you@example.com).
If your instance sets INBUCKET_MAILBOXNAMING=full or domain, match that with mailboxNaming.
SMTP and the UI/API can bind to different hosts. Set apiUrl to the web base (default http://localhost:9000).
Yes, if you only need SMTP. InbucketTransport adds local defaults and REST helpers for tests and inspection.
Learn more
- Mailpit — another local SMTP catcher with a different REST shape
- SMTP — generic SMTP when you are not on a catcher
- Preview — write
.emlfiles to disk instead - Email channel —
createMailercontract - Inbucket REST API — mailbox endpoints on the catcher