dt.iki.fi

Sending email off my (non‑mail) server with sSMTP (and PHP)

This article is originally from 2016, but I edited it a few times. It seems I have to fix my sSMTP setup every now and then... Be aware that some settings depend not only on your system but also on your email provider.

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 email from my server, usually diagnostic messages from services (e.g. SMART daemon, fail2ban), or if someone tries to contact me on my website, sent to my third party email address.

What I really want is sSMTP, an "extremely simple MTA to get mail off the system to a mail hub".

This server runs debian stable (written when jessie was stable, then stretch, now buster).

Previously I had been messing around with dovecot and exim4, which only resulted in breakage, until I realised that these are overkill for my needs.
I purged all packages that contain 'dovecot' and 'exim4' in their names, and performed apt-get --purge autoremove afterwards. Then I went through all leftover configuration/modification in /etc and removed/undid it manually.
There was a lot of it, even after purging the packages.
It seems that even after that some residual configuration files are interfering.
This command: aptitude search ~c will show what is leftover (I should probably have started with that).
This command: aptitude -s purge ~c will simulate the removal, and this: aptitude purge ~c will finally do it.
If you don't want to use aptitude, this has similar functionality:
dpkg -l | grep ^rc to see what residual config files are left over and
for i in $(dpkg -l | grep ^rc | cut -d” ” -f3); do dpkg –purge $i; done
to commit (source).

Installation-up-

With a hopefully clean system, I installed ssmtp: apt-get install ssmtp.

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
$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";
}
?>

General Configuration-up-

sSMTP is not a daemon, it provides the ssmtp binary which can be invoked manually or by other processes. sendmail belongs to ssmtp and is symlinked to ssmtp.
You can check with dpkg-query -S $(which sendmail) and ls -l $(which sendmail).

Edit /etc/ssmtp/ssmtp.conf along these lines:

# Config file for sSMTP sendmail
#
# The person who gets all mail for userids < 1000
# Make this empty to disable rewriting.
#root=

# The place where the mail goes. The actual machine name is required no 
# MX records are consulted. Commonly mailhosts are named mail.domain.com
# (not my mail provider though - it's just domain.com)

# This usually for TLS
#mailhub=domain.com:465
# This usually for StartTLS
mailhub=domain.com:587

# Where will the mail seem to come from?
#rewriteDomain=

# The full hostname
# (can be the server name or an IP address)
#hostname= # probably not required

# Are users allowed to set their own From: address?
# YES - Allow the user to specify their own From: address
# NO - Use the system generated From: address
#FromLineOverride=NO

UseTLS=YES
UseSTARTTLS=YES 

AuthMethod=LOGIN
AuthUser=someone@domain.com
AuthPass=verysecret

Your email provider should provide a page listing servers and ports for SMTP. I gleaned most of this information from my email client's account settings.

Reverse Aliases-up-

Additionally, I had to edit /etc/ssmtp/revaliases thusly:

www-data:someone@domain.com:domain.com:587
root:someone@domain.com:domain.com:587
normal_user:someone@domain.com:domain.com:587

The sSMTP man page has this to say:

A reverse alias gives the From: address placed on a user's outgoing messages and (optionally) the mailhub these messages will be sent through. Example:
root:jdoe@isp.com:mail.isp.com
Messages root sends will be identified as from jdoe@isp.com and sent through mail.isp.com.

The added port :587 seems to be optional; I guess it defaults to whatever ssmtp.conf specifies. However, specifying a wrong port makes sSMTP (or the PHP script calling it) hang.

TLS-up-

sSmtp used to work with UseTLS=YES, but now it requires UseSTARTTLS=YES and the SMTP port required for that; usually 587. I have no idea why (my email client connects just fine over a full TLS connection), but there is a comment under this answer that claims that "Port 465 for SSMTP is deprecated see: en.wikipedia.org/wiki/SMTPS."

Permissions & Ownership-up-

Fix permissions on /etc/ssmtp/ssmtp.conf and /etc/ssmtp/revaliases:

-rw-r----- 1 root mail 111 Mar 23 10:00 revaliases
-rw-r----- 1 root mail 840 Mar 23 11:25 ssmtp.conf

This means that users that want to use sSMTP need to be in the mail group (in my experience contrary to what the arch wiki says; I'm doing this on Debian after all). This is what I had to do to enable my web server's PHP processes to send mail:

# usermod -a -G mail www-data

Sending a test mail-up-

# ssmtp -v recipient_email@example.com

I needed to be root for this.
sSMTP will then wait for you to type your message, which needs to be formatted like this:

To: recipient_email@example.com
From: someone@domain.com
Subject: test email

hello world!

^D

Note the blank like after the subject, everything after this line is the body of the email. Then I pressed Ctrl-D. sSMTP may take a few seconds to send the message before closing (source).

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.

Email providers & Spam Filtering-up-

sSMTP can fail to deliver the mail to the right place, but your email provider can also be picky about accepting it. Essentially we are using sSMTP to use our email provider to send mail to others (or ourselves). One thing both sender & recipient email providers often do not like is making mail look like it comes from somewhere else. To avoid ending up in a spam folder, make sure that the "From:" is always one of your email provider's actual email addresses.

For one email provider I additionally had to set up rewriting in /etc/ssmtp/ssmtp.conf similarly to /etc/ssmtp/revaliases for all involved users:

# /etc/ssmtp/ssmtp.conf:

root=someone@domain.com
normaluser=someone@domain.com
www-data=someone@domain.com

...and disallow users to set their own from address in /etc/ssmtp/ssmtp.conf:

FromLineOverride=NO

This avoids PHP setting something like "root@localdomain" as the "From:" address.

Source