More-reliable email in WordPress 6.9

Emails sent from WordPress will be more reliable in WordPress 6.9 thanks to a few updates and bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority.-fixes to the wp_mail() function.

The sender address is extensibly configured.

The sender address, also known as the Envelope-From, the MAIL FROM, the Return-Path (and even more), is the address where other email servers send “bounce messages” when they can’t deliver a message. Since WordPress 4.7.0 this value was being set by the outgoing mail server and would often end up misconfigured1. That doesn’t sound like it should be a big problem — a site may not receive those notifications from failed delivery — but it’s a bigger problem because of the Sender Policy Framework (SPF) and DMARC systems which help prevent the transmission of spam. They reject these emails entirely.

Thanks to the change in [61010], WordPress 6.9 sets the sender address in an extensibleExtensible This is the ability to add additional functionality to the code. Plugins extend the WordPress core software. way:

  • If a From email headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. is present it uses the From address. Otherwise it defaults to wordpress@home_url(), where home_url() is “the URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org for the current site where the front end is accessible.”
  • Plugins can then filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. the sender address via the wp_mail_from filter in the case the inferred or default address is incorrect2.

For those with custom email configurations it may be necessary to hook into the wp_mail_from filter. If your site was relying on a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party to work around this issue before, or you relied on the phpmailer_init filter to do so, you may no longer need to do that. Otherwise, without any effort on your part, WordPress 6.9 should become more reliable out-of-the-box at sending emails.

The Encoding headers are protected between calls.

wp_mail() calls a $phpmailer global object to actually send emails, meaning that certain state is shared between calls for a given PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher request. Internal logic in the PHPMailer class looks for certain factors in a message that it uses to set or change the Encoding headers in outbound emails. Because this object is global, those encoding changes persisted and, in some cases, would apply to successive emails and cause problems when trying to read them.

In [61131] the internal encoding is reset before sending emails so that PHPMailer sends the appropriate encoding type for each email, based solely on the server configuration and specifics in that message.

Multipart messages are assigned the proper Content-Type.

For the past seventeen years there was a lurking bug in how WordPress interacts with PHPMailer for multipart messages. Ironically, the bug was introduced in a patchpatch A special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing. meant to address this specific case, but an oversight left WordPress sending a corrupted ContentType to PHPMailer. In these cases, PHPMailer would further corrupt the outbound message because of this invalidinvalid A resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. content type. In rare cases this led to a duplicate Content-Type header, but the normative expression was corrupting the multipart boundaries.

This complicated interaction is resolved in [61201] which simplifies the previous fix by relying on PHPMailer’s facilities for setting the content type rather than attempting (erroneously) to manually specify that header.

Acknowledgements

Props to @jorbin, @sirlouen, @stankea, and @westonruter for reviewing this post, and to @websupporter and @stankea for providing expertise knowledge on the interactions of the sender address and SPF/DMARC/DKIM.

  1. Many mail servers auto-generate a sender address from the system user running on the server and the local server hostname, such as www@node-14-dc3.example.com. ↩︎
  2. This could be the case for sites with more advanced email setups, particularly those which send emails from a subdomain or different domain than on which the site is hosted. ↩︎

#6-9, #dev-notes, #dev-notes-6-9, #email