Feature request: add-o365 --headless device-code flow
Summary
Add a --headless flag to msgvault add-o365 that uses OAuth 2.0 device-code flow instead of the authorisation-code-with-localhost-callback flow, mirroring the existing add-account --headless for Gmail.
Why
Personal Outlook.com / Hotmail users hit a structural wall in 2026:
-
IMAP + app password is dead. Microsoft rejected basic auth at 100% as of 30 April 2026 (Exchange Online basic-auth deprecation finished its phased rollout). add-imap against outlook.office365.com:993 now fails with NO AUTHENTICATE failed / NO LOGIN failed even with a valid app password and IMAP enabled at the mailbox level.
-
Own Azure AD app registration from a personal Microsoft account is no longer possible. As of mid-May 2026 the Azure portal explicitly states: "The ability to create applications outside of a directory has been deprecated. You can get a new directory by joining the M365 Developer Program or signing up for Azure." The M365 Developer Program is now gated to Visual Studio Pro/Enterprise subscribers, and Azure free tier requires a card. Neither is "free as in beer" for a personal user who just wants email archive.
-
Reusing a known public client_id (e.g. the pnp/cli-microsoft365 CLI's public app 084a3e9f-a9f4-43f7-89f9-d229cf97853e, which is the most defensible reuse since it's an open-source community project) works at the Microsoft /authorize endpoint — the client_id is accepted, scopes including https://outlook.office.com/IMAP.AccessAsUser.All are requested fine — but the redirect URI msgvault hardcodes (http://localhost:8089/callback/microsoft) is rejected with:
invalid_request: The provided value for the input parameter 'redirect_uri' is not valid. The expected value is a URI which matches a redirect URI registered for this client application.
Public clients only accept redirect URIs registered against them, and msgvault's port-and-path is not in the m365 CLI app's redirect list (nor in any other public Microsoft OAuth app's list as far as I can tell).
The combination locks personal-account users out of the OAuth path msgvault currently offers.
Why device-code flow fixes it
OAuth 2.0 device-authorisation grant (RFC 8628) doesn't use a redirect_uri at all. The client requests a user_code + verification_uri, displays them to the user, the user visits the URL on any device and enters the code, and the client polls a token endpoint for the result. Microsoft fully supports it on /oauth2/v2.0/devicecode for both personal and work accounts.
Crucially: any public multi-tenant client_id works for device-code flow, because there's no redirect URI to validate against the client's registration.
This is exactly the pattern pnp/cli-microsoft365 uses (m365 login --authType deviceCode), and it's why an unprivileged user on a personal Outlook.com mailbox can authenticate with that CLI without owning a tenant.
Proposed UX
Mirror the existing Gmail flow:
$ msgvault add-o365 user@hotmail.co.uk --headless
Authorizing user@hotmail.co.uk with Microsoft (device code flow)...
To sign in, use a web browser to open:
https://microsoft.com/devicelogin
Then enter the code:
GH47PXTC9
Waiting for authorization... (polling every 5 seconds, expires in 15 min)
After the user enters the code in the browser and clicks Allow, msgvault polls until it receives the token, stores it under ~/.msgvault/ with the same on-disk shape as the current flow, and exits with the same success message.
Implementation reference: Microsoft's device code flow docs.
Config tweak
The existing [microsoft] config block stays mostly the same. The only addition is that client_id is no longer required to be a tenant-private app — any public Microsoft client_id that registered the desired scopes works under device-code flow.
For users who don't want to plug a specific client_id, msgvault could ship a default public client_id baked into the binary (analogous to how pnp/cli-microsoft365 ships its 084a3e9f-... default). That removes the last hurdle for personal-account users.
Workaround until shipped
Users without a Microsoft tenant currently have no clean path to msgvault Hotmail/Outlook.com live-sync. Documented workarounds:
- Defer Hotmail entirely (rely on
olm historic archive imports).
- Sign up for Azure free tier (card needed for identity check) and register a private app.
Both are friction-heavy.
Author note
Built this analysis while wiring my own msgvault deployment (~/.msgvault/ on macOS) against a personal Outlook.com account. Gmail OAuth via add-account worked beautifully reusing an existing Google Cloud OAuth client; the contrast with the Microsoft path is what surfaced this gap. Happy to help test a --headless branch.
Filed by Adrian Shedden — adrian@ai-ops.org — 27 May 2026
Feature request:
add-o365 --headlessdevice-code flowSummary
Add a
--headlessflag tomsgvault add-o365that uses OAuth 2.0 device-code flow instead of the authorisation-code-with-localhost-callback flow, mirroring the existingadd-account --headlessfor Gmail.Why
Personal Outlook.com / Hotmail users hit a structural wall in 2026:
IMAP + app password is dead. Microsoft rejected basic auth at 100% as of 30 April 2026 (Exchange Online basic-auth deprecation finished its phased rollout).
add-imapagainstoutlook.office365.com:993now fails withNO AUTHENTICATE failed/NO LOGIN failedeven with a valid app password and IMAP enabled at the mailbox level.Own Azure AD app registration from a personal Microsoft account is no longer possible. As of mid-May 2026 the Azure portal explicitly states: "The ability to create applications outside of a directory has been deprecated. You can get a new directory by joining the M365 Developer Program or signing up for Azure." The M365 Developer Program is now gated to Visual Studio Pro/Enterprise subscribers, and Azure free tier requires a card. Neither is "free as in beer" for a personal user who just wants email archive.
Reusing a known public client_id (e.g. the
pnp/cli-microsoft365CLI's public app084a3e9f-a9f4-43f7-89f9-d229cf97853e, which is the most defensible reuse since it's an open-source community project) works at the Microsoft/authorizeendpoint — the client_id is accepted, scopes includinghttps://outlook.office.com/IMAP.AccessAsUser.Allare requested fine — but the redirect URI msgvault hardcodes (http://localhost:8089/callback/microsoft) is rejected with:Public clients only accept redirect URIs registered against them, and msgvault's port-and-path is not in the m365 CLI app's redirect list (nor in any other public Microsoft OAuth app's list as far as I can tell).
The combination locks personal-account users out of the OAuth path msgvault currently offers.
Why device-code flow fixes it
OAuth 2.0 device-authorisation grant (RFC 8628) doesn't use a
redirect_uriat all. The client requests auser_code+verification_uri, displays them to the user, the user visits the URL on any device and enters the code, and the client polls a token endpoint for the result. Microsoft fully supports it on/oauth2/v2.0/devicecodefor both personal and work accounts.Crucially: any public multi-tenant client_id works for device-code flow, because there's no redirect URI to validate against the client's registration.
This is exactly the pattern
pnp/cli-microsoft365uses (m365 login --authType deviceCode), and it's why an unprivileged user on a personal Outlook.com mailbox can authenticate with that CLI without owning a tenant.Proposed UX
Mirror the existing Gmail flow:
After the user enters the code in the browser and clicks Allow, msgvault polls until it receives the token, stores it under
~/.msgvault/with the same on-disk shape as the current flow, and exits with the same success message.Implementation reference: Microsoft's device code flow docs.
Config tweak
The existing
[microsoft]config block stays mostly the same. The only addition is thatclient_idis no longer required to be a tenant-private app — any public Microsoft client_id that registered the desired scopes works under device-code flow.For users who don't want to plug a specific client_id, msgvault could ship a default public client_id baked into the binary (analogous to how
pnp/cli-microsoft365ships its084a3e9f-...default). That removes the last hurdle for personal-account users.Workaround until shipped
Users without a Microsoft tenant currently have no clean path to msgvault Hotmail/Outlook.com live-sync. Documented workarounds:
olmhistoric archive imports).Both are friction-heavy.
Author note
Built this analysis while wiring my own msgvault deployment (~/.msgvault/ on macOS) against a personal Outlook.com account. Gmail OAuth via
add-accountworked beautifully reusing an existing Google Cloud OAuth client; the contrast with the Microsoft path is what surfaced this gap. Happy to help test a--headlessbranch.Filed by Adrian Shedden — adrian@ai-ops.org — 27 May 2026