mailsim
GitHub本地 SMTP 接收器,用于捕获、查看和断言应用发送的邮件。提供 HTTP API 和 CLI 工具,支持邮件查询、等待、故障注入及负载测试,便于开发调试邮件功能。
Trigger Scenarios
Install
npx skills add langwatch/langwatch --skill mailsim -g -y
SKILL.md
Frontmatter
{
"name": "mailsim",
"description": "Catch, read and assert on the emails the LangWatch stack sends, using mailsim, haven's local mail sink. Use when someone says 'haven mail', 'did the email send', 'where is the verification mail', 'invite link', 'wait for the email', 'mailsim', 'the mail sink', 'haven sim mail', 'test the reset email', or needs to load-test SMTP.",
"user-invocable": true
}
mailsim
A local SMTP sink plus inbox. It catches every message the stack sends and relays
nothing, whatever the recipient domain. Code: services/sims/mailsim, console
apps/sims/src/mail.
Run it
- On by default in haven (
haven up;-mailturns it off). Runs in thegolane by default (seesims). - URL:
https://mail.<slug>.langwatch.localhost(console);haven statusshows the loopback HTTP port (MAILSIM_HTTP_ADDR) and the SMTP port (MAILSIM_SMTP_ADDR). - The app's own mail is routed at it (
SMTP_HOST=127.0.0.1) unless.envnames a provider. - No mail provider at all (even one
.envnames):haven up --no-mail --forceblanks every mail setting for that run;haven up --forcerestores it. It restarts the stack. - Standalone:
make service svc=mailsim(HTTP :5580, SMTP :5581).
Inspect and assert (HTTP)
GET /api/messages?to=&subject= newest first; case-insensitive substring filters
GET /api/messages/{id} /{id}/html one message: text, html, headers, links
GET /api/messages/wait?to=&subject=&after=<id>&timeout=30s
long poll; 200 message, 204 on timeout
DELETE /api/messages | DELETE /api/messages/{id}
GET /api/inbox stack, own address, SMTP address, persistence
GET|PUT /_sim/api/settings {"forcedError": 0|4xx|5xx}: SMTP MAIL FROM refused with that code
Test pattern: trigger the action, then curl ".../api/messages/wait?to=a@x.test&subject=verify&timeout=20s"
and read links[0]. Use after=<newest id> to ignore older mail.
Seed and reset
MAILSIM_SEED=1(haven sets it) delivers three sample messages at start.- Reset with
DELETE /api/messages.MAILSIM_DATA_DIR(haven sets it per slug) persists mail across restarts.
Tests and load
- Send with any SMTP client to the SMTP port; no auth needed.
- Bounded:
MAILSIM_MAX_MESSAGES(default 10000) keeps the newest and evicts the oldest;MAILSIM_MAX_MESSAGE_BYTES(default 10 MiB) caps one message. Id and recipient lookups are indexed. Benchmark:go test -bench . -benchmem ./services/sims/mailsim.
From a terminal or agent
--json on every read (default in agent mode); non-zero exit on failure; a wait timeout exits 66.
haven sim mail address | status | list [--to] [--subject] | get <id> [--html] | links <id>
haven sim mail fault <4xx|5xx|off> # SMTP sends refused with that reply code (4xx retry, 5xx permanent); off clears it
haven sim mail wait [--to] [--subject] [--after <id>] [--timeout 30s] | delete <id> | clear
Version History
- c0c14dc Current 2026-10-19 19:33


