# mesh-mail — the operator's mail accounts, watched and said on the bus One module holds the operator's mail accounts, watches them, and says each change of a message on the bus for the modules the operator grants it to (novox/hq ADR 0359, research 049 document 02). One instance, on the control-node. This is the first stage: accounts of the kind `imap`, read-only. Nothing here flags, moves, deletes, drafts or sends. ## What it does - **Watches.** For each account it keeps one connection: IDLE on the inbox, ended and begun again every two minutes (which proves the server still answers), and a look at every other folder every five minutes. Folders are opened read-only and bodies are peeked, so watching never marks a message seen. - **Indexes.** One row per message and folder in its own database (`postgres-database`): metadata, flags, the text for search, and the attachments' references. Each attachment is kept once, by its SHA-256, in its bucket (`s3-bucket`, from `minio`). - **Says each change.** A message added, its flags changed, or removed is said as the event `mail..message.`: account, folder, uid, message id, date, sender, recipients, subject, size, flags and attachment references; never the body, never an attachment's bytes. The events go to the module's own stream `MAIL`, kept seven days, never to the shared EVENTS stream (novox/hq ADR 0363); a module hears an account's part only when its `consumes` names mesh-mail and the setting `grants` names it for that account. The first look at a folder indexes what is there and says nothing: the bus hears what changed since the watch began. The keeper writes each event in the same step as the change it says; the bundle says it through the runtime and removes it once the bus took it. ## Its settings, both trusted `accounts` — per account name (a lower-case token, which names the account on the bus and its secret): ```json {"mesh": {"kind": "imap", "address": "", "incoming": {"host": "", "port": 993, "security": "tls"}, "outgoing": {"host": "", "port": 465, "security": "tls"}, "folders": ["optional: the folders watched besides the inbox; every folder when left out"]}} ``` `outgoing` is read and never used in this stage. A second `imap` account on another server is one more entry and one more password; no code changes. `user` signs in under another name than the address. `grants` — per account, who may read its mail: a module's name (on every machine), `.`, or `person.`. Nobody by default. It restricts the stream `MAIL` on the bus (a person's entry grants nothing there) and the tools `mail_search` and `mail_read`. The password of an account is the own secret `mail-credential-`, given at the desk; the mesh never makes one. ## Its tools | Tool | Answers | |---|---| | `mail_accounts` | each account's kind, state and why, when its server last answered, its folders; the address only to a caller granted it | | `mail_search` | messages of the accounts the caller is granted, by every word of a query, newest first, no body | | `mail_read` | one message's metadata and text, or one attachment's bytes, to a caller granted its account | | `mail_health` | healthy; unhealthy naming the account and why (connection down, or no answer for five minutes); waits naming `mail-credential-` while its password is not given | The caller is the runtime's word, never an argument. ## Its processes `prepare` brings the index's schema to this version's (numbered migrations, and `schema.sql` for a fresh database). `keep` watches the accounts and is judged by its unit. `watch` judges every minute and is judged by `mail_health`.