How Feeblo sends mail. The SMTP transport variables, the Amazon SES feedback webhook, and the outbox controls.
Feeblo sends every kind of mail through one mailer: verification and password reset links, onboarding and user-feedback digests, weekly summaries, and notifications. The server records each message in an outbox table and a worker inside the server process delivers it, so a failed send retries instead of vanishing.
Sign-up blocks on email by default: new accounts must click a verification link
(AUTH_EMAIL_VERIFICATION_REQUIRED defaults to true). Get SMTP working before you open
registrations, or nobody gets in.
Transports
The repo documents three transport names in .env.example:
| Value | Meaning |
|---|---|
smtp-auth |
default. SMTP with username and password |
smtp-api |
documented option, no implementation in this source |
resend |
documented option, no implementation in this source |
SMTP variables
| Variable | Default | Notes |
|---|---|---|
SMTP_HOST |
127.0.0.1 |
Mail server host |
SMTP_PORT |
2500 |
The dev stack uses 1025 (Mailpit) |
SMTP_USERNAME |
unset | Auth is only attempted when this is set |
SMTP_PASSWORD |
unset | Paired with SMTP_USERNAME |
SMTP_SECURE |
false |
true forces TLS on the connection |
SMTP_UNSAFE_IGNORE_TLS |
false |
true skips TLS even when the server offers STARTTLS |
SMTP_SERVICE |
unset | Well-known nodemailer service name (for example gmail) |
SMTP_FROM_ADDRESS |
hello@feeblo.com |
The from address for all mail |
SMTP_FROM_NAME |
unset | Listed in .env.example, but no code reads it; setting it does nothing |
SMTP_PERSONAL_FROM_ADDRESS |
unset | Sender for onboarding and user-feedback mail; falls back to SMTP_FROM_ADDRESS |
TLS behavior follows nodemailer semantics. With SMTP_SECURE=true, the connection
upgrades to TLS up front. With SMTP_SECURE=false (default) the client uses STARTTLS
when the server offers it, and SMTP_UNSAFE_IGNORE_TLS=true disables even that. Leave
the ignore flag alone unless your relay serves plaintext only.
The from-address trio deserves attention before you launch:
SMTP_FROM_ADDRESSappears on every message unless a template overrides it.SMTP_PERSONAL_FROM_ADDRESSgives personal lifecycle mail (onboarding, user feedback) its own sender. Unset, it falls back toSMTP_FROM_ADDRESS.- Skip
SMTP_FROM_NAME: it sits in.env.exampleas “required”, but nothing in the codebase reads it.
Outbox controls
Delivery pauses and cost guards are environment-driven so an operator can react without
redeploying. All five variables are optional and live in packages/domain/src/email-outbox/:
| Variable | Default | Meaning |
|---|---|---|
EMAIL_OUTBOX_GLOBAL_DELIVERY_PAUSED |
false |
true stops all outbound delivery immediately |
EMAIL_OUTBOX_MAX_CONCURRENT_SENDS |
10 |
Worker concurrency; clamps to at least 1 |
EMAIL_OUTBOX_MONTHLY_SEND_LIMIT |
100000 |
Monthly send budget; clamps to at least 1 |
EMAIL_OUTBOX_ESTIMATED_SEND_COST_MICROS |
100 |
Assumed cost per send in microdollars for cost tracking |
EMAIL_OUTBOX_PAUSED_WORKSPACE_IDS |
empty | Comma-separated workspace IDs whose mail is paused |
Set EMAIL_OUTBOX_GLOBAL_DELIVERY_PAUSED=true while you migrate providers or fix a
bounced-sender problem. Messages keep queuing in the outbox, and delivery resumes when
you flip the flag back. EMAIL_OUTBOX_PAUSED_WORKSPACE_IDS pauses a single tenant the
same way; the server splits the comma-separated list and trims whitespace.
Amazon SES feedback webhook
Feeblo can ingest Amazon SES delivery events: deliveries, bounces, and complaints. Two variables switch it on:
EMAIL_PROVIDER_WEBHOOK_TOKENactivates the webhook atPOST /email-provider/ses/:token. Generate it withopenssl rand -hex 32. The token must not be derivable fromAUTH_ENCRYPTION_KEY, so a dedicated random value is required.EMAIL_PROVIDER_SNS_TOPIC_ARNfilters incoming messages by their signed SNS topic. Set it whenever the token is set: the webhook rejects messages whoseTopicArndoes not match, and without it the source is unverifiable, so requests get rejected anyway.
Subscribe your SNS topic to:
https://<API_URL>/email-provider/ses/<EMAIL_PROVIDER_WEBHOOK_TOKEN>
Leave both variables unset and the route stays inert (404). SNS sends its notifications
over a publicly reachable HTTPS URL, so point the topic subscription at the server’s
public API_URL.