When integrating Amazon SES with your server's email infrastructure, the most efficient approach is to configure Postfix as an SMTP relay. This creates a centralized email gateway that handles all outgoing mail traffic, regardless of whether it originates from PHP mail(), Python apps, or system utilities.
Before proceeding, ensure you have:
- A verified SES domain or email address
- Postfix installed (v2.7+)
- SES SMTP credentials (not AWS root credentials)
- Basic firewall rules allowing outbound traffic on port 587
# Install required packages
sudo apt-get install postfix libsasl2-modules -y
# Main configuration in /etc/postfix/main.cf
relayhost = [email-smtp.us-east-1.amazonaws.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_tls_note_starttls_offer = yes
Create /etc/postfix/sasl_passwd
with your SES SMTP credentials:
[email-smtp.us-east-1.amazonaws.com]:587 YOUR_SMTP_USERNAME:YOUR_SMTP_PASSWORD
Then secure and compile the credentials:
sudo chmod 600 /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd
Verify your configuration with a test email:
echo "Test email from Postfix" | mail -s "SES Test" recipient@example.com
For PHP Applications
No code changes needed if using mail(). For frameworks like Laravel, update your .env
:
MAIL_MAILER=smtp
MAIL_HOST=localhost
MAIL_PORT=25
MAIL_ENCRYPTION=null
For Python Applications
Configure Django's settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25
Check Postfix logs for errors:
sudo tail -f /var/log/mail.log
Common issues include:
- SASL authentication failures (verify credentials)
- Port blocking (check firewall)
- DNS resolution problems
- Implement proper logging and monitoring
- Set up SES sending limits and monitoring
- Consider using separate configuration files for different environments
When managing heterogeneous systems (PHP applications using mail(), Python scripts, and CLI utilities), configuring each component separately for Amazon SES creates maintenance overhead. The optimal solution involves setting up Postfix as a local SMTP relay that transparently routes all outgoing mail through SES.
[Your Applications] → [Local Postfix] → [Amazon SES] → [Recipients]
(mail()/CLI/Python) (localhost:25) (SMTP Interface)
1. Install Required Packages
# Ubuntu/Debian
sudo apt-get install postfix libsasl2-modules
# RHEL/CentOS
sudo yum install postfix cyrus-sasl-plain
2. Configure Postfix for SES
Edit /etc/postfix/main.cf
:
relayhost = [email-smtp.us-east-1.amazonaws.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_tls_note_starttls_offer = yes
3. Set Up SES Credentials
Create /etc/postfix/sasl_passwd
:
[email-smtp.us-east-1.amazonaws.com]:587 YOUR_SES_SMTP_USERNAME:YOUR_SES_SMTP_PASSWORD
Then secure and compile the credentials:
sudo chmod 600 /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd
PHP mail() Function
Configure php.ini
:
sendmail_path = /usr/sbin/sendmail -t -i
Python Applications
Example Django email settings:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25
Send a test email from command line:
echo "Test message" | mail -s "SES Test" recipient@example.com
Check Postfix logs for debugging:
tail -f /var/log/mail.log
- Authentication failures: Verify IAM user has
ses:SendRawEmail
permission - Port 587 blocked: Check AWS Security Group outbound rules
- DKIM failures: Ensure domain verification in SES console