When attempting to send mail from Docker containers through the host's Postfix installation, we encounter several authentication and header issues. From the maillog, we can see three critical problems:
- Missing Date header (MISSING_DATE)
- Missing From header (MISSING_FROM)
- Missing Message-ID (MISSING_MID)
There are two primary approaches to solve this:
# Solution 1: Direct sendmail binary mounting
docker run -v /usr/sbin/sendmail:/usr/sbin/sendmail:ro your-container
# Solution 2: Proper SMTP configuration
docker run -e SMTP_HOST=host.docker.internal your-container
The first approach is simpler but has security implications. The second approach is more robust but requires proper Postfix configuration.
Edit your Postfix configuration (/etc/postfix/main.cf):
# Allow Docker subnet
mynetworks = 127.0.0.0/8 [::1]/128 172.17.0.0/16
# Force proper headers
smtpd_helo_required = yes
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
For applications that don't set proper headers, create a wrapper script:
#!/bin/sh
{
echo "From: youruser@yourdomain.com"
echo "Date: $(date -R)"
echo "Message-ID: <$(date +%s).$(openssl rand -hex 8)@yourdomain.com>"
echo "Content-Type: text/plain; charset=UTF-8"
echo ""
cat -
} | /usr/sbin/sendmail -t "$@"
Ensure your OpenDKIM configuration includes:
AutoRestart Yes
AutoRestartRate 10/1h
UMask 002
Syslog Yes
SyslogSuccess Yes
LogWhy Yes
Canonicalization relaxed/simple
Mode sv
SubDomains no
Create a test container with:
docker run --rm -it alpine sh -c "echo 'Test message' | sendmail -f valid@yourdomain.com recipient@example.com"
Check your mail logs to verify proper header injection and DKIM signing.
For containers that can't use the host's sendmail:
# Dockerfile snippet
RUN apt-get update && apt-get install -y ssmtp
COPY ssmtp.conf /etc/ssmtp/ssmtp.conf
# ssmtp.conf contents
mailhub=host.docker.internal:25
hostname=yourdomain.com
FromLineOverride=YES
UseTLS=NO
UseSTARTTLS=NO
When running applications in Docker containers that need email functionality, we often want to leverage the host's existing Postfix configuration rather than setting up separate mail services inside each container. The challenge lies in maintaining proper email headers (Message-ID, Date, DKIM signatures) while avoiding spam filters.
The original approach of connecting to Postfix via port 25 from the container results in missing headers because:
Sep 28 23:35:52 dantooine spamd[3175]: spamd: result: . 2 - MISSING_DATE,MISSING_FROM,MISSING_MID
Postfix treats these connections differently than local submissions, often stripping important authentication markers.
The most reliable solution is to mount the host's sendmail binary inside the container:
docker run -v /usr/sbin/sendmail:/usr/sbin/sendmail:ro your-container
This gives containers direct access to the host's mail system while preserving all header processing.
Configure Postfix to accept authenticated submissions on port 587:
# /etc/postfix/master.cf
submission inet n - - - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
Then configure your container to use SASL authentication when connecting.
For better integration, consider these Docker network options:
# Use host network directly
docker run --network host your-container
# Or create a dedicated network
docker network create mail_network
Here's how to send mail from a Python container using mounted sendmail:
import subprocess
def send_email(to, subject, body):
message = f"""To: {to}
Subject: {subject}
{body}"""
process = subprocess.Popen(["/usr/sbin/sendmail", "-t"], stdin=subprocess.PIPE)
process.communicate(message.encode())
send_email("recipient@example.com", "Test", "This is a test email")
After configuration, verify your DKIM signatures are properly added:
cat /var/log/mail.log | grep DKIM
You should see entries like:
opendkim[1234]: ABC123: DKIM-Signature field added
If emails still get marked as spam:
- Check SPF records include your Docker subnet
- Verify reverse DNS matches your sending domain
- Ensure proper FROM headers in your application