Reduce the risk of email rejection by making WordPress send emails via SMTP if DKIM is configured

Originally published on the Bytemark forum

I recently migrated yet another WordPress site from a Turnkey Linux install to join my others on Bytemark Symbiosis. As I’ve briefly mentioned elsewhere, this went without major problems.

I also decided to configure SPF and DKIM as part of my plan to finish migrating mail services over. However, I didn’t consider the fact that this has an impact on the deliverability of emails sent from WordPress and presumably other similar PHP-based web applications.

I’ve been using a catch-all forwarding rule and spotted a rejected email from Yahoo! Mail. The rejected email was a blog post that was shared by email using WordPress JetPack sharing. The rejection notice quoted 554 5.7.9: Message not accepted for policy reasons. The explanatory URL clarifies:

Your email failed one or more of the following industry-wide authentication checks that Yahoo uses to verify emails are truly sent from the domains they claim to originate from.

It goes on to briefly explain DKIM, SPF and DMARC (not currently implemented in Symbiosis).

Thankfully, this is a solvable problem – in fact, it’s not even really a problem, as Yahoo! Mail is just doing its job by checking for correct DKIM headers.

However, WordPress doesn’t make solving it obvious. Chad Butler has done a ton of investigation into WordPress’s email woes, pointing the finger at the wp_mail function – a “wrapper” for phpmailer. The solution is to force WordPress to use SMTP via phpmailer. Here are two suggested approaches:

  1. Edit your theme’s functions.php to include an extra code snippet that configures WordPress to use SMTP to send email.
  2. Use an extra plugin to bring this functionality to all themes and WordPress email functions. Chad recommends WP Mail SMTP which I’ve just deployed and tested briefly with WordPress 4.0.1 (this may useful for multi-site setups too).

With both approaches, there are some Symbiosis-specific things you should be aware of (I’ll use the standard Symbiosis examples here):

  • You need to create a mailbox first, if that isn’t obvious, e.g. blog.
  • The SMTP host is mail.my-brilliant-site.com (on default port 25).
  • The username must follow the example blog@my-brilliant-site.com. Obvious, perhaps, but I always forget this.
  • SMTP requires authentication.
  • I used TLS encryption successfully.

If you’ve tweaked your Symbiosis install to be non-standard, then you’ll have to reflect that here but otherwise it’s pretty much the same as setting up a mail client to send mail.

If you’re using the WP Mail SMTP plugin, then you can send a test email. I recommend trying to send it to a Gmail or Yahoo! Mail address. The result you’re looking for is bool(true) – in addition to the test email of course, which you can examine to ensure it includes the right DKIM-Signature header.

I hope this helps with any head-scratching you might have also been doing!

  • Hey Josh

    Thanks for the post, but I’ll just ask if it is entirely impossible to add DKIM signature to emails which are sent using the wpmail thing? I’m asking this because while I can use SMTP, my host ain’t happy with that. I get a SMTP error (in the debug) looking something like “XYZ Host does not allow unsolicited SMTP” for some of the emails sent through SMTP.
    I checked out a plugin called Amazon SES DKIM Mailer, but haven’t managed to get it to work for now. When I point it to the Private Key, it does not add the DKIM signature.

  • Hi, I am trying to use DKIM in my outgoing emails but unfortunately after installing WP Mail SMTP I could not see it attached to the emails.

    Can please guide me if there is any additional step required to make DKIM work in WordPress with WP Mail SMTP and cpanel/whm in the server? I already have the DNS entries configured, but when sending a test email from WP Mail SMTP the DKIM headers are empty.

    [“DKIM_selector”]=>
    string(0) “”
    [“DKIM_identity”]=>
    string(0) “”
    [“DKIM_passphrase”]=>
    string(0) “”
    [“DKIM_domain”]=>
    string(0) “”
    [“DKIM_private”]=>
    string(0) “”