82 lines
5.6 KiB
Markdown
82 lines
5.6 KiB
Markdown
# 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.
|
|
Reading is the first stage: accounts of the kind `imap`, read-only — nothing here flags, moves, deletes or drafts.
|
|
Sending is `mail_send` alone (novox/hq ADR 0361 §2): it sends nothing itself, and reaches an account's outgoing
|
|
server only once the operator approves it on a channel that proves who answered.
|
|
|
|
## Its seats (novox/hq ADR 0378 as amended by ADR 0379, issue 800 part A)
|
|
|
|
It declares three mail seats and claims the one it holds:
|
|
|
|
- **mail-store** (held once for the mesh) — serves `accounts`, `search`, `read` and `send`; mesh-mail claims it,
|
|
through the same handlers as its own `mail_*` tools. The catalogue's own check (`checks/mailstore`) refuses any
|
|
other manifest that claims it.
|
|
- **mail-webclient** (held once for the mesh) — serves `open` and `status`; unheld until issue 580.
|
|
- **mail-notifier** (held once per machine, needing `node-notifier` there) — serves `status`; held by
|
|
mesh-mail-notifier (issue 800 part B), a module of its own built from this one's source, which tells the
|
|
operator of each new inbox mail through `node-notifier.send`.
|
|
|
|
## 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.<account>.message.<added|changed|removed>`: 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": "<the address>",
|
|
"incoming": {"host": "<the IMAP server>", "port": 993, "security": "tls"},
|
|
"outgoing": {"host": "<the SMTP server>", "port": 465, "security": "tls"},
|
|
"folders": ["optional: the folders watched besides the inbox; every folder when left out"]}}
|
|
```
|
|
|
|
`outgoing` is the server `mail_send` sends through: host, port, and `security` `tls` (465, implicit) or `starttls`
|
|
(587). 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, and who may send from it: a module's name (on every machine),
|
|
`<machine>.<module>`, or `person.<name>`. Nobody by default. It restricts the stream `MAIL` on the bus (a person's
|
|
entry grants nothing there) and the tools `mail_search`, `mail_read` and `mail_send` — the same check for all three.
|
|
|
|
The password of an account is the own secret `mail-credential-<account>`, 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-<account>` while its password is not given |
|
|
| `mail_send` | raises an ask on the operator channel (the account, the recipients, the subject, the first lines) for a caller granted the account; answers at once with the ask's id. Sends nothing itself |
|
|
| `mail_send_status` | where a send stands, by its ask id: waiting, sent, declined, ended without a choice, or not proven |
|
|
|
|
The caller is the runtime's word, never an argument. `mail_send` sends through the account's outgoing server only
|
|
once the operator's Approve comes back on a channel that proves who answered, and once: a warrant delivered twice
|
|
never sends twice (novox/hq ADR 0361 §2).
|
|
|
|
The mail-store seat's four verbs, `mail-store.accounts`, `mail-store.search`, `mail-store.read` and
|
|
`mail-store.send`, answer through the same handlers as `mail_accounts`, `mail_search`, `mail_read` and `mail_send`
|
|
above — the same grants, the same refusals, the same ask-then-Approve for a send.
|
|
|
|
## 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`.
|