An app's email goes out as the app — through your own mail server, in the app's branding, logged in the app.
When your app sends email (an invoice reminder from a handler, a sign-in code to one of its users), it goes out as the app:
- from your own mail server, through an email connection your organization set up, on your domain's reputation rather than Authoric's;
- in the app's look: its name, logo, colors and footer. Nothing of Authoric's appears in an app's mail;
- into the app's own email log, where you can preview every message exactly as it was sent, with secrets masked.
The pieces fit together like this:
| Piece | Where | What it is |
|---|---|---|
| Email connection | Integrations › Email (your organization) | One of your mail servers (SMTP), tested, with the addresses it may send as |
| Grant | App integrations › Email (the app) | Lets one app send through a connection, under an alias its handlers write |
| Branding | App settings › Branding (the app) | How the app's email looks |
| Email log | App logs › Email (the app) | Every message the app sent, as sent |
An app sends nothing until it is granted a connection. That is deliberate: deny by default.
1. Connect a mail server
Any provider that offers SMTP works: Postmark, SendGrid, Mailgun, Amazon SES, Google Workspace, Microsoft 365, or your own server. Under Integrations › Email, choose Connect a mail server and give it:
| Field | Notes |
|---|---|
| Name | For you: "Postmark (transactional)". |
| Mail server and port | An SMTP submission port: 587, 465, 25 or 2525. A host that resolves to a private or reserved address is refused (EMAIL_HOST_BLOCKED). |
| Security | STARTTLS (port 587, the usual choice) or TLS (port 465). Unencrypted connections are for development mail catchers only. |
| Username, Password or API key | Encrypted when stored, and never shown again. |
| Senders | The addresses this connection may send as: an address (hello@example.com) or a whole domain (@example.com). |
| Default sender | One of the senders, used when a handler names none. |
| Reply-to | Optional. Where replies go when nothing else says. |
Test and connect logs in to the server before anything is stored; a server that refuses is
reported with its reason (EMAIL_CONNECTION_FAILED). Test again can also send a short test
message to an address you give.
Editing where or how a connection connects returns it to untested. Apps keep their grant, but
nothing sends through it (EMAIL_CONNECTION_UNVERIFIED) until you test it again. Removing a
connection stops every app it was granted to from sending through it.
Connecting and granting mail servers is the Email connections permission; removing one, or an app's grant, is Disconnect email connections. Your organization's owner holds both; give them to others in Access › Policies.
2. Grant it to an app
Open the app, go to App integrations › Email, and choose Add a sender. Pick the mail server and an alias: the name the app's handlers will write.
await sdk.sendEmail("billing", { to: invoice.billing_email, subject: "Your invoice", body: ["…"] });- An alias is lowercase letters, digits and underscores, starting with a letter, and unique in the
app (
EMAIL_ALIAS_IN_USE). Revoke it to point it at another connection. - One grant is the app's default. The first grant an app gets becomes it; Make default
moves it.
sdk.sendEmail(message)with no alias uses the default, and so do the app's own sign-in, password-reset and invitation emails (see Branding and the app's own email). - A handler may name the connection by its uid instead of an alias. The page shows both.
- Revoke removes a grant. If it was the default, the oldest remaining grant becomes the default.
- Only a tested connection can be granted.
Because handlers write the alias, not the connection, you can move the app to another provider by granting the new connection under the same alias. No code changes.
3. Send
From a handler, sdk.sendEmail. It needs the sdk:external_email capability, which is deny by
default, so the handler's author (and its approver) must hold it. Everything about the message,
placeholders and duplicates is in Sending email.
The email log
App logs › Email lists every message the app sent through its own connection: who it was to,
the subject, its status (sending, sent or failed, with the server's reason), when, which
handler or job sent it, and each message's organization. Opening a message shows it exactly as its
recipient got it, in a sandboxed preview, with its plain-text part and details.
- Values written as
{{secret}}placeholders appear as•••in the log. Everything else is kept as sent. See placeholders. - The log row is written outside the handler's transaction. A handler that sends and then rolls back has still sent, and the log says so.
- Reading the log is its own permission (Read sent email), separate from reading request logs, because message bodies are your customers' personal data.
- Messages are kept for your plan's data-retention window, then deleted, bodies and envelope together.
Errors
| Code | Status | When |
|---|---|---|
EMAIL_NOT_GRANTED | 403 | The app has no grant by that alias, or no default. |
EMAIL_CONNECTION_UNVERIFIED | 409 | The connection changed and has not been tested since. |
EMAIL_FROM_NOT_ALLOWED | 403 | from is not one of the connection's senders. |
EMAIL_CONNECTION_INVALID | 400 | The server settings are not usable (host, port, security). |
EMAIL_SENDER_INVALID | 400 | A sender is not an address or a domain, or the default sender is not one of them. |
EMAIL_HOST_BLOCKED | 400 | The mail host resolves to a private or reserved address. |
EMAIL_CONNECTION_FAILED | 502 | The server could not be reached, refused the login, or failed the secure connection. |
EMAIL_ALIAS_IN_USE | 409 | The alias already names another connection in this app. |
Sending has its own errors; see Sending email.