- 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:
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:
Suggested fix When
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 viaEsmtpTransportFactorywith the OAuth access token in the password slot and does not touch the authenticator list.- Every send opens with
AUTH LOGINusing 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.
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.