dt.iki.fi

Getting email off my web server with msmtp (and PHP)

My server is not a mail server, and I never learned to make use of UNIX' internal mailing system.
But sometimes I want to get a message from my server, e.g. diagnostic stuff from services (SMART daemon, fail2ban), or if someone tries to contact me on my website, and I want it sent to my email address.

I used to use sSMTP for this, but it seems to stop working about once a year, is mostly unmaintained and said to be insecure.

So now I switched to msmtp. Here's how to set it up as a drop-in replacement for sendmail (just like sSMTP was), so system utilities and PHP can use it.

msmtp-up-

Be aware that some settings depend on the email provider that provides the email address used to send these mails.

apt install msmtp msmtp-mta # the latter provides the sendmail binary

Do not create a config file in ~/.msmtprc but instead edit /etc/msmtprc only.

Example (you can get port, host and TLS settings from your provider's email client configuration):

grep -vE '^#|^$' msmtprc
account default
host domain.com
port 465
tls on
tls_starttls off
syslog LOG_MAIL
from user@domain.com
auth on
user user@domain.com
password xxxxxxxxxxxxxxxxxxxxxx

Test:

echo asdasdasdasd | sudo -u www-data msmtp recipient@domain.tld

Since PHP is using /usr/sbin/sendmail -t -i by default, let's try that:

echo asdasdasdasd | sudo -u www-data /usr/sbin/sendmail -t -i recipient@domain.tld

Did it work? Then let's switch to secure password storage at this point. Most msmtp tutorials use GPG for that. We probably need to initialise GPG first for the www-data user:

sudo -u www-data gpg --full-gen-key

Don't use any passphrases; but keep in mind not to ever use this key for anything else.

If you get this error:

gpg: agent_genkey failed: Permission denied

- try this solution:

ls -l $(sudo -u www-data tty)
sudo chown www-data $(sudo -u www-data tty)

After you're done with the GPG stuff, change ownership back to the original user (if applicable - for me, it reverted after I closed/re-opened the ssh session).

Generate the GPG password file (do this in a tmpfs to avoid leaving traces on your hard drive):

cd /dev/shm
printf '%s' emailaccountpassword > some_file
sudo -u www-data gpg --default-recipient-self -e some_file
mv some_file.gpg /etc/msmtp.pw
rm some_file
chmod 400 /etc/msmtp.pw

Now let's replace the password ... line in /etc/msmtprc with this:

passwordeval gpg --quiet --for-your-eyes-only --no-tty --decrypt /etc/msmtp.pw

Obviously there's still a security issue here, but ultimately there will always remain one if we want to fully automate this and never enter a password manually.

If you intend to use the key pair generated for www-data for anything else, this might not be the best solution. Otherwise, I think it's sufficiently secure. Please contact me if you think otherwise.

Lastly:

chmod 400 /etc/msmtp*
chown www-data:www-data /etc/msmtp*

Now try again to send an email, as above.

If that worked, try again from your website's contact form. If that doesn't work, you need to go searching for helpful log entries. There's /var/log/mail.* which might provide the answers you need. After that it's server logs.

PHP Configuration-up-

PHP by default relies on sendmail to send out e-mail (you can check with grep sendmail_path -r /etc/php*), and most contact form plugins or code snippets rely on that. If you find this configuration option to be commented out (or not present at all) you can check with phpinfo(); most likely you will see sendmail_path /usr/sbin/sendmail -t -i.

This should be enough to make it work. A quick test:

php
<?PHP $sender = 'you@mail.tld'; $recipient = 'you@mail.tld'; $subject = "php mail test"; $message = "php test message"; $headers = 'From:' . $sender; if (mail($recipient, $subject, $message, $headers)) { echo "Message accepted"; } else { echo "Error: Message not accepted"; } ?>

Further reading-up-

https://wiki.debian.org/msmtp
https://wiki.archlinux.org/title/Msmtp