Postmark
Send through the Postmark Email API with message streams, metadata, and Postmark's single-tag model.
The Postmark adapter calls the Postmark Email API over fetch — no extra dependency. Its distinctive feature is message streams: set messageStream once and every send routes through that Postmark stream.
@opencoredev/email-sdk/postmarkConfigure
Create a server token for the server you send through, and make sure the sender signature or domain is approved in Postmark.
import { createEmailClient } from "@opencoredev/email-sdk";
import { postmark } from "@opencoredev/email-sdk/postmark";
export const email = createEmailClient({
adapters: [
postmark({
serverToken: process.env.POSTMARK_SERVER_TOKEN!,
messageStream: "outbound",
}),
],
});Prop
Type
Send
Postmark maps cc, bcc, replyTo, headers, attachments, metadata, and one tag.
const result = await email.send({
from: "Acme <hello@acme.com>",
to: "user@example.com",
replyTo: "support@example.com",
subject: "Your receipt for order ord_123",
html: "<p>Thanks for your order.</p>",
metadata: { orderId: "ord_123" },
tags: [{ name: "type", value: "receipt" }],
});
console.log(result.id); // Postmark MessageID, also exposed as result.messageIdmetadata becomes Postmark Metadata, and result.accepted echoes Postmark's To line.
One tag per message
Postmark has a single Tag field. The adapter serializes the first tag as name:value and a
second tag throws an EmailValidationError before any request is made. Need multiple tags?
Check the field support matrix.
Verify from the CLI
POSTMARK_SERVER_TOKEN="..." npx email-sdk doctor --adapter postmarkPOSTMARK_SERVER_TOKEN="..." npx email-sdk send \
--adapter postmark \
--message-stream outbound \
--from "Acme <hello@acme.com>" \
--to user@example.com \
--subject "Postmark smoke test" \
--text "It works" \
--dry-runThe token also accepts the --server-token flag. Drop --dry-run for one real send — that is the only check that proves the server token, sender signature, and message stream are ready.
