How to Configure Docker Containers to Send Email via Host’s Postfix SMTP Server


2 views

When running applications in Docker containers that need email functionality, many developers encounter the "Relay access denied" error when trying to use the host's Postfix server. The root cause typically stems from network isolation and Postfix's security configuration.

Your current Postfix configuration includes the Docker network in mynetworks (172.17.0.0/16), but the error shows connections coming from 172.18.0.5. This indicates you're likely using a custom Docker network:

# Check your container's network
docker inspect <container_id> | grep IPAddress

# The solution is either to:
# 1. Use the correct network in mynetworks
# 2. Or better, use the bridge network that's already configured
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16 172.18.0.0/16

For Docker containers to communicate with the host's Postfix service, you have several networking approaches:

# Option 1: Use host networking (simplest approach)
docker run --network host my_image

# Option 2: Use bridge networking and access via host's IP
sendemail -s 172.17.0.1:25 -f sender@domain.com -t recipient@email.com

# Option 3: Create a custom network with proper routing
docker network create my_app_network

Here's a tested configuration that works with Postfix + Docker:

# In /etc/postfix/main.cf
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16 172.18.0.0/16

# For containers using sendemail:
sendemail -s host.docker.internal:25 -f valid@yourdomain.com -t recipient@email.com

# For Python applications using smtplib:
import smtplib
server = smtplib.SMTP('host.docker.internal', 25)
server.sendmail('from@example.com', 'to@example.com', 'Test message')

If you still encounter problems, check these aspects:

# 1. Verify Postfix is listening on all interfaces
netstat -tulnp | grep :25

# 2. Check SELinux/apparmor permissions
getenforce
# If enforcing, consider:
setsebool -P httpd_can_network_connect on

# 3. Test connectivity from container
docker exec -it <container> bash
telnet 172.17.0.1 25

For production environments, consider these security enhancements:

# Create separate credentials for containers
echo "[host.docker.internal]:25 username:password" > /etc/postfix/sasl_passwd

# Configure SASL authentication
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname

When trying to send emails from within Docker containers to an external Postfix SMTP server running on the host machine, you'll often encounter the "Relay access denied" error. This occurs because:

Nov 27 21:42:54 guest8 postfix/smtpd[14979]: NOQUEUE: reject: RCPT from unknown[172.18.0.5]: 
454 4.7.1 <katanophoros@gmail.com>: Relay access denied

The key elements in your setup:

  • Host Postfix version: Debian/GNU
  • Container network: Docker default bridge (172.17.0.0/16)
  • Current mynetworks setting: 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16

First, verify your Docker network configuration:

docker network inspect bridge

Then update Postfix's mynetworks parameter to include both:

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16 172.18.0.0/16

For development environments, you can run containers with host networking:

docker run --network host your_image

Then your sendemail command would be:

sendemail -s localhost:25 -f no-reply@ellak.org -t recipient@example.com -u Subject -m Message

Configure SASL authentication in Postfix:

# /etc/postfix/sasl_passwd
[mail1.ellak.gr]:587 username:password

postmap /etc/postfix/sasl_passwd
systemctl restart postfix

Check Postfix connectivity from container:

telnet 172.17.0.1 25

View real-time Postfix logs:

tail -f /var/log/mail.log

Here's a working Postfix main.cf snippet for Docker environments:

# Network settings
mynetworks = 127.0.0.0/8 172.17.0.0/16 172.18.0.0/16
inet_interfaces = all

# Relay configuration
relayhost = [mail1.ellak.gr]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous