Updated 2026:
ssmtpis no longer actively maintained and has been removed from many Linux distributions. The recommended replacement is msmtp, which provides the same lightweight relay functionality with a nearly identical configuration format and is actively maintained. The approaches described below apply equally tomsmtp; just swap the package name and config file path.
I packaged a standard web application into a Docker container. Everything worked fine until the application needed to send email (an event triggered from inside the container) .
The naive solution is to run an MTA (like Postfix) alongside the application process in the same container. That violates the Docker best practice of one process per container. Instead, use ssmtp (or msmtp) as a lightweight relay client: a single binary that accepts a local sendmail-style call and forwards the message to an external SMTP host.
All four approaches below assume ssmtp is installed in the container. The base configuration relays everything to a configured mailhub:
# /etc/ssmtp/ssmtp.conf
# Catch-all recipient for system mail
root=postmaster
# No MX lookup: specify the SMTP host directly
mailhub=mail.yourdomain.com
# TLS settings
UseTLS=Yes
UseSTARTTLS=Yes
# Credentials (if required by the SMTP host)
AuthUser=postmaster@yourdomain.com
AuthPass=supersecretpassword
Approach 1: External SMTP relay Link to heading
If you have an external SMTP relay (corporate mail server, SendGrid, AWS SES, etc.), point mailhub at it and you’re done. This is the simplest and cleanest option.
Approach 2: Separate Postfix container Link to heading
Run a dedicated Docker container for Postfix and link the application container to it. The application container’s ssmtp.conf points mailhub at the Postfix container’s service name.
docker run --link=postfix-container my-app-that-needs-email
One caveat: if the host is already running an MTA bound to port 25, the Postfix container can’t publish that port: it’s already in use. Plan accordingly.
eea.docker.postfix is a well-maintained Postfix container that works well here.
Approach 3: Relay through the host MTA via docker0 Link to heading
Docker exposes a docker0 bridge interface to all containers on the host:
ip a show docker0
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
inet 172.17.42.1/16 brd 172.17.255.255 scope global docker0
If the host MTA listens on this interface, containers can relay through it by pointing mailhub at the docker0 IP (172.17.42.1 in this example).
Configuring Postfix to listen on docker0 Link to heading
In /etc/postfix/main.cf:
inet_interfaces = 127.0.0.1, 172.17.42.1
mynetworks = 127.0.0.0/8 172.17.42.0/24
Dependency ordering with systemd Link to heading
Postfix must start after the docker0 interface is up. systemd already provides a device unit for it:
systemctl | grep docker0
# sys-devices-virtual-net-docker0.device loaded active plugged
Override the Postfix instance service to depend on it:
systemctl edit postfix@-.service
Add:
[Unit]
Requires=sys-devices-virtual-net-docker0.device
After=sys-devices-virtual-net-docker0.device
Then reload and restart:
systemctl daemon-reload
systemctl restart postfix
Approach 4: Host networking mode Link to heading
Running the container with --net=host gives it direct access to the host’s network stack, including any MTA listening on localhost:
docker run --net=host my-app-that-needs-email
Set mailhub=localhost in ssmtp.conf. This is the simplest configuration, but it comes with a security cost: the container is no longer network-isolated from the host, and it can access any service listening on any port. Use this only when the simplicity trade-off is justified and the container is trusted.