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
partsmore, and the start of the whole token’s SHA-256, itscheck. 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
tidsettles 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
tidis 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.1redirect 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.
freshasks 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 underaddress. 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’soutlook.rs). - finish_
at 🔒 finish, the code traded attoken_url(Microsoft’s, or a stand-in in tests), the grant kept instore.- 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
namesays, 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::Loginof this module (“sync-error-microsoft-again”). - move_
grant - The grant kept for
frommoved toto(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 instorein 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
namewithout 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 (
showopens 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).accountcomes 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 withother_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_BYTESlong, 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.