postmark-email-cli
v1.0.1
Published
CLI tool for sending template emails via Postmark API
Downloads
17
Maintainers
Readme
Postmark Email CLI
📧 Send template emails via Postmark from the command line.
A powerful CLI tool for marketing teams and developers to send bulk template emails using Postmark's reliable email delivery service.
Features
✨ Interactive Setup - One-time configuration wizard
📊 Batch Processing - Send to hundreds or thousands of recipients
🔍 Suppression Checking - Automatically filter unsubscribed users
🧪 Dry Run Mode - Preview before sending
📈 Open & Click Tracking - Monitor email engagement
🎯 Campaign Tagging - Organize and track campaigns
💾 Result Logging - Save successful and failed sends
⚡ Fast & Reliable - Built on Postmark's infrastructure
Installation
Global Installation (Recommended)
npm install -g postmark-email-cliUse with npx (No Installation)
npx postmark-email-cli init
npx postmark-email-cli send -t <template-id> -f recipients.csvQuick Start
1. Run Setup Wizard
postmark-send initThis will prompt you for:
- Postmark Server API Token
- From email address
- Default message stream
Configuration is saved to ~/.postmark-send/config.json
2. Prepare Your CSV
Create recipients.csv:
email,name,company,discount_code
[email protected],John Doe,Acme Corp,SAVE20
[email protected],Jane Smith,Tech Inc,SAVE203. Send Emails
# Preview first (dry run)
postmark-send send -t your-template-id -f recipients.csv --dry-run
# Send for real
postmark-send send -t your-template-id -f recipients.csvUsage
Commands
init - Setup Wizard
postmark-send initInteractive wizard to configure Postmark credentials. Run this once to save your configuration.
send - Send Emails
postmark-send send [options]Send template emails to a list of recipients.
Required Options:
-t, --template <id>- Postmark Template ID or alias-f, --file <path>- Path to CSV file with recipients
Optional Options:
--token <token>- Postmark Server API Token (overrides saved config)--from <email>- From email address (overrides saved config)-s, --stream <name>- Message stream (default: "broadcast")-d, --dry-run- Preview without sending-b, --batch-size <n>- Emails per batch, max 500 (default: 50)--track-opens- Enable open tracking (default: true)--track-links <type>- Link tracking: None, HtmlAndText, HtmlOnly, TextOnly--check-suppressions- Filter suppressed emails before sending--tag <tag>- Add campaign tag for analytics
config - View Configuration
postmark-send config [--show-token]View your saved configuration.
Options:
--show-token- Show full API token (default: masked)
Configuration Methods
The CLI supports multiple configuration methods (in order of priority):
1. Setup Wizard (Recommended)
postmark-send initSaves configuration to ~/.postmark-send/config.json
2. Environment Variables
export POSTMARK_SERVER_TOKEN=your_token
export [email protected]
export MESSAGE_STREAM=broadcast3. Local .env File
Create .env in your project directory:
POSTMARK_SERVER_TOKEN=your_token_here
[email protected]
MESSAGE_STREAM=broadcast4. Command Line Arguments
postmark-send send \
--token your_token \
--from [email protected] \
-t template-id \
-f recipients.csvPriority Order
- Command-line arguments (highest priority)
- Environment variables
- Local
.envfile - Saved config (
~/.postmark-send/config.json)
Examples
Basic Send
postmark-send send -t 12345 -f subscribers.csvMarketing Campaign with Full Options
postmark-send send \
-t newsletter-template \
-f subscribers.csv \
--check-suppressions \
--tag "newsletter-jan-2024" \
--batch-size 200 \
--track-links HtmlAndTextTest Before Sending
# Dry run to preview
postmark-send send -t welcome-email -f new-users.csv --dry-run
# Send to small test group first
postmark-send send -t welcome-email -f test-group.csv
# Send to full list
postmark-send send -t welcome-email -f all-users.csv --check-suppressionsOverride Saved Configuration
# Use different from address for this send
postmark-send send \
-t promo-template \
-f customers.csv \
--from [email protected]
# Use different stream
postmark-send send \
-t receipt-template \
-f orders.csv \
--stream outboundCSV Format
Your CSV file must include an email column. All other columns become template variables.
Example CSV
email,firstName,lastName,planName,expiryDate
[email protected],John,Doe,Premium,2024-12-31
[email protected],Jane,Smith,Pro,2024-11-30
[email protected],Bob,Johnson,Basic,2024-10-15Template Variables
These CSV columns can be used in your Postmark template:
<p>Hello {{firstName}} {{lastName}}!</p>
<p>Your {{planName}} plan expires on {{expiryDate}}.</p>Note: The email column is used for the recipient address and is not passed as a template variable.
Template Setup
1. Create Template in Postmark
- Log into Postmark
- Navigate to: Servers → Your Server → Templates
- Click "Add Template"
- Design your email using template variables
2. Example Template
Subject:
Welcome, {{name}}! 🎉HTML Body:
<!DOCTYPE html>
<html>
<body>
<h1>Hello {{name}}!</h1>
<p>Welcome to {{company}}!</p>
<p>Your discount code: <strong>{{discount_code}}</strong></p>
<!-- Required for broadcast emails -->
<p><a href="{{{ pm:unsubscribe }}}">Unsubscribe</a></p>
</body>
</html>3. Match CSV to Template
Your CSV columns must match template variables:
| CSV Column | Template Variable |
|------------|-------------------|
| name | {{name}} |
| company | {{company}} |
| discount_code | {{discount_code}} |
Output Files
After sending, the CLI creates these files in your current directory:
successful-sends.json
[
{
"email": "[email protected]",
"messageId": "abc123-def456-789xyz",
"submittedAt": "2024-01-09T10:00:00.000Z"
}
]failed-sends.json
[
{
"email": "[email protected]",
"errorCode": 300,
"errorMessage": "Invalid email address"
}
]filtered-suppressed.json
(Only created when using --check-suppressions)
[
"[email protected]",
"[email protected]"
]Getting Postmark Credentials
1. Create Postmark Account
Sign up at postmarkapp.com (100 free emails/month)
2. Get Server API Token
- Navigate to: Servers → Your Server → API Tokens
- Copy the "Server API Token"
3. Verify Sender Email
- Go to: Sender Signatures
- Click "Add Domain or Signature"
- Verify your email address or domain
4. Create Template
- Go to: Templates → Add Template
- Create your email template
- Note the Template ID or set an alias
Tips & Best Practices
Always Test First
# 1. Dry run
postmark-send send -t template -f recipients.csv --dry-run
# 2. Send to yourself
postmark-send send -t template -f test-me.csv
# 3. Send to full list
postmark-send send -t template -f full-list.csvUse Suppression Checking
# Automatically filter unsubscribed users
postmark-send send \
-t template \
-f recipients.csv \
--check-suppressionsPrevents wasting email credits on suppressed addresses.
Tag Your Campaigns
postmark-send send \
-t newsletter \
-f subscribers.csv \
--tag "newsletter-2024-01"Track campaign performance in Postmark dashboard.
Adjust Batch Size
# Small batches (safer for testing)
--batch-size 10
# Medium batches (balanced)
--batch-size 50
# Large batches (faster)
--batch-size 500Monitor Your Sends
After sending, check:
successful-sends.json- Track MessageIDs- Postmark Activity dashboard - View delivery status
- Postmark Statistics - See open/click rates
Troubleshooting
"POSTMARK_SERVER_TOKEN not found"
Run the setup wizard:
postmark-send initOr set environment variable:
export POSTMARK_SERVER_TOKEN=your_token"Sender signature not found"
Verify your from email in Postmark:
- Go to Sender Signatures
- Ensure your email has a green checkmark ✓
"Template not found"
Check your template ID:
- Go to Templates in Postmark
- Click on your template
- Copy the Template ID from the top right
Or use Template Alias:
postmark-send send -t welcome-email -f recipients.csv"Stream does not exist"
Check available streams in Postmark:
- Go to Message Streams
- Note the Stream ID (e.g., "broadcast", "outbound")
- Use exact ID:
--stream broadcast
Variables not populated in email
Ensure CSV column names exactly match template variables:
- CSV:
firstName→ Template:{{firstName}}✅ - CSV:
first_name→ Template:{{firstName}}❌ (mismatch!)
Account in test mode
New Postmark accounts have restrictions:
- Can only send to same domain as "from" address
- Limited to 100 emails
Solution: Contact Postmark to approve your account (usually 1-2 days)
Advanced Usage
Check Suppression List Only
postmark-send send \
-t template \
-f recipients.csv \
--check-suppressions \
--dry-runView filtered emails in filtered-suppressed.json
Custom Link Tracking
# Track HTML links only
postmark-send send -t template -f file.csv --track-links HtmlOnly
# Disable link tracking
postmark-send send -t template -f file.csv --track-links NoneMultiple Campaigns
# Campaign A
postmark-send send -t promo -f listA.csv --tag "campaign-a"
# Campaign B
postmark-send send -t promo -f listB.csv --tag "campaign-b"
# Compare performance in Postmark dashboardAPI Rate Limits
- Maximum 500 emails per batch
- CLI automatically splits large lists into batches
- 1-second delay between batches
Security
Protecting Your API Token
✅ DO:
- Use the
initwizard (saves to~/.postmark-send/config.json) - Use environment variables
- Use
.envfile (add to.gitignore)
❌ DON'T:
- Commit
.envto git - Share your API token publicly
- Hard-code token in scripts
Config File Location
Configuration is saved to:
- Mac/Linux:
~/.postmark-send/config.json - Windows:
C:\Users\YourName\.postmark-send\config.json
This file is in your home directory, not your project directory.
Requirements
- Node.js: >= 14.0.0
- Postmark Account: Free tier available (100 emails/month)
Output
Success
======================================================================
📊 SEND SUMMARY
======================================================================
✓ Successfully sent: 150
✗ Failed: 0
📈 Success rate: 100.0%
======================================================================
✓ Successful sends saved to: successful-sends.json
✅ Done!With Errors
📦 Batch 1/1 (3 recipients):
✓ [email protected] → MessageID: abc123...
✗ [email protected] → Error: Invalid email address
✓ [email protected] → MessageID: def456...
Batch complete: 2 sent, 1 failed
======================================================================
📊 SEND SUMMARY
======================================================================
✓ Successfully sent: 2
✗ Failed: 1
📈 Success rate: 66.7%
======================================================================
⚠️ Failed sends saved to: failed-sends.jsonMessage Streams
Postmark separates emails into streams:
broadcast- Marketing emails, newsletters, announcementsoutbound- Transactional emails (receipts, password resets)
Best practice: Use broadcast for bulk marketing emails (default).
Link Tracking Options
HtmlAndText(default) - Track all linksHtmlOnly- Track HTML email links onlyTextOnly- Track plain text links onlyNone- Disable link tracking
Examples
Example 1: Welcome Email Campaign
CSV: new-users.csv
email,firstName,signupDate,planName
[email protected],John,2024-01-09,Premium
[email protected],Jane,2024-01-09,ProTemplate ID: 12345
Template:
<h1>Welcome, {{firstName}}!</h1>
<p>You signed up on {{signupDate}} for our {{planName}} plan.</p>Command:
postmark-send send \
-t 12345 \
-f new-users.csv \
--tag "welcome-campaign" \
--check-suppressionsExample 2: Newsletter
CSV: subscribers.csv
email,name,lastPurchase
[email protected],John,Widget Pro
[email protected],Jane,Gadget PlusCommand:
postmark-send send \
-t monthly-newsletter \
-f subscribers.csv \
--stream broadcast \
--tag "newsletter-jan-2024" \
--batch-size 200 \
--check-suppressionsExample 3: Transactional Receipts
CSV: orders.csv
email,orderNumber,total,date
[email protected],ORD-12345,$99.99,2024-01-09Command:
postmark-send send \
-t receipt-template \
-f orders.csv \
--stream outbound \
--track-opens false \
--track-links NoneFAQ
How do I get my Postmark credentials?
- Sign up at postmarkapp.com
- Create a server
- Get Server API Token from API Tokens tab
- Verify your sender email
Can I send to any email address?
New Postmark accounts are in "test mode" and can only send to the same domain as your from address. Request account approval to send to any domain.
What happens to unsubscribed users?
If you use --check-suppressions, the CLI automatically filters them out before sending. Otherwise, Postmark blocks the send and you'll see an error.
How do I create templates?
- Log into Postmark
- Go to Templates → Add Template
- Use
{{variableName}}for dynamic content - For broadcast emails, include
{{{ pm:unsubscribe }}}
Can I use template aliases instead of IDs?
Yes! Set an alias in Postmark template settings, then:
postmark-send send -t welcome-email -f recipients.csvHow do I handle unsubscribes?
Postmark handles unsubscribes automatically when you:
- Use
{{{ pm:unsubscribe }}}in your template - Send through a
broadcaststream
Users are added to the suppression list when they unsubscribe.
Where are output files saved?
Files are saved in your current working directory:
successful-sends.jsonfailed-sends.jsonfiltered-suppressed.json
Can I use this in CI/CD?
Yes! Use environment variables or pass credentials via CLI:
postmark-send send \
--token $POSTMARK_TOKEN \
--from $FROM_EMAIL \
-t $TEMPLATE_ID \
-f recipients.csvChangelog
[1.0.0] - 2025-10-14
Added
- Initial release
- Interactive setup wizard (
initcommand) - Batch email sending with templates
- CSV file support with validation
- Suppression list checking
- Open and link tracking configuration
- Dry run mode
- Campaign tagging
- Multiple configuration methods
- Result logging to JSON files
Contributing
Contributions welcome! Please open an issue or submit a pull request.
License
MIT
Links
Author
Your Name
- GitHub: @fyZhang
- Email: [email protected]
Acknowledgments
Built with:
- Postmark - Email delivery service
- Commander.js - CLI framework
- PapaParse - CSV parser
- dotenv - Environment variables
Made with ❤️ for the email marketing community
