WordPress 6.9 Broke Email Delivery — The Envelope Sender Change That Silently Killed WooCommerce Emails
· 7 min read
A client messaged me the week after updating to WordPress 6.9: "We haven't received a single order notification since Thursday." The WooCommerce dashboard showed orders processing normally. Payments going through, stock decrementing, customers being charged. But no emails were going out — not order confirmations, not admin new-order alerts, not shipping notifications. Nothing.
This wasn't the usual email deliverability problem where messages land in spam. These emails weren't arriving at all.
The symptom
The PHP error log told me something was fundamentally broken at the sending level:
[09-Dec-2025 11:47:03 UTC] PHP Warning: mail(): Could not instantiate mail function in /var/www/html/wp-includes/PHPMailer/PHPMailer.php on line 1527
Could not instantiate mail function means PHP's mail() call returned false — the server's mail transfer agent rejected the message before it even left the box. This isn't a deliverability issue. It's a sending failure.
I checked WooCommerce's email settings, Action Scheduler, and WP-Cron — all fine. The problem was lower in the stack.
Tracing the root cause
I checked the server's Postfix mail log:
grep "status=" /var/log/mail.log | tail -20
Dec 9 11:47:03 server postfix/sendmail[28491]: fatal: Sender address rejected: Domain [email protected] does not resolve
Postfix was rejecting the envelope sender outright. The -f parameter being passed to sendmail contained an address whose domain the MTA couldn't validate from this server. But this had been working fine on WordPress 6.8 — what changed?
I pulled up the WordPress 6.9 changelog and found it. Trac ticket #49687, changeset [61010]. A change to one line in wp-includes/pluggable.php that had been the same since WordPress 4.7:
Before (WordPress 4.7 through 6.8):
$phpmailer->setFrom( $from_email, $from_name, false );
After (WordPress 6.9):
$phpmailer->setFrom( $from_email, $from_name );
That third parameter — false — had been deliberately preventing PHPMailer from setting the Sender property (the envelope sender / Return-Path / MAIL FROM). With false, PHPMailer left the envelope sender unset, and the server's MTA would use its own default (typically www-data@hostname or whatever the system user was).
Removing false let PHPMailer copy the From address into the envelope sender. That meant PHP's mail() was now called with -f [email protected], telling Postfix: "The envelope sender for this message is [email protected]."
Why this broke things
The logic behind the change was sound in theory. Email authentication (SPF, DKIM, DMARC) relies on alignment between the envelope sender and the From header. If the envelope sender is [email protected] but the From header says [email protected], SPF alignment fails because the domains don't match.
The problem is that setting the envelope sender to match the From address only works if the sending server is authorised to send for that domain. On this client's server, the SPF record for clientsite.com authorised their email provider (Google Workspace), not the VPS IP address. So:
- Before 6.9: Envelope sender was
[email protected](set by MTA). SPF alignment failed, but the email was accepted by the MTA and delivered — landing in spam or passing depending on other factors. - After 6.9: Envelope sender was
[email protected](set by PHPMailer). Postfix checked whether it was authorised to send as that domain, found it wasn't, and rejected the message locally. The email never left the server.
This is a subtle but critical distinction. The old behaviour was "emails might land in spam." The new behaviour was "emails don't send at all." For a WooCommerce store, that's the difference between a minor annoyance and a silent revenue problem.
The immediate fix
I added a one-line filter to the client's mu-plugins directory to restore the pre-6.9 behaviour:
<?php
// mu-plugins/fix-envelope-sender.php
add_action( 'phpmailer_init', static function ( $phpmailer ) {
$phpmailer->Sender = '';
} );
This clears the Sender property after PHPMailer sets it, reverting to the old behaviour where the MTA chooses the envelope sender. Emails started sending immediately.
The proper fix
Clearing the envelope sender is a workaround, not a solution. The real fix is to stop using PHP mail() entirely and send through authenticated SMTP — which I'd been recommending to this client for months.
I set up FluentSMTP with Brevo (their free tier handles up to 300 emails per day, more than enough for this store's ~60 daily transactional emails). With authenticated SMTP:
- The envelope sender is set correctly by the email provider
- SPF passes because the provider's sending IPs are authorised
- DKIM signs every message
- DMARC alignment works automatically
- The WordPress 6.9 change becomes irrelevant — PHPMailer's SMTP transport ignores the
-fparameter entirely
Once SMTP was configured and DNS records (SPF include:, DKIM, DMARC) were in place, I removed the mu-plugins/fix-envelope-sender.php workaround. The client's mail-tester.com score went from failing to 9.7/10.
WordPress reverted the change
The WordPress core team reverted changeset [61010] after reports flooded Trac ticket #64368. The revert acknowledged that "setting the sender address by default has been shown to reduce deliverability for sites that were working correctly in 6.8 and before."
This is a problem WordPress has been circling since 2010 (Trac #14888) and 2012 (#22837). The envelope sender is genuinely wrong by default — it should match the From address for proper email authentication. But fixing it in core breaks the large number of sites that rely on PHP mail() with no SPF configuration. There's no safe default that works for everyone.
If you updated to 6.9 and your emails broke, updating to the latest point release restores the old behaviour. But you'll still have the underlying deliverability problem — you just won't notice it as acutely.
How to check if you're affected
If you're running WordPress 6.9.0 specifically (before the fix was reverted), check your PHP error log:
grep "Could not instantiate mail function" /var/log/php-errors.log
Or check your mail log for envelope sender rejections:
grep -i "sender.*rejected\|sender.*denied" /var/log/mail.log
You can also test wp_mail() directly from WP-CLI:
wp eval 'var_dump(wp_mail("[email protected]", "Test", "Testing wp_mail delivery"));'
If this returns bool(false), emails are failing at the sending level. Check your PHP error log immediately after running it — the error message will tell you whether it's the envelope sender issue or something else.
The lesson
Every WooCommerce store should use authenticated SMTP. Not because WordPress might break mail() again (though it might — this has been an open debate in core for 14 years), but because PHP mail() was never designed for transactional email delivery. It provides no authentication, no delivery tracking, no bounce handling, and no logs.
I configure SMTP on every WooCommerce site I onboard. It takes 15 minutes, costs nothing on free tiers (Brevo, Mailgun trial), and prevents exactly this kind of silent failure. If your store is still relying on PHP mail(), this incident is a good reason to fix that before the next core update catches you off guard.
If you'd rather not chase email delivery issues yourself, authenticated SMTP setup is part of every WooCommerce maintenance plan. I also monitor email delivery as part of ongoing site health checks — so when something breaks, I catch it before your customers do. View maintenance plans.
