# Mail Portal writes every mail itself and hands it to gdo to deliver (`portal.mail.send`); a reply comes back as a note beside the record (`portal.mail.received`). A mail is a subject and a markdown body with `{placeholders}`, sent as text with an HTML alternative. The kinds of mail are the ones content declares on a state (see [State machines](state-machines.md#mail)), the invite and its rewording (`invite: { group, mail }`, `mail.invite` in site.yaml), the note to a person named responsible for a question, and the answers to a suggested change. ## Variables A placeholder is `{` letters, digits, `_`, `-` or `.` `}`. One that names nothing renders as nothing; a brace that opens no name stays a brace. The variables come in layers, so a template written for one kind of mail reads the same in another. **On every mail** | | | |---|---| | `{site}` | the instance's public URL, no trailing slash | | `{site_name}` | site.yaml's `title` | **On a mail about a record** (every state mail) | | | |---|---| | `{field}` | any field of the record, as the form sent it | | `{chain}` | the record's id | | `{email}` | the record's `email` field, trimmed | | `{bucket}`, `{state}` | where it is and the state it just entered | | `{notice.field}` | a field of the record this one belongs to, through its `type: record` field `notice` | | `{self_link}` | the record's own page for the person it belongs to: a page offering a self-service move (`self_transition`) on the bucket from the state the record is in, with the `?chain=&email=` that lets them act without signing in. Empty when there is no such page or no address | | `{desk_link}` | the desk that moves the record: the page whose list over the bucket has `transitions`, else one that reads it. Empty when no page reads the bucket | | `{link}` | where this reader acts: `{self_link}` in a mail `to: submitter`, `{desk_link}` in one to anyone else, and `{site}` when that link is empty | `{link}` is the one to reach for. "Se meldingen og avtal befaring: {link}" sent to the caretaker opens the desk the report is on; "Feilen du meldte om er utbedret. {link}" sent to the tenant opens their own case where they can still act on it, or the site when there is nothing left for them to do. **On an invite and the note to someone responsible**, beside every field of the invite's form: `{name}`, `{username}`, `{email}`, `{group}` (invite), `{questions}` (responsible), `{expires}`, and `{link}`, which here is the one-time sign-in link. ## What the lint holds a mail to A state mail that sends from a state no record reaches warns; one that names a field no form recording into the bucket collects fails, since it would go out with a blank where the field should be. The lint knows every variable above, so `{link}` and the rest are never flagged. `to: submitter` requires a required `email` on every form filling the bucket, and `to: "{notice.email}"` requires the `notice` field.