npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

postmark-email-cli

v1.0.1

Published

CLI tool for sending template emails via Postmark API

Downloads

17

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-cli

Use with npx (No Installation)

npx postmark-email-cli init
npx postmark-email-cli send -t <template-id> -f recipients.csv

Quick Start

1. Run Setup Wizard

postmark-send init

This 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,SAVE20

3. 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.csv

Usage

Commands

init - Setup Wizard

postmark-send init

Interactive 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 init

Saves configuration to ~/.postmark-send/config.json

2. Environment Variables

export POSTMARK_SERVER_TOKEN=your_token
export [email protected]
export MESSAGE_STREAM=broadcast

3. Local .env File

Create .env in your project directory:

POSTMARK_SERVER_TOKEN=your_token_here
[email protected]
MESSAGE_STREAM=broadcast

4. Command Line Arguments

postmark-send send \
  --token your_token \
  --from [email protected] \
  -t template-id \
  -f recipients.csv

Priority Order

  1. Command-line arguments (highest priority)
  2. Environment variables
  3. Local .env file
  4. Saved config (~/.postmark-send/config.json)

Examples

Basic Send

postmark-send send -t 12345 -f subscribers.csv

Marketing Campaign with Full Options

postmark-send send \
  -t newsletter-template \
  -f subscribers.csv \
  --check-suppressions \
  --tag "newsletter-jan-2024" \
  --batch-size 200 \
  --track-links HtmlAndText

Test 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-suppressions

Override 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 outbound

CSV 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-15

Template 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

  1. Log into Postmark
  2. Navigate to: Servers → Your Server → Templates
  3. Click "Add Template"
  4. 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

  1. Navigate to: Servers → Your Server → API Tokens
  2. Copy the "Server API Token"

3. Verify Sender Email

  1. Go to: Sender Signatures
  2. Click "Add Domain or Signature"
  3. Verify your email address or domain

4. Create Template

  1. Go to: Templates → Add Template
  2. Create your email template
  3. 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.csv

Use Suppression Checking

# Automatically filter unsubscribed users
postmark-send send \
  -t template \
  -f recipients.csv \
  --check-suppressions

Prevents 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 500

Monitor 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 init

Or set environment variable:

export POSTMARK_SERVER_TOKEN=your_token

"Sender signature not found"

Verify your from email in Postmark:

  1. Go to Sender Signatures
  2. Ensure your email has a green checkmark ✓

"Template not found"

Check your template ID:

  1. Go to Templates in Postmark
  2. Click on your template
  3. 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:

  1. Go to Message Streams
  2. Note the Stream ID (e.g., "broadcast", "outbound")
  3. 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-run

View 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 None

Multiple 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 dashboard

API 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 init wizard (saves to ~/.postmark-send/config.json)
  • Use environment variables
  • Use .env file (add to .gitignore)

DON'T:

  • Commit .env to 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.json

Message Streams

Postmark separates emails into streams:

  • broadcast - Marketing emails, newsletters, announcements
  • outbound - Transactional emails (receipts, password resets)

Best practice: Use broadcast for bulk marketing emails (default).

Link Tracking Options

  • HtmlAndText (default) - Track all links
  • HtmlOnly - Track HTML email links only
  • TextOnly - Track plain text links only
  • None - 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,Pro

Template 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-suppressions

Example 2: Newsletter

CSV: subscribers.csv

email,name,lastPurchase
[email protected],John,Widget Pro
[email protected],Jane,Gadget Plus

Command:

postmark-send send \
  -t monthly-newsletter \
  -f subscribers.csv \
  --stream broadcast \
  --tag "newsletter-jan-2024" \
  --batch-size 200 \
  --check-suppressions

Example 3: Transactional Receipts

CSV: orders.csv

email,orderNumber,total,date
[email protected],ORD-12345,$99.99,2024-01-09

Command:

postmark-send send \
  -t receipt-template \
  -f orders.csv \
  --stream outbound \
  --track-opens false \
  --track-links None

FAQ

How do I get my Postmark credentials?

  1. Sign up at postmarkapp.com
  2. Create a server
  3. Get Server API Token from API Tokens tab
  4. 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?

  1. Log into Postmark
  2. Go to Templates → Add Template
  3. Use {{variableName}} for dynamic content
  4. 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.csv

How do I handle unsubscribes?

Postmark handles unsubscribes automatically when you:

  1. Use {{{ pm:unsubscribe }}} in your template
  2. Send through a broadcast stream

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.json
  • failed-sends.json
  • filtered-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.csv

Changelog

[1.0.0] - 2025-10-14

Added

  • Initial release
  • Interactive setup wizard (init command)
  • 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

Acknowledgments

Built with:


Made with ❤️ for the email marketing community