A server sends mail through one email service in tablewalk.json; an App
never names a credential or an address to send from.
{ "name": "mail", "kind": "email", "url": "smtps://smtp.example.com:465", "auth": { "username": "${SMTP_USER}", "password": "${SMTP_PASSWORD}" } }url |
What it does |
|---|---|
smtps://host:465 |
TLS from the first byte. |
smtp://host:587 |
Must offer STARTTLS, or nothing is sent; "insecure": true allows a plain relay on a trusted network. |
log: or log:mail.log |
Sends nothing: each message is one JSON line on stdout, or in the file (beside the config file). For development and tests. |
Credentials are ${VARIABLE} references, expanded when the transport opens
and never logged. The host resolves through the same network rules as every
other connection; link-local addresses are refused unless "allowLinkLocal": true.
What is sent
Section titled “What is sent”- Notifications a
notifyrule marksemail: true, and its mentions (notifications). - A status check’s step-up code and a form’s email proof (commands).
- Sign-in links: account verification on sign-up, password resets, and a note when an application is added to an account.
A server whose App asks for any of these and names no email service does not start.
After the write, never inside it
Section titled “After the write, never inside it”A notice’s email is queued in the write’s own transaction, beside the notice
(the inbox store’s __tablewalk_inbox_mail), and sent once the write has
committed: a rolled-back write queues nothing, and nothing is sent while a
transaction is open. The sender checks each message again as its recipient:
an address with no account, an account that turned email off and a record
its grants cannot read are dropped unsent. A failed send is tried again after
a minute, doubling to an hour; after eight tries, or a refusal for good, the
row is kept as failed with the reason. A send never fails the write.