Skip to main content

Module microsoft

Module microsoft 

Source
Expand description

Microsoft’s mail: Outlook.com, Hotmail, Live and MSN (personal accounts), and Microsoft 365 (work or school accounts), over IMAP and SMTP signed in with OAuth 2.0 (docs/microsoft.md). Microsoft takes no password and no app password from mail programs any more.

The sign-in is a native app’s (RFC 8252): your browser opens on Microsoft’s page, Microsoft sends its answer back to this device (loopback.rs, on 127.0.0.1 only: Microsoft takes no IPv6 loopback), and PKCE (RFC 7636) proves it is the same program asking. No client secret, ever: Sioul is a public client, and Microsoft refuses a secret from one. The application is Sioul’s own when the build was given one (SIOUL_MICROSOFT_CLIENT_ID), else yours, registered once in Microsoft Entra.

What stays: the grant (the application, the tenant, the refresh token), in the system keyring only, split over a few entries when it is longer than Windows keeps in one; the access token, in memory. Microsoft gives a new refresh token at each use and asks to keep the newest: it is written back each time. Microsoft offers no way for an app to give a token back: removing an account forgets it here, and you withdraw the consent on your account’s page (forget says which).

A token goes to Microsoft’s sign-in (login.microsoftonline.com), and to the account’s own mail servers, each named exactly (is_imap_host, is_smtp_host): never to a server a configuration names otherwise.

Structs§

Grant
What the keyring keeps for an address signed in with Microsoft.
Kept 🔒
The grant as the keyring keeps it: the refresh token’s first part in this entry, the rest in parts more, and the start of the whole token’s SHA-256, its check. The parts are named after the check (<name>#<check>#2, #3…): each token’s parts are its own, written before the entry that names them, so that a rotation cut short, or two crossing, never leave this entry naming parts it does not have (the review of 15 October 2026, L2); every generation with parts is noted beside it until its parts are gone (generations), so that removal forgets them all. A grant without its check is no grant.
Keyring 🔒
The system keyring, through secret.rs.
SignIn
A sign-in under way: the page to open, and the door Microsoft comes back to.
Signed
What a sign-in made of an account, kept only once answered (answer).

Enums§

Authority
Whose accounts the sign-in takes: the {tenant} of Microsoft’s endpoints.
Kind
What discovery makes of an address before anyone signs in: a personal account’s (Outlook.com’s domains, or a domain whose mail Outlook.com receives), a work or school account’s (Microsoft 365), or not known. The ID token’s tid settles it at sign-in.
Step 🔒
When in the sign-in a refusal came: it says different things.

Constants§

ACCOUNT_TYPES
The application’s registration does not take this kind of account.
ADMIN
Your organisation must approve Sioul once.
AGAIN
Microsoft asks you to sign in again (the access withdrawn, a second factor wanted…).
AGAIN_FREQUENCY
The same because your organisation asks you to sign in again every so often.
AGAIN_LATE
Microsoft’s answer reached Sioul after its code had ended (a code lasts about a minute).
AGAIN_PASSWORD
The same after a password changed or reset.
AGAIN_UNUSED
The same after 90 days without use.
BLOCKED
Your organisation’s rules block this app or this sign-in.
CANCELLED
Cancel pressed while Microsoft’s page was open.
CONFIDENTIAL
The application’s registration takes it for a confidential (web) client.
CONSENT_PERSONAL
Where a personal account withdraws an app’s access.
CONSENT_WORK
Where a work or school account reviews and removes the apps that have access.
CONSUMERS_TID
The tenant every personal Microsoft account signs in to: an ID token whose tid is this one is a personal account’s.
DECLINED
You declined on Microsoft’s page (a personal account).
DECLINED_WORK
Microsoft’s page ended without access for a work account: declined, or an approval wanted.
IMAP_HELP
Microsoft’s page on Outlook.com’s IMAP switch (off by default) and its settings.
IMAP_HOST
IMAP for every account, on 993, encrypted from the first byte.
IMAP_SCOPE
Reading mail over IMAP.
LOGIN
Microsoft’s sign-in: its page, its token endpoint.
LOGIN_TAKEN
Another of your accounts already signs in to Microsoft as this login (it follows): two accounts never share one sign-in, so that removing one cannot sign the other out.
MAILBOX_REFUSED
The mailbox refused the access Microsoft had just given, or stayed closed to IMAP: its switch, most often.
MAIL_SCOPES
What the sign-in asks, all at once: reading, sending, staying signed in, and who you are (no other permission: Microsoft’s terms ask the fewest).
MOST_GENERATIONS 🔒
At most this many generations noted: past them, the oldest are dropped (a crossing leaves one, at most, and each write strikes off what it replaced).
MOST_PARTS 🔒
At most this many entries after the first: a token of about 9 KB, several times the longest reported.
NOT_CONNECTED_PERSONAL
Signed in, but the mailbox stays closed to IMAP: Outlook.com’s switch, or an activity to confirm.
NOT_CONNECTED_WORK
Signed in, but the mailbox stays closed to IMAP: the organisation’s choice, or another account chosen.
OTHER_ACCOUNT
The mailbox did not open with the account Microsoft’s page signed in (that account follows).
OTHER_DECLINED
You said No to the mailbox of the login Microsoft’s page signed in (it follows): nothing kept.
OTHER_HOST
An account signed in with Microsoft whose configuration names another server: nothing sent there.
PASSWORD
A password refused by Microsoft’s IMAP server, which takes only its own sign-in.
REDIRECT
The application has no http://127.0.0.1 redirect under “Mobile and desktop applications”.
REFRESH_SCOPES
What a refresh asks: the mail’s alone (one resource per token).
SCOPES_MISSING
Microsoft’s page gave reading or sending, not both.
SECRET_SENT
A secret was sent: a fault of Sioul’s, never meant to happen.
SMTP_AUTH_HELP
Microsoft’s page on Authenticated SMTP switched off by an organisation.
SMTP_OFF
The organisation switched off sending by mail programs (Authenticated SMTP).
SMTP_PERSONAL
SMTP for personal accounts, on 587 with STARTTLS (Microsoft has no 465).
SMTP_PORT
SMTP_SCOPE
Sending over SMTP.
SMTP_WORK
SMTP for work and school accounts, on 587 with STARTTLS.
TIMEOUT
No answer from Microsoft’s page within five minutes.
UNKNOWN_APP
Microsoft does not know the application (a mistyped id, or a build given a wrong one).

Statics§

ACCESS 🔒
Access tokens, by grant (its keyring name), until about when they end; in memory only.

Traits§

Store 🔒
Where grants are kept: the system keyring, or, in tests, memory.

Functions§

aadsts 🔒
The first AADSTS<digits> of Entra’s description.
access_token
An access token for a login’s mail (IMAP and SMTP alike): the one in memory while it lasts, else a new one from the refresh token, whose successor is kept. fresh asks a new one (after a refusal).
admin_consent_url
The link an organisation’s administrator opens to approve Sioul for everyone there, once: Microsoft’s admin consent, for the organisation’s directory (its id, or the domain of the address; never common).
app_for
The application to sign in with: the id given (yours), else yours kept on this device for this address, else Sioul’s own. None when this build has none and none is given or kept: then each person gives their own.
authority_for
The authority a sign-in goes to: the directory given (an application of your own registered for one organisation), else the kept grant’s (a personal account’s, or its organisation’s), else the kind discovery found.
begin
Opens the door on this device (127.0.0.1 only) and makes Microsoft’s page to open: PKCE’s challenge (S256), a random state, your address as a hint, and the account chooser, since a browser often holds more than one Microsoft account, and a personal and a work account may share an address.
built_in
Sioul’s own application, when the build was given one (SIOUL_MICROSOFT_CLIENT_ID): an id, no secret (Microsoft refuses a secret from a program on your device). The same on every system, the phone’s included. None: each person gives an application of their own.
check_of 🔒
claims 🔒
What the ID token says, from its payload (it came straight from Microsoft’s token endpoint over TLS; Sioul only reads who signed in, and the server’s own login decides): tid, and the address.
finish
Waits for Microsoft’s answer (five minutes at most, or until stop), trades its code for tokens at once (a code lasts about a minute), reads who signed in and whether the account is a personal or a work one, and keeps the grant in the keyring under address. The access token is kept in memory. Who signed in is not checked against the address here: an alias, a shared mailbox, a phone number’s sign-in differ; the mail server’s own login decides (the window’s outlook.rs).
finish_at 🔒
finish, the code traded at token_url (Microsoft’s, or a stand-in in tests), the grant kept in store.
forget
Forgets a login’s grant on this device, keyring and memory. Microsoft is not asked anything (it offers apps no way to give a token back): the page where you withdraw Sioul’s access comes back, a personal account’s or a work account’s.
forget_entries 🔒
forget_entries_in 🔒
Forgets the grant under name: its parts (the generation in use, every generation noted beside it, and the first version’s names), then the first entry; and its access token.
forget_legacy_parts 🔒
forget_parts 🔒
Forgets a generation’s parts: whether every one is gone.
gave_mail 🔒
Whether Microsoft gave what mail needs: reading and sending. An answer without its scopes gives what was asked (Microsoft says so).
generations 🔒
generations_name 🔒
The checks of the generations whose parts may still be in the keyring, the one in use included (<name>#generations): each write notes its own before it writes a part, and the one it replaces; one is struck off only once its parts are gone. Two rotations crossing (the window and a command, each renewing) can leave a generation that no first entry names any more: removal still finds it here (the re-check of 15 October 2026, L2-bis). A short token has no part, and is not noted.
grant
The grant kept on this device for a login (the account’s address, or the user name its mailbox opened with).
is_app_id
Whether a text is an application’s id as Microsoft gives them: a GUID (00000000-0000-0000-0000-000000000000). Anything else (a secret pasted in its place) is refused before Microsoft is asked.
is_imap_host
Whether an IMAP server is Microsoft’s, named exactly: an access token is given to no other.
is_smtp_host
Whether an SMTP server is one of Microsoft’s two, named exactly.
is_tenant 🔒
A directory’s id or domain as Microsoft’s paths take it: letters, digits, dots and hyphens, at most a domain’s length; nothing that could reach another path or host.
kept_in 🔒
What the first entry under name says, read as is.
keyring_name 🔒
Its entry in the keyring: microsoft-mail:<login>, the login lowercased.
legacy_part_name 🔒
A part’s name as the first version of this format had it (<name>#2…), before parts were named after their token: read when the named one is missing, and forgotten at the next write.
load_from 🔒
The grant kept under name, its token joined again from its parts; None when there is none, or when its parts do not make the token it was: then you sign in again, rather than Sioul sending a token that is not one.
message_of 🔒
The message that says a SyncError::Login of this module (“sync-error-microsoft-again”).
move_grant
The grant kept for from moved to to (the user name a mailbox opened with, when it is not the address given), its access token with it.
move_grant_in 🔒
not_connected 🔒
Microsoft’s IMAP refusal that is not about the token: “User is authenticated but not connected”, the mailbox closed to IMAP. Said for what it is, with what to do; no second token is asked.
note_generation 🔒
Notes a generation that has, or is about to have, parts. Read once more after a passing error; not noted when the keyring does not answer.
now 🔒
open_mailbox 🔒
The mailbox tried with the grant just kept under address, before anything else is kept: as the address; refused there (the token refused, or IMAP closed), as the login Microsoft’s page signed in, once, the grant moved there first, unless another account already uses it. Comes back with the account and, when it opened only under that other login (and the account did not already sign in as it, before), that login, for the person’s Yes. Nothing kept when it does not open.
own_app
An application of your own kept on this device for an address (its id, and the directory refreshes go to when it was given one): to sign in with again. Sioul’s own is not “yours”.
part_name 🔒
A part’s name: the entry’s, the check of the token it belongs to, its place (2, 3, 4).
post 🔒
Posts a form to Microsoft’s token endpoint (or a stand-in in tests): HTTPS only, no redirect followed (a refresh token goes nowhere else), no secret. The answer’s JSON, else its refusal said (refusal).
refreshed 🔒
A new access token traded for a grant’s refresh token at endpoint, and how long it lasts, in seconds. Microsoft’s answer brings a new refresh token: kept in store in place of the old one (Microsoft asks it; the old one keeps working until its own end, so a write that fails is said and does not stop the mail, and two of Sioul’s processes refreshing at once do not lock each other out: the last one written stays).
refusal 🔒
What Microsoft’s refusal means, as Sioul says it: OAuth’s error, Entra’s codes (error_codes, else the description’s AADSTS), the account’s kind when known, and the step.
refuse_taken 🔒
Refuses a login that another of your accounts already signs in to Microsoft as (taken: their logins, lowercased): each grant is kept under its login, and two accounts sharing one would sign each other out.
remember 🔒
remember_until 🔒
remembered 🔒
The access token kept in memory under a grant’s name, while it lasts.
save_in 🔒
Writes a grant under name without ever leaving it lost: the new token’s parts first, under names of their own, noted beside it (generations); then the first entry, which names them (the pointer); then it is read back whole before the generation it replaced is forgotten. A write that fails takes back what it wrote, and the grant kept before stays whole; one that does not read back whole puts the entry it replaced back. A read-back that the keyring does not answer, twice, leaves everything as written: what it replaced, noted, goes at the next write or at removal. Two writes crossing (the window and a command, each renewing the token) leave the one written last, whole, and every part of the other noted.
sign_in
Signs an address’s mail in with Microsoft, or signs it in again: Microsoft’s page (show opens it: the window’s browser, the terminal’s line), its answer, then the mailbox itself tried with the access given, before anything is kept (open_mailbox). account comes back at Microsoft’s servers, signed in with Microsoft, its sending server and its kind those the sign-in found. taken: the logins your other Microsoft accounts sign in as, refused here (the address before Microsoft’s page, the login it signed in after). A mailbox that opens only under another login than the address comes back with other_login, for the person’s Yes first; every sign-in ends with its answer (Signed::answer). When the mailbox does not open, nothing is kept.
smtp_refused 🔒
Microsoft’s SMTP refusal that no token changes: Authenticated SMTP switched off for the organisation or the mailbox (5.7.139).
split 🔒
A grant as the keyring keeps it: the first entry at most secret::ENTRY_BYTES long, the token’s rest in parts as long.
strike_generations 🔒
Strikes off generations whose parts are gone; the list itself goes with the last.
test_token 🔒
A local stand-in’s token, in test builds only (insecure-test-tls, never in Sioul’s builds): with it, an account signed in with Microsoft may be pointed at a local IMAP and SMTP server for a test (OAuth::may_reach).
wait_for_code 🔒
The answer Microsoft’s page sends back to this device: its code, checked against the state. An answer whose state is not this sign-in’s is refused, and the wait goes on: a page from an earlier sign-in, or anyone else, cannot end it. An error is read only from an answer whose state is.