A high-performance, concurrent email campaign dispatcher built with Go. This application reads recipient data from a CSV file, processes email templates, and sends emails concurrently using a Worker Pool architecture.
It also includes a robust Dead Letter Queue (DLQ) mechanism to capture and log failed email deliveries without interrupting the overall campaign execution.
- Read recipient details from a CSV file
- Concurrent email sending using Goroutines
- Worker Pool implementation for efficient processing
- Dynamic email template rendering
- Dead Letter Queue (DLQ) for failed deliveries
- Thread-safe logging using
sync.Mutex - Local SMTP testing with Mailpit and Docker
This project follows an Event-Driven Architecture (EDA) using the Producer-Consumer Pattern, implemented with Go's native concurrency primitives (Goroutines and Channels).
emails.csv
│
▼
Producer (producer.go)
│
▼
Go Channel (Broker)
│
▼
Worker Pool (consumer.go)
│
├── Template Rendering
├── SMTP Email Sending
│
├── Success → Email Sent
│
└── Failure
│
▼
Dead Letter Queue (dlq.csv)
The producer is responsible for:
- Reading recipient information from
emails.csv - Parsing CSV records
- Handling minor formatting inconsistencies (such as leading/trailing spaces)
- Creating
Recipientobjects - Sending recipients into a Go channel
The Go channel acts as a thread-safe communication pipeline between the producer and workers.
It provides:
- Safe communication between Goroutines
- Automatic synchronization
- Backpressure when workers are busy
- Memory-efficient processing
Multiple worker Goroutines consume recipients concurrently.
Each worker:
- Waits for a recipient from the channel
- Loads and executes the email template (
email.tmpl) - Injects recipient-specific data
- Sends the email via SMTP
- Reports failures to the Dead Letter Queue
If email generation or delivery fails:
- The error is captured without stopping the application.
- A
sync.Mutexsafely locks thedlq.csvfile. - The failed recipient and error details are written to the file.
- The lock is released.
- Processing continues with the next email.
This ensures that one failed email does not interrupt the rest of the campaign.
.
├── consumer.go # Worker pool implementation
├── producer.go # Reads recipients from CSV
├── main.go # Application entry point
├── email.tmpl # Email template
├── emails.csv # Recipient data
├── dlq.csv # Failed email log
├── go.mod
└── README.md
Before running the project, make sure you have:
- Go 1.18 or later
- Docker (for running Mailpit)
git clone https://github.com/your-username/email-dispatcher.git
cd email-dispatcherReplace the repository URL with your own.
Mailpit captures outgoing emails locally so you can test email delivery without sending real emails.
docker run -d --restart unless-stopped \
--name mailpit \
-p 8025:8025 \
-p 1025:1025 \
axllent/mailpitdocker run -d \
--restart unless-stopped \
--name=mailpit \
-p 8025:8025 \
-p 1025:1025 \
axllent/mailpitgo run .Open your browser and navigate to:
http://localhost:8025
The Mailpit dashboard will display all successfully sent emails.
Any failed email deliveries will automatically be recorded in:
dlq.csv
Example emails.csv
name,email
John Doe,john@example.com
Jane Smith,jane@example.com
Alice Johnson,alice@example.comThe application uses Go's text/template package.
Example email.tmpl
Hello {{.Name}},
Thank you for joining our campaign!
Best Regards,
Go Email Dispatcher- Producer: Reads recipients from the CSV file.
- Channel: Transfers recipients safely between Goroutines.
- Worker Pool: Multiple Goroutines process emails simultaneously.
- Mutex: Prevents race conditions while writing to
dlq.csv.
This architecture provides:
- High throughput
- Efficient CPU utilization
- Memory safety
- Fault tolerance
- Go
- Goroutines
- Channels
- Worker Pool Pattern
- SMTP
- Go Templates
- Docker
- Mailpit
- sync.Mutex
This project is licensed under the MIT License.
Feel free to use, modify, and contribute.