# Email templates and sending

This topic has the exact rules for how an email's templates are checked
and how the email is sent ([Email](email.md) has the overview).

## Rendered when it is sent

The outbox keeps an email's fields as its payload: its type's contract
JSON, within the outbox's 64 KB limit
([Limits and runtime faults](limits-and-runtime-faults.md)).
Its delivery renders it as it is sent: its templates, its subject and
its attachments. A rendered body never fills the outbox, and a retry
renders the same text from the same fields.

## A template is a callable

Each `.html` and `.txt` is read beside its type, as a prompt's text is
([Prompts as files](prompts-as-files.md)). The body checker checks
it as a pure callable taking its email's fields, with `to` and `locale`
first, and lowers it to a typed body the executor runs, so its
expressions are Jadpo's own, typed once. The layout's callable takes
`content`, `subject` and `locale`.

## At least one template

An email has an `.html`, a `.txt` or both. These are
`email.template_missing`: an email with neither, a template named after
no email, and a file in `shared/emails/` other than the layout's two.

## What a template may do

A template may use literals, its names and their fields, comparisons,
`and`, `or`, `not`, enum values, translations and `text.format`.
Arithmetic, any other call, building a value, and reading a setting or
a constant are `email.template_not_allowed`. Translations and
`text.format` take the email's locale when `locale:` is left out.

`{{ locale.direction }}` is Jadpo's wording of `TextDirection`
(`jadpo.text_direction`): `ltr` or `rtl`, unless the root translations
file rewords it. `{{ app.display_name }}` is
`application { display_name: }`, plain text on one line.

## What is written out

- A value that may be `none` is refused.
- A number is written by `text.format` in the email's locale.
- An enum is written by its wording.
- `Html` is written as it is in an `.html` template, and refused in a
  `.txt` one.
- Everything else is escaped in HTML: `&`, `<`, `>`, `"` and `'` become
  character references.

## A subject in every locale

An email's entry in its domain's language files is required in every
supported locale that isn't in progress, as a message's wording is
(`translation.wording_missing`).

## A field nothing reads

A field nothing reads is `email.field_unused`, which you can decline.
`to`, `locale` and `File` fields, which are attachments, are never
reported, and a field the subject's wording writes in any locale counts
as read.

## The layout

When the layout exists, it wraps each body: the `.html` in
`layout.html` and the `.txt` in `layout.txt`. You can keep either file
without the other. Without a layout, "Jadpo's plain layout" is the
template's own text, sent as it is.

## `email:`

`email:` names a connection with `driver: Driver.smtp`, or a mail
package's connection that fills `email`. Its `from:` is an `Email`
setting or an address written out. Emitting an email with no `email:` is
`email.connection_required`.

## Its delivery

Each email type has a subscriber of its own, `email <domain>.<Type>`,
tried as a subscriber is by default: 10 attempts within 24 hours. Its
record alone says it went.

The delivery renders the email first, so an email that can't be
rendered is settled as a subscriber's fault is, and nothing is sent.
Then it is marked `sending` and sent with no key. The driver is given
`from`, `to`, `subject`, `html`, `text` and `attachments`: each
attachment's name, media type and bytes, read whole from its store, at
most 10 MB, as `store.read` reads.

## Development and tests

`jadpo test` gives the email connection a driver that catches each
message and answers that it went, so every email is rendered and nothing
leaves your machine. `jadpo dev` catches mail the same way, in the dev
inbox.

## Where a partial is declared

A partial such as
`type Button = EmailPartial { label: PresentationText  url: Url }` is
declared in `shared/emails/` or a domain's `emails/`, with its `.html`
and `.txt` beside it as an email's are, and called with its fields by
name.
