How to improve the way WordPress websites send email
Is there a better way to send emails through WordPress? Find out why the default method could cause deliverability and server issues. Plus, get insights into how to use a viable, open-source alternative.
If you’re using the default PHP mail() function to send email via WordPress, you could be experiencing deliverability issues or server problems, especially with high volume sending. Thankfully, there’s a more reliable way. With the right solutions, you can use simple mail transfer protocol (SMTP) servers instead.
For all its email communication, WordPress has a special function called wp_mail() that, in a default environment, uses the phpMailer open-source library to construct the email, set the appropriate headers, handle HTML and plain/text versions, then queue the mail for delivery. Under the hood, phpMailer defaults to using the built-in PHP function called mail().
On most systems, PHP's mail() function simply calls whatever executable is set in the sendmail_path configuration directive. That program reads the standard input for the headers, mail body, attachments, etc., and performs various checks. For example, it checks that the recipient’s address is valid.
If everything looks good, depending on the system configuration, this program will usually send the mail through a local SMTP server or place it in a queue to be processed by the local SMTP server later.
Unfortunately, this method isn’t the best for email deliverability or large volume sending.
Table of content
Table of content
The problem with how WordPress sends email
Queuing the mail for the local SMTP server is quite efficient since PHP's mail() can return immediately, without having to wait for the message to actually be sent.
However, the local SMTP server itself may quickly become a bottleneck. That’s because it may have to communicate with hundreds of third-party mail transfer agents (MTAs) and keep track of every mail, retry sending on failure, etc. This can amount to a lot of work for a server that wasn't designed to be a mail server.
And that's just one part of the problem. The second and bigger problem is deliverability. You'll notice that a large portion of mail sent directly from web servers will often end up in the junk/spam folder, due to incorrect or incomplete configuration of email authentication protocols (SPF, DKIM, etc.) which can be tricky to set up. The reputation of the web server's IP address will also play a huge role in deliverability.
And in shared hosting environments, it's even trickier, because you (usually) have only one SMTP server, but multiple domains, "from" addresses and signatures, which is really hard to get right, and even harder to keep clean and prevent abuse.
This is why most hosting providers, especially around the managed WordPress hosting services, will rate-limit and filter all outgoing mail. This is not very useful, especially in e-commerce, where email is more frequent and so crucial to success: abandoned carts, watch lists, special offers, etc.
The majority of hosting platforms will recommend using a third-party transactional mail service, such as Mailgun, to address all these issues.
The benefits of a transactional email service
Mailgun and other transactional email services will take care of delivering mail as quickly and efficiently as possible. They'll set the appropriate mail headers, signatures, etc., and advise on setting correct DNS records for your domains, which improves the chances of your messages reaching recipients' inboxes.
Mailgun offers tons of additional features as well, such as email validations, reputation checks, logging, analytics, A/B testing, and more.
All that's left for the website owner, is to get the message from their WordPress application, into Mailgun's queue. There are multiple ways to do that.
How to set up Mailgun via SMTP with WordPress filters
Most WordPress developers are familiar with the concept of actions and filters when it comes to WordPress, and creating a small, custom, must-use plugin would be the leanest and quickest way to get started with Mailgun:
This creates a function hooked to the phpmailer_init action in WordPress, which configures the phpMailer library to send email using an external SMTP server. The username and password can be obtained (or reset) in your Mailgun dashboard.
Once active, this code snippet will prevent phpMailer from using PHP's mail() function and instead route all outgoing email to Mailgun's SMTP servers. You can verify this by sending yourself a password recovery email for example, and watching the Logs section in your Mailgun dashboard.
How to use an SMTP WordPress Plugin
Writing your own little plugin is not always a great option, especially for somebody who is unfamiliar with the PHP programming language or how WordPress actions and filters work. The alternative approach is to use a ready-made plugin.
Mailgun's plugin is a great option that, in addition to sending via SMTP, can also send outgoing messages using Mailgun's HTTP API. This is especially good for shared hosting environments where any outgoing SMTP communication is simply blocked to prevent abuse.
The API credentials can also be located in your Mailgun dashboard.
There are other SMTP plugin options too, which may come in handy if you're looking to send through a third-party SMTP server other than Mailgun.
Performance considerations and alternatives
One thing to keep in mind, when using these plugins or snippets to have WordPress deliver mail to a third-party SMTP service, you're compromising on application performance.
Instead of simply passing in some text to the local sendmail system executable, these plugins force WordPress to do a lot more work. That includes opening a new connection, performing a TLS handshake, and authenticating using SMTP with a third-party external service. For large-volume sending this may not be an option at all, just because of the latency factor alone.
There's a very detailed description of these performance problems in the article wp_mail() is not broken, where we used the Sail WordPress profiler to measure the time taken to send 20 emails. The SMTP plugins performed up to 90x slower than the default sendmail method.
The better alternative is to use a combination of both a local queue and a transactional mail service. This can be done by using a local MTA, such as Postfix, in an SMTP-relay mode, where it will act as a local SMTP server. But anything it receives will simply be relayed to the third-party service, such as Mailgun.
This ensures that WordPress does not have to do any heavy lifting when it comes to sending mail and also improves email deliverability by sending it via Mailgun.
Keep in mind, this method does mean that you'll need root-level privileges to install and configure this software on your server. So, it's slightly more work than a simple WordPress plugin. However, if you use Sail to deploy and manage WordPress on DigitalOcean, then you can have this exact configuration in a single blueprint:
This blueprint will install and configure a Postfix instance on your server, to relay emails to Mailgun's SMTP servers. You'll be asked for the SMTP username and password, which you can get or reset from your Mailgun dashboard.
If you're not using Sail and would rather do things manually, here's a great guide on how to set up a local relay with Postfix on Ubuntu Linux.
Choose a reliable way to send email with WordPress
For many companies, email is a vital part of the business. There needs to be a trustworthy method for sending messages, especially transactional emails. If you’re a high volume sender, developers should consider WordPress email solutions other than the default option.
One of the best things about using open source solutions like WordPress is that developers have access to all sorts of resources, including plugins and free solutions. Combining Mailgun with Sail CLI is an excellent example of how developers can scale WordPress applications and implement a better way to send email through the platform.
Konstantin Kovshenin is a WordPress Core contributor, public speaker, and plugin developer, an expert in WordPress performance, scaling, and security.
Build Laravel 10 email authentication with Mailgun and Digital Ocean
When it was first released, Laravel version 5.7 added a new capability to verify user’s emails. If you’ve ever run php artisan make:auth within a Laravel app you’ll know the...
Here’s everything you need to know about DNS blocklists
The word “blocklist” can almost seem like something out of a movie – a little dramatic, silly, and a little unreal. Unfortunately, in the real world, blocklists are definitely something you...