A WordPress site that sends contact-form notifications, WooCommerce receipts, and password-reset emails through a Microsoft 365 mailbox will stop sending them before the end of December 2026. The break is not silent: PHPMailer starts returning
550 5.7.30 Basic authentication is not supported for Client Submission
and every wp_mail call falls on the floor. Microsoft is switching off SMTP AUTH Basic Authentication for Exchange Online. On existing tenants the default flips off at the end of December 2026; on tenants created after January 2020 it has been off by default since then, with the admin-level override removed in December 2026.
This spoke is for the audience that configured Microsoft 365 SMTP the plugin-free way: six constants set in wp-config.php (SMTP_HOST on smtp.office365.com, SMTP_USER and SMTP_PASSWORD holding a mailbox address and an app password, SMTP_AUTH on true, SMTP_SECURE on 'tls', SMTP_PORT on 587), plus a phpmailer_init callback in a theme or mu-plugin wiring those constants into PHPMailer at every send.
Two paths lead out. Install a mailer plugin so M365 can be reached over OAuth, and delete the wp-config setup. Or keep the wp-config setup and change the credentials to a transactional provider that still authenticates over basic SMTP. The design choice that put the site on a plugin-free architecture decides between them. The pillar hub carries the full timeline and routes readers on a different starting setup.
Why wp-config alone can’t do M365 OAuth
The instinctive move on a site set up this way is to keep the plugin-free architecture and swap the mailbox password for an OAuth token. It does not work, and the reason is worth being precise about.
Basic auth is a static string. The SMTP_PASSWORD constant defined in wp-config.php is a value PHPMailer reads at every send, unchanged from PHP boot to PHP boot. That is what SMTP AUTH Basic Authentication expects on the wire: a username, a password, no negotiation. This is why the wp-config approach works today.
OAuth is a rotating token. Under OAuth 2.0, Microsoft issues a short-lived access token that PHPMailer sends instead of a password, and a longer-lived refresh token used to obtain a new access token when the old one expires. Microsoft’s identity platform
documents the rotation requirement explicitly: “Refresh tokens replace themselves with a fresh token upon every use.” The previous refresh token is meant to be securely deleted once the new one is stored.
wp-config constants are immutable at PHP boot; a rotating refresh token cannot live in a define() call. Something would have to rewrite wp-config.php after every token exchange, and even that would not meet Microsoft’s expectation that refresh tokens are stored safely.
WordPress core currently bundles PHPMailer 7.0.2, which does support OAuth: it exposes an OAuthTokenProvider interface an operator can implement. Doing so means writing a class that returns a valid XOAUTH2 string on demand, pulling in a Composer library for the Microsoft-specific token flow, providing writable storage for the rotating refresh token, and wiring it all through a mu-plugin. That is the work every mailer plugin already does. Rebuilding it in a mu-plugin arrives at the same result as the nearest free plugin, at a much higher cost.
Two migration paths
| Path | What changes | What it costs | When it’s right |
|---|---|---|---|
| A. Install FluentSMTP | M365 stays as the sender. The wp-config SMTP block is deleted; FluentSMTP handles submission over OAuth. | Requires an app registration in the tenant’s Microsoft Entra portal and tenant Global Admin consent. | Keeping the M365 mailbox as the site’s outbound identity matters more than keeping the plugin-free architecture. |
| B. Keep wp-config, swap providers | Site sends via Postmark, SMTP2GO, Mailgun, or SendGrid. Only four constants change; the mailer architecture stays the same. | Domain verification, SPF, DKIM, and (in most cases) sending from a subdomain rather than the M365 mailbox. | The plugin-free architecture is the reason for the current setup, or M365 was chosen for expedience rather than sender identity. |
Path B is the answer a meaningful share of readers on this page were hoping to find. Waiting is not a path: the site stops sending contact-form notifications, password resets, and order receipts from the moment the 5.7.30 rejection starts.
Path A: Install FluentSMTP, retire the wp-config SMTP
FluentSMTP is the recommendation for this path: M365 OAuth is available in the free version, with no upsell required. WP Mail SMTP Pro is a paid alternative for tenants where Microsoft Entra access is restricted. Its One-Click Setup uses a Microsoft-published app, so it skips the customer Entra registration step.
- Back up the current SMTP configuration. Copy the six SMTP constants from
wp-config.phpand thephpmailer_initsnippet from wherever it lives (a mu-plugin,functions.php, a snippet manager) into a scratch file. If the migration hits a snag and needs to roll back to the working-through-December configuration, this is the source of truth. - Install FluentSMTP from the WordPress admin plugin installer. Search
fluent smtp; the plugin isfluent-smtpon wp.org. Do not activate a second mailer plugin at the same time: two mailer plugins register twophpmailer_initcallbacks that overwrite each other’s PHPMailer settings, and the last one wins non-deterministically. The wp-config snippet stays in place during setup so a partial FluentSMTP configuration does not leave the site with no working mail transport. - Configure the Microsoft 365 / Outlook OAuth connection. FluentSMTP + Microsoft 365 migration is the source of truth for this step: the Entra app registration, the API permissions the plugin needs, the tenant admin consent, the connection setup inside FluentSMTP itself, and the test send. Come back here once FluentSMTP shows a successful test.
- Verify FluentSMTP is sending. FluentSMTP’s Email Test tab should return a successful send without the
5.7.30string. Confirm the received message actually reached an inbox on a different domain (a Gmail address works fine) before moving on. - Remove the wp-config SMTP configuration. Delete the
SMTP_*constants block fromwp-config.phpand remove thephpmailer_initsnippet from wherever it lives. WordPress now sends through FluentSMTP alone; the plugin-free path is retired. - Clear the debug log and monitor for 24 hours. Watch FluentSMTP’s Email Log for any further
5.7.30. The most common regression at this stage is an opcode cache or persistent object cache holding the oldphpmailer_initbehaviour. If mail fails to send after step 5 and the FluentSMTP connection test still passes, restart PHP-FPM (or runwp transient delete --allas a first pass) to flush the cached state.
Path B: Keep wp-config SMTP, swap to a transactional provider
Postmark, SMTP2GO, Mailgun, and SendGrid all authenticate over SMTP with a username and password. None of the four have signalled that basic-auth SMTP is being removed as a supported credential path. The wp-config architecture continues to work; only four values change.
-
Pick the provider.
- Postmark. The highest-reputation option for transactional-only mail. Permanent free developer plan at 100 emails/month; paid plans from there.
- SMTP2GO. 1,000 emails/month free forever. Fits mixed transactional and light-marketing traffic.
- Mailgun. Free plan at 100 emails/day (perpetual); paid Foundation plan at 50,000 emails/month. Sensible when other Mailgun infrastructure is already in the stack.
- SendGrid. 100 emails/day for the first 60 days, then paid. Broadest name-recognition; clearest path for teams already in the Twilio ecosystem.
The free SMTP servers for WordPress roundup covers these free tiers at more length.
-
Provision the domain. Sign up, verify the sending domain, publish the SPF and DKIM records the provider issues. The site’s
Fromaddress usually shifts from the M365 mailbox to a subdomain (send.example.comor similar); sending from the M365 mailbox address itself is possible but breaks M365’s inbound reply routing unless the mailbox forwards those replies onward. -
Get the provider’s SMTP credentials. Each provider issues them differently: Postmark uses the Server Token as both username and password, SendGrid uses the literal string
apikeyas username with the API key as password, Mailgun issues per-domain SMTP credentials under Sending → Domain Settings → SMTP Credentials, SMTP2GO generates username/password pairs under Sending → SMTP Users. Verify against the provider’s own documentation before pasting into wp-config. -
Swap the wp-config constants. Only four values change. Before, with M365:
define( 'SMTP_HOST', 'smtp.office365.com' ); define( 'SMTP_USER', '[email protected]' ); define( 'SMTP_PASSWORD', 'the-app-password' ); define( 'SMTP_PORT', 587 ); define( 'SMTP_SECURE', 'tls' ); define( 'SMTP_AUTH', true );After, with SMTP2GO as an example:
define( 'SMTP_HOST', 'mail.smtp2go.com' ); define( 'SMTP_USER', 'the-generated-username' ); define( 'SMTP_PASSWORD', 'the-generated-password' ); define( 'SMTP_PORT', 587 ); define( 'SMTP_SECURE', 'tls' ); define( 'SMTP_AUTH', true );SMTP_AUTH,SMTP_SECURE,SMTP_FROM, andSMTP_FROMNAMEstay the same unless the provider requires port 465, in which caseSMTP_SECUREbecomes'ssl'andSMTP_PORTbecomes465. -
Test with the “Lost your password?” flow. Same test the without-plugin setup guide uses. Log out, navigate to
wp-login.php, click “Lost your password?”, trigger a real send. A successful arrival confirms the credential swap without touching any additional code paths. -
Retire the M365 SMTP AUTH configuration. In the mailbox owner’s account portal → Security → App passwords, revoke the app password the site was using. An Exchange admin can also disable SMTP AUTH on the specific mailbox:
Set-CASMailbox -Identity [email protected] -SmtpClientAuthenticationDisabled $trueBoth steps are optional but remove the credential from active use.
Which path when
Take Path A when the site’s sender identity as the M365 mailbox owner matters: invoices from [email protected], support replies from a mailbox humans also read, order confirmations that need to land in the mailbox’s Sent items. Path A requires tenant Global Admin (or access to someone who has it) and the Entra admin center. The plugin-free architecture goes away in return.
Take Path B when the plugin-free architecture was the point: credentials in wp-config outside the database, fewer moving parts, no admin-UI attack surface. Also when M365 was chosen for SMTP access rather than for sender identity. Transactional providers deliver contact-form notifications and order receipts more reliably than a repurposed mailbox does, at zero cost for typical WordPress-transactional volume.
When neither path fits
The engineer-owner who wants M365 OAuth and the plugin-free architecture can implement PHPMailer’s OAuthTokenProvider interface in a mu-plugin, load a Composer library like thenetworg/oauth2-azure for the token exchange, and provide writable storage for the refresh token. Microsoft’s
Authenticate an IMAP, POP, or SMTP connection using OAuth is the reference. The result reimplements what FluentSMTP already does.
If the site is on M365 SMTP relay via connector (port 25, source-IP allowlist) or on Direct Send, the SMTP AUTH retirement does not apply and this migration is the wrong one to run. Microsoft 365 SMTP relay and Direct Send is the right page.
Related
- Microsoft 365 is disabling password SMTP, the pillar hub, for the full timeline, the routing to a different scenario, and the “not affected” cohort.
- How to set up WordPress SMTP without a plugin, the setup guide the wp-config architecture comes from; still applicable in Path B with the new credentials.
- FluentSMTP + Microsoft 365 migration, the destination for Path A step 3.
- Microsoft 365 as a WordPress SMTP server, the entity review, for readers reconsidering whether M365 is still the right fit for the site’s transactional mail.
