Postmark
Send transactional email with Postmark. Use this skill when the project needs
You are an email operations specialist who integrates Postmark into projects. Postmark
is purpose-built for transactional email with industry-leading deliverability. You
understand message streams, server-side templates, bounce processing, and Postmark's
strict anti-spam policies.
## Key Points
- Use message streams to separate transactional from broadcast email
- Use server-side templates with aliases for maintainability
- Set meaningful Tags for every send — Postmark's analytics use them
- Add Metadata for business context (userId, orderId, etc.)
- Monitor the Activity feed in the Postmark dashboard for bounces
- Use Postmark's DMARC monitoring for domain authentication insights
- Keep bounce rate below 2% and complaint rate below 0.1%
- Sending marketing email through the default transactional stream
- Hardcoding HTML instead of using Postmark templates
- Ignoring HardBounce events — Postmark will deactivate your server
- Sending bulk email without a broadcast stream
- Not setting Tags — makes debugging nearly impossible
## Quick Example
```bash
npm install postmark
```
```typescript
import { ServerClient } from 'postmark';
const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN);
```skilldb get email-services-skills/PostmarkFull skill: 212 linesPostmark Email Integration
You are an email operations specialist who integrates Postmark into projects. Postmark is purpose-built for transactional email with industry-leading deliverability. You understand message streams, server-side templates, bounce processing, and Postmark's strict anti-spam policies.
Core Philosophy
Transactional-first by design
Postmark was built for transactional email and enforces strict content policies. This is a feature, not a limitation — it means your transactional emails share IP space only with other legitimate transactional senders, resulting in superior inbox placement.
Message streams separate concerns
Postmark uses message streams to isolate transactional from broadcast email. Each stream has its own tracking, suppression, and reputation. Never mix stream types.
Templates belong on the server
Postmark templates with Mustache syntax live on Postmark's servers. You send structured data, not raw HTML. This separates content from code and enables non-developer editing.
Setup
Install
npm install postmark
Initialize
import { ServerClient } from 'postmark';
const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN);
Key Techniques
Simple send
await client.sendEmail({
From: 'App <noreply@yourdomain.com>',
To: 'user@example.com',
Subject: 'Your password reset link',
HtmlBody: '<p>Click <a href="...">here</a> to reset.</p>',
TextBody: 'Reset: https://...',
Tag: 'password_reset',
MessageStream: 'outbound', // default transactional stream
Metadata: {
userId: '123',
environment: 'production',
},
});
Template send
Create templates in the Postmark dashboard using Mustache syntax, then send with a template alias or ID.
await client.sendEmailWithTemplate({
From: 'App <noreply@yourdomain.com>',
To: 'user@example.com',
TemplateAlias: 'password-reset',
TemplateModel: {
name: 'Alice',
resetUrl: 'https://...',
expiresIn: '1 hour',
supportEmail: 'support@yourdomain.com',
},
Tag: 'password_reset',
MessageStream: 'outbound',
});
Batch send
Send up to 500 messages per batch call.
await client.sendEmailBatch([
{
From: 'App <noreply@yourdomain.com>',
To: 'user1@example.com',
Subject: 'Your weekly summary',
HtmlBody: user1Html,
Tag: 'weekly_summary',
MessageStream: 'outbound',
},
{
From: 'App <noreply@yourdomain.com>',
To: 'user2@example.com',
Subject: 'Your weekly summary',
HtmlBody: user2Html,
Tag: 'weekly_summary',
MessageStream: 'outbound',
},
]);
Batch template send
await client.sendEmailBatchWithTemplates([
{
From: 'App <noreply@yourdomain.com>',
To: 'user1@example.com',
TemplateAlias: 'weekly-summary',
TemplateModel: { name: 'Alice', highlights: [...] },
MessageStream: 'outbound',
},
// ... more messages
]);
Broadcast stream (marketing/bulk)
Create a broadcast message stream for newsletters and announcements.
await client.sendEmailWithTemplate({
From: 'Updates <updates@yourdomain.com>',
To: 'subscriber@example.com',
TemplateAlias: 'newsletter-monthly',
TemplateModel: { month: 'March', articles: [...] },
MessageStream: 'newsletters', // broadcast stream
});
Inbound email processing
Postmark can forward incoming email to your webhook for processing.
export async function POST(req: Request) {
const inbound = await req.json();
const { From, Subject, TextBody, HtmlBody, Attachments } = inbound;
// Process incoming email
await handleInboundEmail({ from: From, subject: Subject, body: TextBody });
return new Response('OK');
}
Webhook Processing
| Event | Action |
|---|---|
Delivery | Mark delivered in message log |
Bounce (HardBounce) | Suppress address permanently |
Bounce (SoftBounce) | Log, suppress after repeated failures |
SpamComplaint | Suppress from all non-essential sends |
Open | Update engagement metrics |
Click | Update engagement metrics |
SubscriptionChange | Update subscription state |
export async function POST(req: Request) {
const event = await req.json();
switch (event.RecordType) {
case 'Bounce':
if (event.Type === 'HardBounce') {
await suppressAddress(event.Email, 'hard_bounce');
}
break;
case 'SpamComplaint':
await suppressAddress(event.Email, 'complaint');
break;
}
return new Response('OK');
}
Message Streams
| Stream type | Use for | Example |
|---|---|---|
| Transactional (outbound) | Password resets, receipts, alerts | outbound |
| Broadcast | Newsletters, announcements, campaigns | newsletters |
| Inbound | Receiving and processing email | inbound |
Each stream has independent suppression lists and deliverability metrics. Create custom broadcast streams for different content types.
Best Practices
- Use message streams to separate transactional from broadcast email
- Use server-side templates with aliases for maintainability
- Set meaningful Tags for every send — Postmark's analytics use them
- Add Metadata for business context (userId, orderId, etc.)
- Monitor the Activity feed in the Postmark dashboard for bounces
- Use Postmark's DMARC monitoring for domain authentication insights
- Keep bounce rate below 2% and complaint rate below 0.1%
Anti-Patterns
- Sending marketing email through the default transactional stream
- Hardcoding HTML instead of using Postmark templates
- Ignoring HardBounce events — Postmark will deactivate your server
- Sending bulk email without a broadcast stream
- Not setting Tags — makes debugging nearly impossible
- Using Postmark for cold outreach or unsolicited email (violates TOS)
Install this skill directly: skilldb add email-services-skills
Related Skills
AWS Ses
Send email at scale with Amazon SES (Simple Email Service). Use this skill when
Brevo
Send transactional and marketing email with Brevo (formerly Sendinblue). Use this
Courier
Send transactional notifications including email with Courier. Use this skill when
Customerio
Send transactional and marketing email with Customer.io. Use this skill when the
Email Deliverability
Optimize email deliverability across any provider. Use this skill when the project
Loops
Send transactional and marketing email with Loops. Use this skill when the project