engine.yaml: mail and newsletter
Every key of engine.yaml's mail section (the transactional mail driver for SMTP, Postmark, Amazon SES or Resend, bounce webhooks, templates, suppression and broadcast sending) and its newsletter section, with type, default and meaning.
The engine sends mail through a provider or relay you bring; it never runs mail infrastructure. Transactional mail (sign-in links, enquiry notifications, confirmations) uses the mail section. The Newsletter module’s campaigns use the same driver with the newsletter section’s sender and rules.
mail:
driver: postmark
from: "Visit Example <hello@example.org>"
reply_to: help@example.org
postmark:
server_token: ${POSTMARK_SERVER_TOKEN}
webhook_token: ${POSTMARK_WEBHOOK_TOKEN} Check a configuration with a real send:
engine-dmo mail status
engine-dmo mail test --to you@example.org # sends the magic-link template by default | Key | Type | Default | Meaning |
|---|---|---|---|
mail.driver | string | Empty (log) | postmark, ses, resend, smtp, or log (messages are written to the log, development only). engine-dmo check refuses log in production |
mail.from | string | Empty | The sender, hello@example.org or Visit Example <hello@example.org>. Required in production |
mail.reply_to | string | Empty | The Reply-To address |
mail.rate_limit_per_minute | integer | 0 | The most messages a minute each process sends; 0 is no limit |
mail.delivery_record_retention | retention | Empty (13m) | How long delivery records (what was sent to whom, and its outcome) are kept |
mail.smtp
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.smtp.host | string | Empty | The relay’s host. Required for a send |
mail.smtp.port | integer | 0 (meaning 587) | The relay’s port |
mail.smtp.username | string | Empty | The user, when the relay needs authentication |
mail.smtp.password | secret | Empty | The password |
mail.smtp.tls | string | Empty | starttls: require STARTTLS; tls: connect over TLS from the start (port 465); none: never encrypt. Empty uses STARTTLS when the relay offers it. TLS 1.2 or later |
Only Postmark, SES and Resend report bounces and complaints back through a webhook; an SMTP relay does not.
mail.postmark
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.postmark.server_token | secret | Empty | The Postmark server’s API token |
mail.postmark.message_stream | string | Empty | The transactional message stream; empty is Postmark’s default stream |
mail.postmark.broadcast_stream | string | Empty (broadcast) | The stream marketing mail (newsletters and broadcasts) goes out on, so its reputation stays apart |
mail.postmark.webhook_token | secret | Empty | The token Postmark’s bounce and complaint webhook must present. Required in production |
mail.ses
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.ses.region | string | Empty | The AWS region, such as eu-west-2 |
mail.ses.access_key_id | string | Empty | The IAM access key |
mail.ses.secret_access_key | secret | Empty | Its secret |
mail.ses.configuration_set | string | Empty | The SES configuration set that publishes events |
mail.ses.notification_topic_arn | string | Empty | The SNS topic bounces and complaints arrive from; notifications from another topic are refused |
mail.resend
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.resend.api_key | secret | Empty | The Resend API key. Required in production |
mail.resend.webhook_secret | secret | Empty | The signing secret of the webhook endpoint the Resend dashboard shows (whsec_...). Required in production |
mail.webhooks
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.webhooks.path | string | Empty (/_mail/webhooks) | Where the provider posts delivery events. Only the configured driver’s route exists: <path>/postmark, <path>/ses or <path>/resend. Point the provider’s webhook at https://<your host><path>/<driver> |
mail.templates
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.templates.dir | string | Empty (emails) | The subdirectory, in each of a site’s template roots, that holds your mail templates (templates/_shared/emails/). A template there replaces the engine’s of the same name |
mail.templates.plain_text | string | Empty (generate) | generate makes the plain-text part from the HTML when a template has no .txt alternative; require makes a missing .txt an error |
engine-dmo mail templates lists every transactional template, which directory resolved it, and whether a plain-text alternative exists.
mail.suppression
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.suppression.soft_bounce_threshold | integer | 3 | Soft bounces within the window that suppress an address |
mail.suppression.soft_bounce_window | retention | 30d | The window soft bounces are counted over |
mail.suppression.notify_on_suppress | boolean | true | When a CRM contact’s address is suppressed after a hard bounce, notify staff, naming the contact’s organisations (engine-dmo). The suppression is recorded on the contact’s timeline either way |
mail.broadcast
How the CRM’s broadcasts to members are sent (engine-dmo).
| Key | Type | Default | Meaning |
|---|---|---|---|
mail.broadcast.batch_size | integer | 50 | Messages queued at a time, 1 to 1000 |
mail.broadcast.batch_pause | duration | 5s | The pause between batches, 0s to 1h, on top of the mail rate limit |
mail.broadcast.unsubscribe_footer | boolean | Unset (on) | Every broadcast carries an unsubscribe link. false is refused |
mail.broadcast.open_tracking | boolean | false | Count opens with a tracking image |
mail.broadcast.per_recipient_tracking | boolean | false | Record clicks and opens per recipient rather than per broadcast; the footer then says so |
newsletter
The Newsletter module’s sender and rules. Double opt-in is always on.
| Key | Type | Default | Meaning |
|---|---|---|---|
newsletter.from_name | string | Empty | The sender name of campaigns. One line of plain text |
newsletter.from_address | string | Empty | The sender address, a bare address such as news@example.org |
newsletter.reply_to | string | Empty | The reply address, a bare address |
newsletter.double_opt_in | boolean | Unset (on) | false is refused: a subscriber always confirms |
newsletter.pending_expiry | retention | 14d | An unconfirmed subscriber is deleted after this, 1d to 90d |
newsletter.preference_centre_path | string | /newsletter/preferences | The preference centre’s path on each site: starting with /, not /_, no trailing slash |
newsletter.open_tracking | boolean | false | Count opens |
newsletter.click_tracking | boolean | Unset (on) | Send links through a counted redirect; false turns it off |
newsletter.send_rate_per_minute | integer | 600 | Campaign messages a minute, 1 to 100000 |
newsletter.dormant_after | retention | 12m | An active subscriber with no click in this long counts as dormant in the hygiene report. At least 30d |
newsletter.require_domain_verification | boolean | Unset (on) | A campaign is refused until the sending domain passes the SPF, DKIM and DMARC checks (engine-dmo newsletter deliverability) |
newsletter.topics | list of strings | [] | The topics subscribers choose from, as lower case keys |
newsletter.dkim_selectors | list of strings | [] | The DKIM selectors the deliverability check looks up for the sending domain |
See Mail and Newsletters.
engine.yaml: content, media and search
Every key of engine.yaml's content, media, events, tags, approvals, endpoints, forms, search, maps, admin and notifications sections, with type, default and meaning.
engine.yaml: analytics and AI
Every key of engine.yaml's analytics section (cookieless ingest, bot filtering, retention, reporting time zone, PDF reports), its ai section (provider, models, data boundary, budget, features, disclosure) and its translation section, with type, default and meaning.