Skip to content

Configuration reference

Every runtime setting Mailify honors lives in this table. The same value can be set three ways — TOML, dotenv, or direct process env — with precedence resolved as documented in Concepts: Config precedence.

Mailify looks for a TOML config file in this order at startup, using the first one that exists:

  1. $MAILIFY_CONFIG (explicit path)
  2. ./Mailify.toml in the current working directory
  3. Per-user config dir:
    • Linux/macOS: $XDG_CONFIG_HOME/mailify/config.toml (fallback ~/.config/mailify/config.toml)
    • Windows: %APPDATA%\mailify\config.toml
  4. /etc/mailify/config.toml (Unix system-wide, last resort)

If no file is found, defaults + env vars still drive config.

The env prefix is MAILIFY_. Nested keys use double underscore __:

TOML pathEnv var
server.hostMAILIFY_SERVER__HOST
smtp.hostMAILIFY_SMTP__HOST
auth.api_keys.webMAILIFY_AUTH__API_KEYS__WEB
theme.colors.primaryMAILIFY_THEME__COLORS__PRIMARY
KeyTypeDefaultPurpose
hoststring0.0.0.0Bind address. Use 127.0.0.1 for loopback-only.
portu168080HTTP listen port.
request_timeout_secsu6430Per-request timeout applied by tower-http.
body_limit_bytesusize10485760 (10 MiB)Max request body. Raise if you attach large files via /mail/send-custom.
KeyTypeDefaultPurpose
urlstringpostgres://mailify:mailify@localhost:5432/mailifyPostgres connection URL. Used by apalis for job storage and migrations.
max_connectionsu3210sqlx pool upper bound.
min_connectionsu321sqlx pool lower bound (kept warm).

Process-wide default SMTP sender. Can be overridden per-job via smtp_override.

KeyTypeDefaultPurpose
hoststringlocalhostSMTP server hostname.
portu161025SMTP port. 25/587/465 in prod, 1025 for Mailpit dev.
usernameoption<string>SMTP AUTH user. Omit for unauthenticated.
passwordoption<string>SMTP AUTH password. Never logged.
tlsenumnoneOne of none, starttls, tls. starttls for 587, tls for 465.
default_from_emailstringno-reply@mailify.localDefault From: when the caller omits it.
default_from_nameoption<string>MailifyDisplay name paired with default From.
timeout_secsu6430lettre SMTP client timeout.
KeyTypeDefaultPurpose
jwt_secretstringCHANGE_ME_IN_PRODUCTIONHS256 secret. Must be changed in prod.
jwt_issuerstringmailifyiss claim.
jwt_ttl_secsu643600JWT lifetime.
api_keysmap<id, hash>{}Argon2-hashed API keys. Key = id, value = hash.
bootstrapbooltrueIf true and api_keys is empty at boot, auto-generate an ephemeral key.

Generate an argon2 hash:

Terminal window
make hash-key KEY=my-secret ID=web
# or
cargo run -p mailify-auth --example hash-key -- "my-secret" "web"

Paste the printed MAILIFY_AUTH__API_KEYS__WEB=… line into your env source.

KeyTypeDefaultPurpose
worker_concurrencyusize4Simultaneous in-flight jobs the worker will run.
max_retriesusize5Max retry count before a job is marked Failed.
retry_backoff_secsu6430Seconds between retries.
KeyTypeDefaultPurpose
pathpath./templates-parser/outDirectory with compiled HTML bundle.
strictboolfalseIf true, missing built-in template files for the default locale fail startup.

Branding tokens injected into every render under the {{ theme.* }} namespace.

KeyTypeDefaultPurpose
brand_namestringMailifyShown in subject lines, footer, default logo alt.
brand_logo_urloption<string>Public URL to the logo (prefer HTTPS + CDN).
radiusstring8pxCSS radius token applied to buttons/cards in templates.
footer_textoption<string>Footer legalese.
social_linksmap<string, string>{}Social icon → URL map.
extramap<string, string>{}Arbitrary key/value bag for custom template variables.

All hex strings.

KeyDefault
primary
primary_foreground
secondary
secondary_foreground
background
foreground
muted
border
danger
success
KeyDefault
body
heading

See Configure theme for the full mapping to minijinja spans in templates.

KeyTypeDefaultPurpose
default_localestringenUsed when a send request omits locale.
fallback_chainlist<string>["en"]Tried in order when the requested locale’s asset is missing.
supported_localeslist<string>["en", "fr"]Declared locales — used by startup strict-mode checks.
KeyTypeDefaultPurpose
log_levelstringinfotracing env filter. Overridden by RUST_LOG if set.
log_formatenumprettypretty or json. Use json for structured log shipping.

In addition to the OS env, Mailify reads the first existing .env-style file from:

  1. $MAILIFY_DOTENV_PATH
  2. .env.<MAILIFY_ENV>.local
  3. .env.<MAILIFY_ENV>
  4. .env.local
  5. .env

Existing env vars are not overridden — dotenv only fills gaps. Disable dotenv entirely with MAILIFY_DOTENV=false.

[server]
host = "0.0.0.0"
port = 8080
[database]
url = "postgres://mailify:secret@db.internal:5432/mailify"
max_connections = 20
[smtp]
host = "smtp.resend.com"
port = 587
tls = "starttls"
username = "resend"
# password loaded from env: MAILIFY_SMTP__PASSWORD
default_from_email = "hello@acme.com"
default_from_name = "Acme"
[auth]
jwt_secret = "a-very-long-random-secret-from-a-secret-manager"
jwt_ttl_secs = 900
bootstrap = false
[auth.api_keys]
web = "$argon2id$v=19$m=19456,t=2,p=1$...hash..."
[queue]
worker_concurrency = 8
max_retries = 10
[theme]
brand_name = "Acme"
brand_logo_url = "https://cdn.acme.com/logo.svg"
footer_text = "© Acme Corp · 100 Main St · San Francisco"
[theme.colors]
primary = "#2D5BFF"
primary_foreground = "#ffffff"
[observability]
log_format = "json"