High-throughput bulk email campaign API built with TypeScript.
Mailer is designed for teams that need reliable, asynchronous campaign delivery with simple HTTP workflows and template-based personalization.
- Async delivery pipeline powered by BullMQ and Redis.
- Campaign-centric workflow from upload to completion.
- Template placeholders in both subject and HTML body.
- Clear status tracking for operational visibility.
- Minimal integration surface: straightforward REST endpoints.
- CSV + HTML upload per campaign.
- Recipient validation through mandatory
recipientcolumn. - Batched worker processing with retry and exponential backoff.
- Campaign progress metrics (
pending,processing,completed,failed). - Structured server and worker logging.
- Node.js
- TypeScript
- Express
- BullMQ
- Redis (ioredis)
- Nodemailer
npm installCreate .env in the project root:
PORT=3000
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
USER_EMAIL=your-email@gmail.com
USER_PASSWORD=your-gmail-app-passwordnpm run devAPI base URL:
http://localhost:3000/api
GET /health
POST /upload (multipart/form-data)
csv: recipients file with arecipientheaderhtml: HTML template file
curl -X POST http://localhost:3000/api/upload \
-F "csv=@recipients.csv" \
-F "html=@template.html"POST /send
{
"campaignId": "<campaign-id>",
"from": "sender@example.com",
"subject": "Welcome {{firstName}}"
}POST /preview
{
"campaignId": "<campaign-id>"
}GET /campaign/:campaignId
DELETE /campaign/:campaignId
Placeholders follow {{columnName}} and are resolved from CSV headers.
Example CSV:
recipient,firstName,company
jane@example.com,Jane,AcmeExample HTML:
<h1>Hello {{firstName}}</h1>
<p>Welcome to {{company}}.</p>npm run dev
npm run build
npm run start
npm run typechecksrc/
controller/ request handlers
routes/ API route definitions
services/ mail, queues, and workers
middleware/ error and not-found handlers
store/ Redis key helpers
db/ Redis connection setup
utils/ logger and template utilities
types/ shared TypeScript interfaces
- Client uploads CSV and HTML template to the API.
- API validates input and stores campaign metadata and assets in Redis.
- Client starts delivery via
/send; API pushes a job to BullMQ. - Worker consumes the job, renders templates, and sends emails in batches.
- Worker writes progress and final status back to Redis.
- Client retrieves campaign status through the status endpoint.
- Delivery is asynchronous, so API requests remain fast.
- Jobs are retried automatically with exponential backoff.
- Campaign state is centralized in Redis for real-time status checks.
- Worker concurrency and batch size control throughput and resource usage.
