If your applications need to send emails reliably, an SMTP relay is one of the cleanest solutions.
In this tutorial, we will build a lightweight SMTP relay using Docker and Postfix on Ubuntu. Your applications will send email locally to the relay, and the relay will securely forward mail through providers like Amazon SES, SendGrid, Mailgun, or Gmail SMTP.
This setup is ideal for:
- Laravel applications
- WordPress websites
- Node.js apps
- Dockerized services
- Internal notification systems
- Transactional emails
Architecture
Application
↓ SMTP
Docker Postfix Relay
↓ TLS SMTP
Amazon SES / SendGrid / Mailgun
↓
Recipient Inbox
Prerequisites
Before starting, make sure you have:
- Ubuntu server
- Docker installed
- Docker Compose plugin installed
- SMTP provider credentials
Supported providers include:
- Amazon SES
- SendGrid
- Mailgun
- Gmail SMTP
- Postmark
Step 1 — Install Docker
Update Ubuntu:
sudo apt update
Install Docker:
sudo apt install -y docker.io docker-compose-plugin
Enable Docker:
sudo systemctl enable --now docker
Verify installation:
docker --version
Optional: run Docker without sudo
sudo usermod -aG docker $USER
newgrp docker
Step 2 — Create Project Directory
Create a working directory:
sudo mkdir -p /opt/smtp-relay
cd /opt/smtp-relay
Step 3 — Create Persistent Storage
Create directories for mail queue and logs:
sudo mkdir -p relay
sudo mkdir -p logs
These directories ensure queued emails survive container restarts.
Step 4 — Create Docker Compose File
Create a docker-compose.yml file:
services:
smtp-relay:
image: boky/postfix
container_name: smtp-relay
restart: unless-stopped
ports:
- "25:25"
environment:
# Upstream SMTP provider
RELAYHOST: smtp.gmail.com
RELAYHOST_PORT: 587
RELAYHOST_USERNAME: YourSMTPEnabledGmailUserID
RELAYHOST_PASSWORD: YourGmailPassword
# Allowed sender domains
ALLOWED_SENDER_DOMAINS: wempro.com,pumpsandinstrumentations.com
# Relay hostname
POSTFIX_myhostname: relay.vmi3202307.local
POSTFIX_mynetworks: 127.0.0.0/8 172.16.0.0/12 192.168.0.0/16
POSTFIX_smtpd_recipient_restrictions: permit_mynetworks,reject_unauth_destination
TZ: UTC
volumes:
# Mail queue persistence
- ./relay:/var/spool/postfix
# Optional logs
- ./logs:/var/log
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
Save the file.
Step 5 — Start the SMTP Relay
Launch the container:
docker compose up -d
Verify container status:
docker ps
View logs:
docker logs -f smtp-relay
Step 6 — Test Email Sending
Install swaks:
sudo apt install -y swaks
Send a test email:
swaks \
--to you@example.com \
--from noreply@yourdomain.com \
--server localhost:25 \
--header "Subject: SMTP Relay Test" \
--body "SMTP relay is working"
Successful output:
250 2.0.0 Ok: queued as ...
Step 7 — Configure Your Application
Your applications should connect to:
localhost:25
Example DSN:
smtp://localhost:25
Laravel .env example:
MAIL_MAILER=smtp
MAIL_HOST=localhost
MAIL_PORT=25
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="Your App"
Multiple Domain Support
To allow multiple sender domains:
ALLOWED_SENDER_DOMAINS: domain1.com,domain2.com,domain3.com
Why Use an SMTP Relay?
Benefits include:
- centralized email handling
- provider abstraction
- email queueing
- retry handling
- cleaner application configuration
- rate limiting
- easier provider switching
Important Security Tips
Do NOT Create an Open Relay
Never use:
POSTFIX_mynetworks: 0.0.0.0/0
This will allow the internet to abuse your server for spam.
SPF, DKIM, and Deliverability
For production use, verify your domain with your SMTP provider and configure:
- SPF
- DKIM
- DMARC
Without these, emails may land in spam folders.
Queue Management
View mail queue:
docker exec -it smtp-relay postqueue -p
Flush queue:
docker exec -it smtp-relay postqueue -f
Final Thoughts
A Dockerized SMTP relay is a lightweight and reliable solution for modern applications. By combining Postfix with providers like Amazon SES or SendGrid, you get:
- reliable delivery
- secure outbound SMTP
- local application integration
- retry and queue management
- simplified infrastructure
This setup works especially well for Docker-based deployments and internal application stacks.
Happy emailing!