Fixed Gmail OAuth SMTP sends fail starting ~2026-09-29 due to failed auth LOGIN by Symfony

blues

Member
Licensed customer
Affected version
2.3.12
Affected version: XenForo 2.3.12 (bundled symfony/mailer v5.4.52), PHP 8.3.33, nginx/Centminmod on AlmaLinux 9. Email transport: SMTP, smtp.gmail.com:465 (SSL), Google OAuth configured via the ACP "Set up OAuth" flow (Google Workspace account, Internal audience).

Summary
Starting 2026-09-29, every outbound email through gmail oauth smtp fails with:

Code:
Symfony\Component\Mailer\Exception\TransportException: Email to <recipient> from <sender> failed:
Failed to authenticate on SMTP server with username "<workspace-user>" using the following
authenticators: "LOGIN", "PLAIN", "XOAUTH2".
Authenticator "LOGIN" returned "Expected response code "235" but got code "535", with message
"535-5.7.8 Username and Password not accepted. For more information, go to 535 5.7.8
https://support.google.com/mail/?p=BadCredentials ... - gsmtp".".
Authenticator "PLAIN" returned "Expected response code "235" but got empty code.".
Authenticator "XOAUTH2" returned "Expected response code "235" but got empty code.".
src/vendor/symfony/mailer/Transport/Smtp/EsmtpTransport.php:198

Nothing changed on our install during this time period, flow was working fine before this date. The OAuth token is valid and being refreshed successfully (the token_expiry in emailTransport advances on every send attempt and there are no "Failed to refresh OAuth access token" entries. Re-running the OAuth setup with a new client secret produced the same failure.

The cause seems to be an interaction between Symfony Mailer's fixed authenticator order and a gmail server-side behaviour change:

  • Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport (5.4.x) tries authenticators in a hard-coded order: CRAM-MD5, LOGIN, PLAIN, XOAUTH2.
  • XF\Mail\Mailer::getTransportFromOption() builds the transport via EsmtpTransportFactory with the OAuth access token in the password slot and does not touch the authenticator list.
  • Every send opens with AUTH LOGIN using the access token as the password. Gmail rejects that with 535-5.7.8. Until recently Gmail kept the connection open, Symfony fell through to PLAIN (535 again) and then XOAUTH2, which succeeded.
  • Gmail now closes the connection immediately after the first failed AUTH. PLAIN and XOAUTH2 get no response at all — Symfony reports this as got empty code — and XOAUTH2 is never actually tried.
Workaround that restored mail send I moved new Auth\XOAuth2Authenticator() to the front of the $this->authenticators array in src/vendor/symfony/mailer/Transport/Smtp/EsmtpTransport.php (constructor, ~line 38) and restarted PHP-FPM. ACP test email succeeds immediately, no further errors logged.

Suggested fix When $config['oauth'] is set in XF\Mail\Mailer::getTransportFromOption(), restrict the transport to XOAuth2Authenticator only. Symfony added EsmtpTransport::setAuthenticators() and an $authenticators constructor argument in version 6.3, but 5.4 has neither, so for 2.3 it needs a small subclass/factory or a reordered default.
 
Ran into this same issue on a client I support; should have written a note about it back then. We took the same solution as written above, but just wrote a small addon to address this instead of modifying the original files.
 
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.3.14).

Change log:
Fix outgoing email failing to send through Gmail SMTP when connected with OAuth
There may be a delay before changes are rolled out to the XenForo Community.
 
Back
Top Bottom