User login

You are here

Docker: My solution to sending emails from within the container to the host with PHP

Here's my solution to reliably and quickly (low latency) sending emails from the docker container using the hosts email subsystem (in my case Postfix), I had tried using the SSMTP solution but I found it had terrible performance and suffered from random delays and pauses. Knowing the amount of effort that goes into a reliable mail subsystem I decided to cut SSMTP out of the picture.

In short: I am mounting a mailspool directory that the container dumps its emails to, and process that from the host, this means there is zero network activity to wait for, and faults well if there's a problem with the host sending emails

volumes:
  - ./mailspool.sh:/mailspool.sh
  - ./mailspool:/mailspool

 

In PHP I set my sendmail_path to a small custom script (that is chmod+x) used to write to the mailspool directory

[mail function]
  sendmail_path = /mailspool.sh
  sendmail_from = noreply@mysite.com

 

The mailspool.sh just writes a file for each mail item

#!/bin/bash

cat > /mailspool/mail.`date +%s%N`

 

 

And then on the host, I use a script I like to call "spoolrunner.sh"

 

#!/bin/bash

# Use postqueue -p to get a list of whats in the queue

find $1 -type f|while read fname
do
  # Pass it to sendmail, -t means to extract the recipient from the command line
  cat "$fname"|/usr/sbin/sendmail -t
  if [ $? -eq 0 ]
  then
    rm -f "$fname"
  fi

# Safety check
if [ -f "$fname" ]
then
  echo "rm did not work"
  exit 1
fi

done

The clever part here is the use of the -t option, "Extract recipients from message headers. These are added to any recipients specified on the command line."

This script then runs from a crontab every minute.

This enables us to feed the email straight into the mail subsystem.

I find that decoupling the actual mail sending from the saving of the mail item greatly decreases user interface latency (espicially in this case of a large forum that uses AJAX Comments), the feedback is almost instantenous because there's no waiting for network IO to occur that a mail has been sent.

To be a docker purist, it could be argued that this should go into a separate container running postfix