SMTP presets
z4j sends invitation and password-reset emails through the project's notification channels, not through global env vars. Each email channel is a record in the brain's notification_channels table with the SMTP config inline. Create one per project and z4j picks the first active email channel when it needs to send.
Channel config schema
Section titled “Channel config schema”An email channel's config JSON looks like this:
{ "smtp_host": "smtp.gmail.com", "smtp_port": 587, "smtp_pass": "xxxx-xxxx-xxxx-xxxx", "smtp_tls": true,}| Field | Meaning |
|---|---|
smtp_host |
SMTP hostname. Resolution is checked during validation and again for delivery; loopback, private, link-local, and other blocked address classes are rejected. There is no private-network opt-in for SMTP channels. |
smtp_port |
One of the allow-listed SMTP ports (25, 465, 587, 2525). |
smtp_user |
Username. |
smtp_pass |
Password. |
smtp_tls |
true for STARTTLS on 587 / implicit TLS on 465. |
from_addr |
From: header. RFC 5322 mailbox or display <addr@host> format. |
to_addrs |
Default recipient list. For invitation and reset emails the brain overrides this with the recipient address. |
Create the channel via API (POST /api/v1/projects/{slug}/notifications/channels) or via the dashboard's Notifications page.
Gmail requires an app password (not your account password). Enable 2FA, mint an app password at myaccount.google.com/apppasswords, then create an email channel with:
{ "smtp_host": "smtp.gmail.com", "smtp_port": 587, "smtp_pass": "xxxx-xxxx-xxxx-xxxx", "smtp_tls": true,}OAuth2 against Gmail is not supported; SMTP + app password only.
Mailgun
Section titled “Mailgun”{ "smtp_host": "smtp.mailgun.org", "smtp_port": 587, "smtp_pass": "<mailgun smtp password>", "smtp_tls": true, "from_addr": "z4j <noreply@yourdomain>"}Brevo (formerly Sendinblue)
Section titled “Brevo (formerly Sendinblue)”{ "smtp_host": "smtp-relay.brevo.com", "smtp_port": 587, "smtp_user": "<your brevo smtp login>", "smtp_pass": "<your smtp key>", "smtp_tls": true, "from_addr": "z4j <noreply@yourdomain>"}AWS SES
Section titled “AWS SES”{ "smtp_host": "email-smtp.us-east-1.amazonaws.com", "smtp_port": 587, "smtp_user": "<SES SMTP username>", "smtp_pass": "<SES SMTP password>", "smtp_tls": true, "from_addr": "z4j <noreply@verified-domain>"}SES requires a verified sender domain.
No-email fallback
Section titled “No-email fallback”Without an active email channel, invitation creation still returns its single-use accept URL, so an administrator can deliver that link out of band.
Password-reset requests are different: the public endpoint always returns the same generic accepted response and never exposes the reset token or URL. Without an email channel, self-service password reset cannot deliver its link. Use the fresh-MFA admin password-reset route or z4j changepassword [email protected] --password-stdin for operator-assisted recovery.