Repository navigation
Modernize email delivery with OAuth2 and API transports - #5454
nilsteampassnet merged 20 commits into
Conversation
e19739b to
63bd305
Compare
63bd305 to
8925591
Compare
8925591 to
bee559e
Compare
|
Thanks @guerricv. Two points must be fixed before merge:
Strongly suggested in the same round:
Smaller points:
Real-provider and visual acceptance remain on your list, as you noted. I'll handle POEditor for the other languages. |
|
Thanks Nils, both blockers were valid, and I've addressed the other suggestions too. The fixes are split into six commits:
Local validation: 258 focused PHP tests / 2,576 assertions, explicit PHPStan analysis of the email package and worker/queue/profile code, PHP syntax and table-prefix checks all passed. Both new JavaScript regressions passed too. Fresh Quality and CodeQL checks passed on Live Microsoft/Google permission, consent/renewal, inbox delivery and visual acceptance remain open as documented. No installed application data was used for these tests. |
|
Thanks @guerricv, #5454 is merged and pushed to Must fix
Strongly suggested in the same PR
Smaller point
Your real-provider and visual acceptance checks are still pending, as you noted. I'll handle POEditor and the release note (encrypted queue payloads and rollback, SMTP host formats now refused). |
Description
TeamPass email delivery currently depends on SMTP configuration, while Microsoft and Google deployments also need unattended OAuth authentication and API delivery. This PR keeps
EmailServiceas the common entry point and PHPMailer as the MIME builder, then adds Microsoft 365 SMTP XOAUTH2, Microsoft Graph and delegated Gmail API transports alongside existing SMTP relays.The administration page saves one complete transport profile atomically, with explicit keep/replace/clear actions for secrets. Provider credentials and tokens are encrypted with the existing instance key. Token renewal uses configuration revisions and expiring database leases; Google consent uses state, PKCE and an administrator-bound pending configuration.
New queued messages are encrypted before insertion into the existing background-task queue. Confirmed transient failures can be deferred for at most three attempts, respecting
Retry-After. Ambiguous acceptance, partial delivery and interrupted sends never trigger an automatic replay. No failure falls back to Basic SMTP authentication.Related issue
Builds on #5453, merged into develop on 9 November 2026. The PR contains only the 14 modernization commits; its prerequisite fixes are now integrated into develop. There is no combined squash.
Temporarily in draft while the checks after the #5455 rebase complete, including Scrutinizer. The prerequisite fixes are now integrated. The remaining real-provider and interface acceptance checks are documented below.
For the modernization-only changes, compare the current develop branch with this branch. No issue is automatically closed by this PR.
Type of change
How has this been tested?
Rebase after #5455 (9 November 2026): current head
bee559e37a1247f9d3de0e022245ef10aac70ff9is based ondevelop2b605c51d, including the merged search favorites PR #5455 and its follow-up tests. All 14 modernization patches are unchanged. The only shared file ismain.functions.php, where the email queue and favorite-access changes affect separate functions; the rebase had no conflicts. The 34 focused email/favorites tests passed with 406 assertions. Fresh CI is running on this head; the PR will return to Ready for review after all checks, including Scrutinizer, pass. Previous validation results follow for context.History refresh (9 November 2026): previous head
89255910aa82639934ff9daebc3f7fd0329507beis rebased directly ontodevelop227acfb78, the merge of #5453. GitHub now shows only the 14 modernization commits. All 14 patches match their earlier versions, and the complete Git tree is identical to63bd305fb; no application file changed. Fresh CI on this new head passed: PHP 8.2/8.3 each ran 3,636 tests and 84,619 assertions; all 319 JavaScript tests, PHPStan level 4, MariaDB, repository guards, CodeQL and Scrutinizer passed. All 11 checks are green, and the PR is ready for code review. The documented real-provider and visual acceptance checks remain open. Earlier source validation results follow for context.Rebase follow-up (9 November 2026): previous head
63bd305fb00ac43baa7e8e50d3ff15c088c8b9b9is based on the review fixes in #5453 (004760823), abovedevelop945069257. The 14 modernization commits remain separate. Conflicts were resolved to retain the connection/TLS diagnostics, safe decryption errors, failed-task anonymization and purge requested in #5453. Terminal failures replace encrypted payloads with failure metadata without claiming provider acceptance; deferred sealed messages retain their ciphertext for retry. Regression coverage includes both outcomes.Validation before the history refresh (63bd305): Quality CI passed: PHP 8.2/8.3 each ran 3,636 tests and 84,619 assertions; all 319 JavaScript tests, PHPStan level 4, MariaDB and repository guards passed. CodeQL passed. Scrutinizer also passed (two non-blocking findings reported); all 11 checks are green on this head. The source tree passed these checks before the history refresh; the acceptance checks below remain open. Locally, 259 focused tests and 2,043 assertions passed (five skips), along with explicit PHPStan analysis of the email package, worker and handler. The isolated Linux copy passed 3,636 tests and 84,569 assertions on PHP 8.5.4 (14 deprecations and five skips), plus both email MariaDB regressions. Earlier validation results follow for context.
Rebase follow-up (8 November 2026): rebased onto the updated prerequisite #5453, itself based on
developat2e3db0edde1b4bfb1a93c84f5944e964c278b548(TeamPass 3.2.4.2). The three prerequisite commits and 14 modernization commits remain separate. The only conflict was the version file: the official 3.2.4.2 version and the email schema marker were both retained; the migration test comment now names the current release. Current head:e19739b618c6b749a55deceef7bb881075a9643e. Local email/background-task/upgrade tests passed (254 tests, 1,914 assertions; five environment skips), as did explicit PHPStan analysis of the email package, the table-prefix guard and dual-copy checks. Fresh Quality CI passed on this rebased head: PHP 8.2/8.3 each passed 3,619 tests and 84,429 assertions; all 311 JavaScript tests, PHPStan level 4, MariaDB and repository guards passed. CodeQL and external Scrutinizer also passed on this rebased head; all 11 checks are green. The new upstream security regressions also passed locally from an LF archive (34 tests, 455 assertions); CRLF-sensitive source assertions fail in the Windows checkout. The results below are historical checks of the earlier head. It remained a draft at that stage.The upstream PR checks also passed on
7910412ce49e5cd0aa810f1d8120f44905436263, including PHP 8.2/8.3, JavaScript, PHPStan, MariaDB, repository guards, CodeQL and external Scrutinizer. The PR was still a draft at that stage.Quality CI on commit
7910412ce49e5cd0aa810f1d8120f44905436263passed all seven jobs:An isolated Linux test copy also passed 3,585 tests and 83,922 assertions on PHP 8.5.4, with the same 14 deprecations and five skipped tests as the baseline, plus full PHPStan. The transport package was analyzed separately because the main PHPStan configuration excludes these library copies.
Regression coverage includes real PHPMailer MIME preparation, synthetic loopback SMTP sessions for relay/LOGIN/XOAUTH2, mocked provider HTTP responses, token cache and renewal ownership, consent binding, encrypted queue payloads, worker and handler outcomes, deferred scheduling, and the refusal to replay ambiguous results. MariaDB tests execute fresh-install and upgrade code, replay the migration, and verify encryption, rollback, configuration concurrency and due-task selection with a non-default table prefix.
Acceptance checks still pending: real Microsoft/Google credentials, mailbox permission scoping, consent and renewal against live providers, inbox receipt and client rendering, and visual review of the administration page on small screens and in dark mode. The browser automation host was unavailable. No manual admin/manager/standard/read-only role matrix or personal-folder scenario is claimed; these remain in the documented acceptance procedure. Installed application data was not used by the isolated tests.
Checklist
var_dump()orconsole.log()was added.Impact on install / upgrade
Schema change: the replayable
upgrade_run_3.2.4.phpstep and fresh installation add provider settings, a configuration revision,email_oauth_state, and theemail_attempts/next_attempt_attask columns with a due-task index.UPGRADE_MIN_DATEis advanced so existing 3.2.4.1 and 3.2.4.2 installations also run the migration; the release number is unchanged.Existing SMTP settings are preserved and remain the default. Historical queued messages remain readable. New encrypted task envelopes require compatible workers: restore compatible code and database backups together when rolling back, and account for pending encrypted tasks before a downgrade.
Guzzle and League OAuth2 Client were already shipped transitively; they are declared directly without changing their locked versions or rebuilding the committed production autoloader.
Initial API limits are explicit: 2 MiB of prepared MIME, matching configured sender and From, and Bcc refused rather than silently dropped. SMTP retains its existing envelope behavior. Google SMTP OAuth, service accounts/domain-wide delegation, national-cloud endpoints, Microsoft certificate credentials and native transactional-provider APIs are outside this version.
Administration, provider permissions, migration, rollback, limitations and acceptance steps are documented in
docs/manage/email-transports.md. Transport and queue design notes are in.claude/rules/architecture-email-transports.md.Screenshots
Pending visual acceptance. Server-rendered controls were checked for secret leakage and escaped labels, and the generated JavaScript syntax was verified; these checks do not replace a browser review.