Simple steps to setup WordPress SMTP email without a plugin

Simple steps to setup WordPress SMTP email without a plugin

Recently a reader of my blog asking on how to setup WordPress mail. It turns out it take a just a few simple steps to make the WordPress SMTP email works without a plugin.

I never pay much attention to the WordPress mail since the beginning of this website 4 years ago. But with this site gaining attraction steadily, it is time to setup the WordPress mail properly.

There are many of WordPress plugins available, free or payable, and even some crazy one asking for monthly subscription, I generally try to minimise the installation of plugins, and very often what those plugins do in the background could be very simple. My tinkering curiosity also means that I like to figuring out how exactly things work behind the scene.

It turns out it take just a few simple steps to make the WordPress mail works without a plugin!

First of all, what I'm going to describe here works on Raspberry Pi which is based on Raspberry Pi OS (formerly called Raspbian), which is a variation of Debian, if you are using different OS, part of the system installation and commands may vary. Secondly, it is assumed that you are comfortable of doing some command line configuration over a linux system, and you are either running on your own WordPress theme or a child theme that you could modify the configuration of the theme functions.

The steps to make the WordPress mail works can be summarised as:

  1. Install and configure mSTMP;
  2. Setup PHP configuration to use mSMTP;
  3. Setup WordPress configuration;

Step 1 - Intall and configure mSMTP

Since Debian Buster release (same for Raspberry Pi OS) in march 2019, it drops the support of sSMTP, and recommends to use mSMTP.

mSMTP is a free, open-source SMTP client that can be used to forward mails to an SMTP server (such as your gmail or outlook) which takes care of the final email delivery. To use mSTMP with a mail user agent (MUA), create a configuration file with your mail account(s) and tell your MUA to call mSMTP.

By default, mSMTP is not installed by the Raspberry Pi OS (Buster), but it can be installed with simple command:

sudo apt-get install msmtp msmtp-mta

The mSMTP read the configuration from a configuration file called msmtprc about the settings of your email provider. We need to create the configuration file:

sudo nano /etc/msmtprc

and copy the following information and modify it to match your email access credentials.

# default common settings
defaults
port		587
auth		on
tls		on
tls_starttls	on
tls_trust_file	/etc/ssl/certs/ca-certificates.crt
logfile		/var/log/msmtp.log

# gmail settings
account		gmail
host		smtp.gmail.com
from		your-username@gmail.com
user		your-username
password	your-gmail-password

# outlook smtp settings
account		microsoft
host		smtp.office365.com
from		your-username@hotmail.com
user		your-username@hotmail.com
password	your-outlook-mail-password

# set a default account
account		default: microsoft

As you can see from the configuration file msmtprc that it consists of three sections, and I will explain in details so that you can modify it based on your needs.

The first section of the configuration file are the parameters that are common across all email service providers, it specify the port, and security protocol settings, and whether login authentication is required, and finally where the log file should be kept.

mSTMP allows you to keep multiple email service provider configurations in the msmtprc. Two email providers' configurations are provided in my msmtprc example file, they are gmail and microsoft, microsoft configuration applies to outlook.com, live.com, hotmail.com, and office365.com mail services. Both of those configurations have been tested by me, if you uses an email provider other than those, you should consult your email service provider on how to configure an email client.

The account under each email configuration section is just a string for identifying your email service provide, it could be anything you like, for example, you could call your gmail account as "google_mail" if you like.

Please noted that user means the username of your email account, and this varies from each service provider, for example, in the case of gmail, the username is your email address without the domain name, but in microsoft, the username is exactly the same as your email address.

The last line in the configuration file account default: microsoft specified which email provider should be used as the default when multiple email configurations are stored in msmtprc. The value of the default must match whatever you used for the account name in each service provider, if you have a typo or incorrect name for the default value, the configuration of the first service provider will be used to send emails.

In case you don't have ca-certificates installed (check if /etc/ssl/certs directory exists), you will need to install it with:

sudo apt-get install ca-certificates

if you set the log file as I did in the /var/log/ directory, the directory is in general requires root access, we should create a dummy log file and make it accessible by the msmtp to avoid "Permission denied" error.

sudo touch /var/log/msmtp.log
sudo chown user:group /var/log/msmtp.log

Remember to replace user:group to the username and group that you used for accessing your Raspberry Pi.

mSTMP run as a daemon in the background, once the configuration file has been saved, we can now restart the service with:

sudo systemctl restart msmtpd.service

To make sure that there is no error, run the following command to check the status:

sudo systemctl status msmtpd.service

To test our settings actually work, create a text file testmsmtp.txt as shown below, there are ways to send an email via command line without creating an email file, but I thought it is kind of good to keep some useful information in a text file and use it as a test email.

From: User Name <your-username@hotmail.com>
To:   Recipient <recipient@example.com>
Subject: Testing msmtp

This is an email sent using MSMTP.

The configuration file for msmtp is at /etc/msmtprc

To send this file as email, run:
cat testmsmtp.txt | msmtp recipient@domain.com

msmtp is run as a daemon with systemd:
sudo systemctl status msmtpd.service

The email address in the From must match the smtp email address you used in your msmtprc for the email provider. The email address in the To can be anything, but if you don't have the line in the text file, you will receive the email with Undisclosed recipients:; on the received email.

Send the email with this command line and check your email inbox:

cat testmsmtp.txt | msmtp recipient@domain.com

Step 2 - Setup PHP configuration to use mSMTP

So now the mSMTP works, we need to tell PHP to use our mSMTP. The first thing is to point the sendmail_path in php.ini to the msmtp. The actual path for php.ini depend on the type of web server you are using (apache, nginx, etc.) and the PHP version that you had installed on your Raspberry Pi. I'm running nginx with PHP version 7.3.

sudo nano /etc/php/7.3/fpm/php.ini

Press ctrl-W to search for "sendmail_path", uncomment the line and edit it so that it looks like this:

sendmail_path = /usr/bin/msmtp -C /etc/msmtprc

Save the file and reload the nginx server for the PHP to use the new configuration, and check the server status to make sure there is no error:

sudo service nginx reload
sudo service nginx status

Let's create a simple PHP script called sendmail.php for sending email via PHP mail() function:

<?php

$to = "recipient@domain.com";
$from = "recipient@example.com";
$subj = "sending email from php mail()";
$body = "This email is sent using php mail() function which rely on your msmtp service.";

mail($to, $subj, $body);
?>

Run the script to send the mail:

php sendmail.php

Check your email box, you should be able to receive an email sent by the PHP script.

Step 3 - Setup WordPress configuration

We have both msmtp and PHP mail() working, now let's setup WordPress to send mail via SMTP. WordPress wp_mail() function relies on the PHPMailer class to send email through PHP's mail function. The phpmailer_init action hook allows you to hook to the phpmailer object and pass in your own arguments, including telling the phpmailer instance to use SMTP for sending the email. This is in the nutshell what most of the WordPress SMTP email plugins do - to pass in the necessary parameters to the phpmailer!

In order to add the action hook, we need to add it to the functions.php of the child theme of the WordPress theme that you are using. Unless you have a WordPress theme that you developed yourself, you should not modify the functions.php on the main theme, and if you don't have a child theme, you should create one.

If your child theme doesn't have a functions.php yet, here is a good summary on WordPress functions.php child theme to see how to create one.

The functions.php should be located at your WordPres directory ../wp-content/themes/theme-name-child/ where theme-name is the name of whatever WordPress theme you are using. Open the functions.php and add the following action hook to the end of file, and save it.

/**
 * This function will connect wp_mail to your authenticated SMTP server.
 * All SMTP_CONSTANTS are defined in wp-config.php
 */
add_action( 'phpmailer_init', 'send_smtp_email' );
function send_smtp_email( $phpmailer ) {
	if ( ! is_object( $phpmailer ) ) {
		$phpmailer = (object) $phpmailer;
	}

	$phpmailer->Mailer     = 'smtp';
	$phpmailer->Host       = SMTP_HOST;
	$phpmailer->SMTPAuth   = SMTP_AUTH;
	$phpmailer->Port       = SMTP_PORT;
	$phpmailer->Username   = SMTP_USER;
	$phpmailer->Password   = SMTP_PASS;
	$phpmailer->SMTPSecure = SMTP_SECURE;
	$phpmailer->From       = SMTP_FROM;
	$phpmailer->FromName   = SMTP_NAME;
}

For security reason, we don't want to add email user name and password directly into this function.php, we will use wp-config.php to keep those data.

Add the following to the wp-config.php, those should be added right after the line /* That's all, stop editing! Happy blogging. */ or somewhere BEFORE the constant ABSPATH (if applicable) is defined.

/*
 * Set the following constants in wp-config.php
 * These should be added somewhere BEFORE the
 * constant ABSPATH is defined.
 */

define( 'SMTP_HOST',   'smtp.office365.com' );          // The mail server name
define( 'SMTP_PORT',   '587' );                         // SMTP port number
define( 'SMTP_SECURE', 'tls' );                         // Encryption system tls
define( 'SMTP_AUTH',    true );                         // Use SMTP authentication
define( 'SMTP_USER',   'your-username@hotmail.com' );	// Username for SMTP authentication
define( 'SMTP_PASS',   'your-email-password' );		// Password for SMTP authentication
define( 'SMTP_FROM',   'your-username@hotmail.com' );	// SMTP From email address
define( 'SMTP_NAME',   'microsoft' );			// This should match account default:microsoft setting in msmtprc 

As you can see the information that we trying to pass to the phpmailer is quite similar to what we setup in the msmtprc, instead of having phpmailer to read and parse the data from msmtprc, we just pass it in via wp-config.php.

We are done! Go to your WordPress contact form or user comment form to create a message, you will then receive the contact form/comment message as an email in your email inbox.

If you have Aksimet Spam Protection plugin activated, the message you sent may take a couple of minutes to reach your inbox. If you still don't receive the email by then, check your WordPress Admin Dashboard under the Comment section and your email spam folder, or the msmtp log for diagnostic.

I hope this not only help you to setup your WordPress SMTP email, and you get better idea on how exactly WordPress mail, PHP mail and msmtp works, all done without a bloated plugin!

8 comments by readers

  1. I am hosting a wordpress site on a Pi situated behind a reverse proxy server (nginx). The reverse proxy server terminates the SSL connection and communicates with the website via http on my local network. How should I go about configuring SSL in this instance?

      1. Henry

        Thanks very much for this tutorial. Everything is working as it should.

        One question though, the email notification sent from the website has my gmail address as the sender. Is there a way I could alias this to “info@websitename.com?”

  2. Thank you so much for putting this together. It was quite helpful when setting up wordpress on a Caddy server running on a RPi

  3. Hi,

    Thanks for sharing this useful info. I host my WordPress site on an VPS with Ubuntu and am trying to set up the SMTP with Amacon SES without any plugin. I found your Step 3 – Setup WordPress configuration seems to do a redundant job as the Step1 + Step 2 do? Please correct me if I’m wrong but it looks like one can just choose to do either Step1 + Step 2 or just Step 3 to get the same result?

    Regards,
    Acon

    1. Yes, the php mail() function rely on system utility such as sendmail or msmtp to send the mail. However, phpmailer which WordPress based on does not seems to need the support from linux system. I only find out this later on, but at the time when I was trying, it doesn’t work for me without the proper setup of the linux msmtp.

  4. Thanks! I was looking for a lightweight SMTP sender to work with webmin on RPI and msmtp is just perfect for that.

    Just a couple of remarks:

    – there are some access violation issues with /var/log/msmtp.log due to apparmor so instead I use option “syslog LOG_MAIL” in /etc/msmtprc, it will log msmtp activity in /var/mail.log

    – I had been using the free “Easy WP SMTP” WordPress plugin on the same RPI to send mail directly to my ISP SMTP over STARTTLS and it works well … unless there is a connectivity issue (it won’t retry sending). Instead of tinkering with functions.php to use msmtp, I’ve kept the plugin but now I’m pointing it to 127.0.0.1 to use msmtp for better logging and overcome connectivity issues (although I still need to simulate a network problem).

    Thanks again.

Leave a Reply to David Parkinson Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.