Mailpit
Catch outbound email in a local Mailpit instance during development.
Catch outbound email in a local Mailpit 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 Mailpit only in development — swap to a production transport before you deploy.
Quick start
Start Mailpit (SMTP 1025, UI 8025):
docker run -d --rm -p 1025:1025 -p 8025:8025 axllent/mailpitimport { createMailer } from "sently/mailer";
import { MailpitTransport } from "sently/transports/mailpit";
const mailpit = new MailpitTransport();
const mailer = await createMailer({ transport: mailpit });await mailer.send({
from: "dev@example.com",
to: "you@example.com",
subject: "Hello",
text: "Captured by Mailpit",
});Open http://localhost:8025, or list messages from code:
const inbox = await mailpit.messages();
console.log(inbox.messages[0]?.Subject);Configuration
| Option | Type | Default | Meaning |
|---|---|---|---|
host | string | "localhost" | SMTP hostname |
port | number | 1025 | 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:8025" | Web UI / REST API base |
apiAuth | { user, pass } | — | Basic auth for the UI/API |
provider is "mailpit". verify() checks SMTP; close() closes the socket adapter.
REST helpers
Vendor extras stay on the transport instance (not on createMailer):
| Method | Mailpit API | Meaning |
|---|---|---|
messages({ limit?, start? }) | GET /api/v1/messages | List captured messages (newest first) |
getMessage(id) | GET /api/v1/message/{id} | Full message body |
deleteMessages(ids) | DELETE /api/v1/messages | Delete by id |
deleteAll() | DELETE with empty IDs | Clear the inbox |
webUrl | — | UI base URL (same as apiUrl) |
await mailpit.deleteAll();
await mailer.send({ from: "a@test.com", to: "b@test.com", subject: "T", text: "ok" });
const list = await mailpit.messages({ limit: 1 });
const full = await mailpit.getMessage(list.messages[0]!.ID);REST failures throw MailpitError (provider: "mailpit"). Empty getMessage("") throws with status 400.
Troubleshooting
Mailpit is not running, or the SMTP port is remapped. Start the container above, or set host / port to match your install.
SMTP and the UI/API can bind to different hosts. Set apiUrl (and apiAuth if the UI requires Basic auth).
Yes, if you only need SMTP. MailpitTransport adds local defaults and REST helpers for tests and inspection.
Learn more
- SMTP — generic SMTP when you are not on Mailpit
- Preview — write
.emlfiles to disk instead - Email channel —
createMailercontract