Email Providers
Configure Resend, Postmark, Cloudflare, Plunk, SES, SendGrid, Mailgun, Nodemailer, or local console mail.
Select config.mailing.provider: console, resend, postmark, cloudflare, plunk, ses, sendgrid, mailgun, nodemailer or custom. Templates call the same sendEmail helper whichever provider is selected.
| Provider | Configuration |
|---|---|
| Resend | RESEND_API_KEY, or the supported admin integration form |
| Postmark | POSTMARK_SERVER_TOKEN |
| Cloudflare | CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_EMAIL_API_TOKEN |
| Plunk | PLUNK_API_KEY |
| Amazon SES | SES_REGION, SES_SMTP_USER, SES_SMTP_PASSWORD |
| SendGrid | SENDGRID_API_KEY |
| Mailgun | MAILGUN_SMTP_USER, MAILGUN_SMTP_PASSWORD, MAILGUN_REGION (us / eu) |
| Nodemailer / SMTP | MAIL_HOST, MAIL_PORT, MAIL_USER, MAIL_PASS |
| Console | No provider credentials; writes local mail output |
| Custom | Implement send in packages/mail/provider/custom.ts |
Resend, Postmark, Cloudflare and Nodemailer take the sender from resolved template settings, falling back to config.mailing.from. Plunk uses its service-configured sender; the adapter does not pass a sender field. MOCK_SERVICES=true forces the console provider. Missing keys for a selected real provider do not automatically select console.
The console provider logs mail and maintains the local .vibekit/mail-trap.json test trap. Treat its content as private because verification codes and links can appear there.
SES, SendGrid and Mailgun
These named adapters reuse Nodemailer on port 587 with required STARTTLS and the sender from resolved template settings. Select the adapter in /app/admin/setup or config.mailing.provider; environment credentials override saved integration values.
- SES: choose an SES region with an SMTP endpoint, generate SMTP credentials in that same region, verify your sender identity, and request production access if the account is still in the sandbox.
SES_SMTP_PASSWORDis an SMTP password, not an AWS secret access key. - SendGrid: create an API key with Mail Send permission and authenticate your sending domain or verify the sender. The adapter uses the fixed SMTP username
apikeywithSENDGRID_API_KEYas its password. - Mailgun: verify the sending domain and use that domain's SMTP username/password. Match
MAILGUN_REGIONto the domain's region; it defaults tous. An HTTP API key is not an SMTP password.
After configuration, verify a test message's delivery and failure handling on the selected provider. DNS values must come from your account's dashboard.
Add a provider
Use MailProvider / SendEmailHandler from mail: send({ to, subject, text, html? }) returns Promise<void> and must reject on delivery failure. Implement the existing custom adapter, or add a provider ID to packages/config/providers.ts and a matching lazy resolver in packages/mail/provider/index.ts. Keep template rendering and translation in packages/mail/util/templates.ts; adapters deliver already-rendered content.
If a vendor SDK is needed, add it to packages/mail/package.json and update bun.lock. Test rendering separately from delivery, then verify the adapter's failure path and a real test delivery before production use.
Domain verification
Copy domain-verification, DKIM, SPF and return-path records from the selected provider's dashboard for your exact domain and region. There is no universal set of DNS values that works for every account, and authentication alone cannot guarantee inbox placement. Configure DMARC to match your domain's existing sending services before enforcing a rejection policy.
See Email Templates.
When adding a provider ID, also add its credential-guidance entry in packages/config/providers.ts. This supports product validation and setup guidance; a product manifest does not automatically select a runtime adapter.