A production-ready email queue system built with TypeScript, Redis, and Nodemailer. This system demonstrates how to build scalable job queues for processing emails asynchronously.
- β Asynchronous Email Processing - Non-blocking queue operations
- β Redis-backed Queue - Fast, reliable job storage
- β Worker Pattern - Separate process for handling jobs
- β Error Handling - Failed emails are automatically re-queued
- β
Environment Configuration - Easy setup with
.envfile - β TypeScript Support - Full type safety
- Node.js (v14 or higher)
- Redis (running locally or remotely)
- Gmail Account (with 2-Step Verification enabled)
git clone https://github.com/Zurard/jobqueue.git
cd jobqueuenpm installCreate a .env file in the root directory:
cp .env.example .envEdit .env and add your Gmail credentials:
REDIS_HOST=localhost
REDIS_PORT=6379
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-app-password
SENDER_EMAIL=your-email@gmail.com- Go to: https://myaccount.google.com/apppasswords
- Select Mail & Windows Computer
- Copy the generated 16-character password
- Paste it as
EMAIL_PASSin.env
redis-server --daemonize yesOr check if it's running:
redis-cli ping
# Should return: PONGTerminal 1 - Start the Email Worker (background process):
npm run workerYou should see:
Processing the email queue
Terminal 2 - Run the Server:
npm run devYou should see:
email: shreetejmeshram07@gmail.com
password: password123
Starting email processing...
Processing the email queue
β
Email added to queue! Worker will process it.
π Server running...
Email sent to shreetejmeshram07@gmail.com
queue/
βββ src/
β βββ server.ts # Main application entry point
β βββ config/
β β βββ queue.ts # Queue class & Redis configuration
β β βββ emailWorker.ts # Email processing worker
β βββ services/
β βββ emailService.ts # Email service configuration
βββ .env # Environment variables (git ignored)
βββ .env.example # Example environment template
βββ .gitignore # Git ignore rules
βββ package.json # Dependencies
βββ tsconfig.json # TypeScript configuration
βββ README.md # Documentation
βββββββββββββββββββββββββββ
β Application Server β
β (server.ts) β
β - Receives requests β
β - Adds emails to queue β
ββββββββββββββ¬βββββββββββββ
β (lpush)
β
βββββββββββββββββββββββββββ
β Redis Queue β
β ("emailQueue") β
β [Email1, Email2, ...] β
ββββββββββββββ¬βββββββββββββ
β (brpop)
β
βββββββββββββββββββββββββββ
β Email Worker β
β (emailWorker.ts) β
β - Runs continuously β
β - Processes emails β
β - Sends via Gmail β
βββββββββββββββββββββββββββ
- User submits form β Server receives request
- Add to Queue β
addEmailToQueue()stores email in Redis - Server returns immediately β Non-blocking operation
- Worker picks up job β
brpop()gets oldest email from queue - Send email β Nodemailer sends via Gmail SMTP
- Log result β Success or error logged
# Install dependencies
npm install
# Run server (development mode)
npm run dev
# Start email worker
npm run worker
# Build to JavaScript
npm build
# Run compiled code (production)
npm start
# Test the queue
npm run test-queueimport { Queue } from "./config/queue";
import Redis from "ioredis";
const redis = new Redis();
const emailQueue = new Queue(redis, "email");
// Add email to queue
await emailQueue.addEmailToQueue(
"user@example.com",
"Welcome to our service!"
);const length = await emailQueue.getQueueLength();
console.log(`Pending emails: ${length}`);const allEmails = await emailQueue.getAll();
console.log(allEmails);Edit src/config/queue.ts:
class Queue {
constructor(redis: Redis, queueName: string) {
this.redis = redis;
this.queueName = "emailQueue"; // Change queue name here
}
}Edit src/config/emailWorker.ts:
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});Solution:
- Make sure
.envfile exists with valid credentials - Remove quotes from
EMAIL_PASSvalue - Use Gmail App Password, not regular password
Solution:
# Start Redis server
redis-server --daemonize yes
# Verify connection
redis-cli ping
# Should return: PONGSolution:
- Check Gmail spam/junk folder
- Verify 2-Step Verification is enabled on your Gmail account
- Check
.envhas correct App Password - Look at error logs in worker terminal
Solution:
- Make sure worker is running:
npm run worker - Check Redis is running:
redis-cli ping - Verify queue name matches in
queue.tsandemailWorker.ts
The system uses these Redis commands:
# Add to queue (left push)
LPUSH emailQueue "{"email":"user@example.com"}"
# Remove from queue (right pop)
RPOP emailQueue
# Get queue length
LLEN emailQueue
# View all items in queue
LRANGE emailQueue 0 -1
# Delete queue
DEL emailQueue- Never commit
.envfile - It contains sensitive credentials - Use
.gitignore- Already included in project - Use App Passwords - Never use your main Gmail password
- Rotate credentials - Change passwords periodically
- Use environment variables - Never hardcode secrets
# Terminal 1: Start worker
npm run worker
# Terminal 2: Run server (adds email to queue)
npm run dev
# Worker automatically processes the email
# Output: Email sent to shreetejmeshram07@gmail.comContributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the ISC License - see the LICENSE file for details.
Shree - GitHub
- Bull - Job queue inspiration
- Nodemailer - Email sending library
- ioredis - Redis client
- TypeScript - Language
For issues and questions:
- Open an issue on GitHub
- Check existing documentation
- Review error logs in terminal
Happy queuing! π