saasprokit
Email

Setup Guide

Configure email providers for your environment

Put these in apps/web/.env.local (copied from apps/web/.env.example by pnpm run setup). packages/email/.env.example is reference only.

Schema lives in packages/email/keys.ts. Booleans (SMTP_SECURE, SMTP_POOL) use a stringBool transform — z.coerce.boolean() would treat "false" as true.

Common variables

# Shipped value in apps/web/.env.example
EMAIL_FROM="noreply@yourdomain.com"

# Optional. Unset = auto-detect (see below).
# EMAIL_PROVIDER="resend"
# EMAIL_PROVIDER="nodemailer"

Never set EMAIL_PROVIDER=resend|nodemailer — that is not a valid enum value.

RESEND_API_KEY=re_xxxxxxxxxxxxx
EMAIL_FROM="noreply@yourdomain.com"

Production EMAIL_FROM must be a domain you verified in Resend. An unverified from-address fails the send; Resend does not rewrite it to onboarding@resend.dev.

Auto-detect

When EMAIL_PROVIDER is unset:

ConditionProvider
NODE_ENV=production and RESEND_API_KEY is setResend
Anything elseNodemailer

A RESEND_API_KEY in pnpm dev does not select Resend. NODE_ENV=development is not its own branch.

Factory: packages/email/providers/index.ts (getProviderName(), getEmailProvider()).

What the app actually calls

Auth mail is triggered from Better Auth hooks in packages/auth/server.ts, not from app routes. Subscription mail is packages/auth/stripe-hooks.ts. See Templates for wired vs preview-only.

Troubleshooting

IssueFix
RESEND_API_KEY requiredSet RESEND_API_KEY, or leave EMAIL_PROVIDER unset locally
Connection refused on port 1025docker compose up -d maildev
Emails not appearinghttp://localhost:1080
Invalid senderVerify the domain in Resend; set EMAIL_FROM to that domain

On this page