You want CI to exercise the email path. You do not want CI to email real people. Postmark gives you three tools, and they are not interchangeable.
1. The POSTMARK_API_TEST token
Set the server token to the literal string POSTMARK_API_TEST.
POSTMARK_SERVER_TOKEN=POSTMARK_API_TEST
- Postmark validates the request exactly as it would a real one.
- It answers with a normal response and a MessageID.
- Nothing is delivered. Nothing appears in the activity feed. No webhook fires.
Good for: local development, CI, unit-ish tests of the real HTTP path. A malformed address, a missing body, a metadata limit and a bad header all still fail.
Not good for: anything after the API call. You cannot test bounces, webhooks or what the email looks like.
Tell people when it is on. A log line on each send saves someone refreshing an inbox for ten minutes:
if (process.env.POSTMARK_SERVER_TOKEN === "POSTMARK_API_TEST") {
console.warn("[email] POSTMARK_API_TEST token: validated, not delivered");
}
Server-only reads (like GET /server) are not a use for it. Skip those checks when the test token is set rather than reporting them as failures.
2. A sandbox server
When you create a server you can choose Sandbox delivery. It cannot be changed later.
- Sends are processed and appear in the activity feed with full content.
- Nothing leaves Postmark.
- Webhooks can be tested from the dashboard.
Good for: staging, QA, previewing what was actually sent, demo environments that must never mail a customer.
Make it a separate server with its own token. Never flip production into a test mode.
3. The bounce-testing domain
On a live server, send to @bounce-testing.postmarkapp.com:
hardbounce@bounce-testing.postmarkapp.comproduces a hard bounce.- Postmark records a real bounce event and fires your Bounce webhook.
- Fake bounces count toward your monthly volume but not toward your bounce rate.
Good for: proving the full loop. Send, bounce, webhook, address suppressed, next send refused.
Which to use
| You want to prove | Use |
|---|---|
| The request is valid | POSTMARK_API_TEST |
| The rendered email looks right, in context | Sandbox server, or a real send to yourself |
| Your webhook handles a bounce | bounce-testing address on a live server |
| It lands in the inbox | A live server and a real mailbox you own |
Do not
- Do not mock the SDK and call it an email test. It proves your mock works.
- Do not point CI at a live token "just for a few tests". One bad fixture mails every address in it.
- Do not use real customer addresses in fixtures. Use
example.com(reserved for this) or the bounce-testing domain.