account-api: the account service
Standard port(s): bind 8180, health 8191.
Wallet-challenge login (issuing a JWT), plus mail passwords, timezone, and do-not-disturb schedule management.
With a [chain] section configured, the API additionally serves the
authenticated /v1/chain surface — an on-chain read proxy (SOL balance,
mailbox, published encryption key, aliases, per-sender stamp balances)
plus a relay for transactions the client built and signed itself. This is
the browser-reachable surface the Thunderbird extension rides: mail-grpc
holds a hot signing key and speaks raw gRPC, so browsers never talk to it
directly. Reads always answer for the JWT’s wallet; the relay never signs
anything. Without [chain], those routes answer 503.
The API also serves the /v1/mail surface — the user-facing mail
routes (folders and folder CRUD, message pages with parsed summaries,
full rendering, raw/part downloads, flags, move/delete, and a capped
scan search with a resume cursor) over the same store the
IMAP/POP servers serve. No IMAP bridge is involved: webmail and the
Outlook add-in read the rows and blobs directly through these routes,
authenticated by the same JWT as the account surface. It needs no
configuration beyond [store].
The one write route that leaves the store is compose
(POST /v1/mail/send): the API builds the RFC822 message and spools it
through the same core sithbitd’s SMTP sink uses — local recipients get
mailbox rows and background chain jobs, foreign domains get relay jobs
the spooler’s relay worker drains (the two binaries share the store, so
no extra wiring), and the composer gets an already-read Sent copy.
Routing is configured by the [mail] section: local_domains names the
domains whose recipients live in this store (mirror sithbitd’s
local_domains; aliases and the stamp precheck resolve over the
[chain] gateway — without one, only literal wallet addresses resolve
locally), and [mail.dkim] (same one-or-many shape as
[spooler.dkim]) signs composed mail. Both default off: with no local
domains everything relays — mail addressed to this deployment’s own
domain then loops back through its MX, which is correct, just slower —
and with no keys relayed mail goes unsigned.
Two semantics worth knowing when these routes mutate mail:
- Move settles the source’s chain copy. Exactly like IMAP MOVE, a move is copy + expunge: the surviving copy is server-local, and the original’s on-chain message and IPFS pin are torn down in the background. Deleting does the same teardown directly.
- IMAP IDLE sees API changes with a delay. The API and
sithbitdare separate processes, so a webmail mutation reaches an idling IMAP client viasithbitd’s change poller ([imap] watch_poll_seconds), not instantly. Flag-only changes on a SQLite store don’t bump the change sequence at all — they surface with the next real mailbox event.
With a [static] section configured, the API also serves a static
directory (default route /addin) on its own origin — this is how the
Outlook add-in’s built bundle (webclients/outlook/staging) is hosted,
so the add-in’s pages call /v1/… same-origin with no CORS
configuration. Office requires the add-in over https: either front
the API with a TLS-terminating reverse proxy (the production
recommendation) or enable the built-in [tls] listener. A dev
certificate for sideloading is one command —
openssl req -x509 -newkey ed25519 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost"
— then trust cert.pem in the OS store (Office rejects untrusted
certificates even on localhost).
When you need it: only if you’re exposing self-service account management — for example, the Thunderbird extension, the Outlook add-in, or a webmail UI — rather than administering accounts purely through the CLI.
Quickstart:
cargo run -p account-api
Config file account_api.toml, or point ACCOUNT_API_CONFIG at an
alternate path. It shares sithbitd’s [store] — point both at the same
database so account state and mail state stay consistent.
See the Configuration reference for the full key/default table.