mailsim

GitHub

本地 SMTP 接收器,用于捕获、查看和断言应用发送的邮件。提供 HTTP API 和 CLI 工具,支持邮件查询、等待、故障注入及负载测试,便于开发调试邮件功能。

.claude/skills/mailsim/SKILL.md langwatch/langwatch

Trigger Scenarios

触发场景1: 用户询问邮件是否发送或查找验证码/邀请链接邮件 触发场景2: 需要模拟 SMTP 服务进行邮件功能的单元测试或负载测试

Install

npx skills add langwatch/langwatch --skill mailsim -g -y
More Options

Non-standard path

npx skills add https://github.com/langwatch/langwatch/tree/main/.claude/skills/mailsim -g -y

Use without installing

npx skills use langwatch/langwatch@mailsim

指定 Agent (Claude Code)

npx skills add langwatch/langwatch --skill mailsim -a claude-code -g -y

安装 repo 全部 skill

npx skills add langwatch/langwatch --all -g -y

预览 repo 内 skill

npx skills add langwatch/langwatch --list

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; -mail turns it off). Runs in the go lane by default (see sims).
  • URL: https://mail.<slug>.langwatch.localhost (console); haven status shows 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 .env names a provider.
  • No mail provider at all (even one .env names): haven up --no-mail --force blanks every mail setting for that run; haven up --force restores 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

Same Skill Collection

.claude/skills/analyticssim/SKILL.md
.claude/skills/browser-pair/SKILL.md
.claude/skills/browser-test/SKILL.md
.claude/skills/chakra-ui-builder/SKILL.md
.claude/skills/chakra-ui-refactor/SKILL.md
.claude/skills/code-review/SKILL.md
.claude/skills/code-search/SKILL.md
.claude/skills/feature-map/SKILL.md
.claude/skills/githubsim/SKILL.md
.claude/skills/haven-auth/SKILL.md
.claude/skills/haven-db/SKILL.md
.claude/skills/haven-orb/SKILL.md
.claude/skills/haven-play/SKILL.md
.claude/skills/haven-seed/SKILL.md
.claude/skills/haven-setup/SKILL.md
.claude/skills/idpsim/SKILL.md
.claude/skills/lambdasim/SKILL.md
.claude/skills/langwatch-kanban/SKILL.md
.claude/skills/llmsim/SKILL.md
.claude/skills/module/SKILL.md
.claude/skills/outboundsim/SKILL.md
.claude/skills/ownership/SKILL.md
.claude/skills/repo-tree/SKILL.md
.claude/skills/storagesim/SKILL.md
.claude/skills/voicesim/SKILL.md
plugins/langwatch/skills/langwatch/SKILL.md
services/langy-agent/skills/github/SKILL.md
skills/_compiled/native/agent-best-practices/SKILL.md
skills/_compiled/native/agent-performance/SKILL.md
skills/_compiled/native/automations/SKILL.md
skills/_compiled/native/code-changes/SKILL.md
skills/_compiled/native/context-sweet-spot/SKILL.md
skills/_compiled/native/daily-insights/SKILL.md
skills/_compiled/native/dashboard-widgets/SKILL.md
skills/_compiled/native/datasets/SKILL.md
skills/_compiled/native/debug-instrumentation/SKILL.md
skills/_compiled/native/debug-with-langwatch/SKILL.md
skills/_compiled/native/drive-the-ui/SKILL.md
skills/_compiled/native/eval-triage/SKILL.md
skills/_compiled/native/evaluate-multimodal/SKILL.md
skills/_compiled/native/evaluations/SKILL.md
skills/_compiled/native/experiments/SKILL.md
skills/_compiled/native/find-traces/SKILL.md
skills/_compiled/native/generate-rag-dataset/SKILL.md
skills/_compiled/native/github/SKILL.md
skills/_compiled/native/guided-onboarding/SKILL.md
skills/_compiled/native/level-up/SKILL.md
skills/_compiled/native/lwql-charts/SKILL.md
skills/_compiled/native/online-evaluations/SKILL.md

Metadata

Files
0
Version
c0c14dc
Hash
94870c51
Indexed
2026-10-19 19:33

Home - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-19 23:15
浙ICP备14020137号-1