fix(smtp): respect configured SMTP user for XOAUTH2 authentication - #13668
Open
Rikdekker wants to merge 1 commit into
Open
fix(smtp): respect configured SMTP user for XOAUTH2 authentication#13668Rikdekker wants to merge 1 commit into
Rikdekker wants to merge 1 commit into
Conversation
The SASL XOAUTH2 identity for SMTP was hardcoded to the account's email address, ignoring the configured SMTP user. For basic auth the SMTP user is honoured, and provisioning can already derive a distinct one, so the xoauth2 path was the only place where the setting had no effect. This breaks sending from Microsoft 365 shared mailboxes. Exchange Online accepts a shared mailbox as XOAUTH2 identity for IMAP but rejects it for SMTP AUTH with "535 5.7.3 Authentication unsuccessful", because a shared mailbox has no sign-in credentials of its own. The supported approach is to authenticate as the delegate's own mailbox and rely on Send As for the sender address, which is what other clients such as Thunderbird do. Use the configured SMTP user as the XOAUTH2 identity and fall back to the account's email address when it is empty, so existing accounts keep their current behaviour. The IMAP client factory is left unchanged on purpose: there the shared mailbox address is the correct identity. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Rikdekker <Rikdekker@users.noreply.github.com>
Rikdekker
requested review from
ChristophWurst,
GretaD and
kesselb
as code owners
September 10, 2026 14:41
|
Thanks for opening your first pull request in this repository! ✌️ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #13667
Summary
For
xoauth2accounts the SASL XOAUTH2 identity used for SMTP was hardcoded to$account->getEmail(), so the configured SMTP user had no effect. This makes itimpossible to authenticate as one mailbox and send as another — which is exactly what
Microsoft 365 requires for shared mailboxes.
This PR uses
getOutboundUser()when set and falls back to the account's email addressotherwise.
Why
Exchange Online accepts a shared mailbox as the XOAUTH2 identity for IMAP but rejects it
for SMTP AUTH with
535 5.7.3 Authentication unsuccessful, because a shared mailbox hasno sign-in credentials of its own. A Microsoft engineer confirms this in
this Q&A thread:
"we cannot use shared mailbox for SMTP AUTH client submission."
The supported pattern is to authenticate as the delegate's own mailbox and let Exchange
Send As handle the sender address. Thunderbird works this way, which is why users report
that Thunderbird can send from a shared mailbox while Mail cannot.
Why only SMTP
IMAPClientFactorydeliberately keeps using the account email: for IMAP the sharedmailbox address is the correct identity, and Microsoft documents that substitution.
That path works today and is untouched.
Backwards compatibility
No behaviour change for existing accounts:
AccountForm.vuerequiressmtpUserin the OAuth flow as well (only the passwordfields are gated behind
!useOauth) and pre-fills it with the email address.smtpConfig.username; provisioning computes it viabuildSmtpUser().smtpUserfor OAuth accounts.So for accounts created through the UI both values are already identical, and the
fallback covers CLI/provisioning cases where the column may be empty.
Precedent
#12442 (Dovecot master user) introduced the same concept — an SMTP auth identity distinct
from the account address — across the IMAP, SMTP and Sieve factories.
Tests
tests/Unit/SMTP/SmtpClientFactoryTest.phphad no xoauth2 coverage at all. This PR addstwo cases:
Verified locally against a Nextcloud instance (PHP 8.5):
Reverting the production change makes the new test fail with exactly the reported
symptom, confirming the tests are meaningful:
End-to-end verification against a real Microsoft 365 tenant
Verified with an actual Exchange Online shared mailbox (
shared@example.org), with Full Access andSend As granted to the personal account (
user@example.org), configured exactly as users do today:the shared mailbox added as its own account, authorised with the personal user's OAuth
token.
shared@example.orgsmtp_user= account address)shared@example.orgsmtp_user=user@example.org)user@example.orgFrom: shared@example.orguser@example.orgsmtp_usertoshared@example.orgshared@example.orgSo the same account, token and mailbox only differ in the SMTP auth identity, and that is
what decides between rejection and delivery. Sending as the shared mailbox works through
Exchange Send As once the identity is decoupled — which is what this PR enables.
The sent message is stored in the shared mailbox's own Sent Items folder (verified over
IMAP), so it is visible to everyone with access to that mailbox. That is a meaningful
difference from the alias-based workaround, where the copy ends up in the sender's
personal Sent folder and colleagues sharing the mailbox never see the replies.
Context
Reported during the SURF Works pilot, which offers Nextcloud to Dutch research and
education institutions where functional/shared mailboxes are common.
Checklist