indiegoon supports 5 email providers through a unified interface. Like payments, switch providers by changing one env var.
Supported Providers
| Provider | Best For | Setup Difficulty |
|---|---|---|
| Resend | Modern apps, great DX | Easy |
| Postmark | High deliverability | Easy |
| SendGrid | Volume senders | Medium |
| Mailgun | Developers, EU compliance | Medium |
| Nodemailer (SMTP) | Gmail, SES, self-hosted | Easy |
Setup
Using the CLI
goon setup email
Pick your provider. The CLI validates your API key, sets the from address, and configures everything.
Manual Setup
# Choose: resend | postmark | sendgrid | mailgun | nodemailer
EMAIL_PROVIDER="resend"
# Resend
RESEND_API_KEY="re_..."
# Common
EMAIL_FROM_NAME="My SaaS"
EMAIL_FROM_ADDRESS="hello@mysaas.com"
EMAIL_REPLY_TO="support@mysaas.com"
Sending Emails
Basic Usage
import { sendEmail } from "@/lib/email"
await sendEmail({
to: "user@example.com",
subject: "Welcome to My SaaS",
html: "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
})
Using Templates
Auth email templates are pre-built:
import { sendEmail } from "@/lib/email"
import {
welcomeEmail,
verifyEmailTemplate,
passwordResetEmail,
magicLinkEmail,
} from "@/lib/email/templates/auth"
// Welcome email (sent automatically on signup)
await sendEmail({
to: user.email,
subject: "Welcome to My SaaS!",
html: welcomeEmail({ name: user.name }),
})
// Verification email
await sendEmail({
to: user.email,
subject: "Verify your email",
html: verifyEmailTemplate({ url: verificationUrl, name: user.name }),
})
Creating Custom Templates
Add new templates in src/lib/email/templates/:
// src/lib/email/templates/billing.ts
export function invoiceEmail({ amount, date }: { amount: string; date: string }) {
return `
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
<h1>Invoice Paid</h1>
<p>Your payment of <strong>${amount}</strong> on ${date} was successful.</p>
<a href="https://mysaas.com/billing"
style="background: #f59e0b; color: #000; padding: 12px 24px; text-decoration: none; border-radius: 6px;">
View Invoice
</a>
</div>
`
}
Provider Details
Resend
EMAIL_PROVIDER="resend"
RESEND_API_KEY="re_..."
Uses the official Resend SDK. Best developer experience.
Postmark
EMAIL_PROVIDER="postmark"
POSTMARK_SERVER_TOKEN="..."
REST API. Known for excellent deliverability.
SendGrid
EMAIL_PROVIDER="sendgrid"
SENDGRID_API_KEY="SG...."
REST API. Good for high-volume sending.
Mailgun
EMAIL_PROVIDER="mailgun"
MAILGUN_API_KEY="key-..."
MAILGUN_DOMAIN="mg.mysaas.com"
MAILGUN_REGION="us" # or "eu"
REST API with Basic auth. Supports EU region for GDPR.
Nodemailer (SMTP)
EMAIL_PROVIDER="nodemailer"
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="your-email@gmail.com"
SMTP_PASS="your-app-password"
SMTP_SECURE="false"
Works with Gmail (App Password), Amazon SES, Mailtrap, or any SMTP server.
How It's Wired
Auth emails are sent automatically:
- •Signup → Welcome email
- •Email verification → Verification link
- •Forgot password → Reset link
- •Magic link sign-in → Magic link
This is configured in the auth hooks at src/lib/auth/index.ts. You don't need to wire anything manually.
Testing Emails
Development
Use Mailtrap or Ethereal to catch emails without sending to real inboxes:
EMAIL_PROVIDER="nodemailer"
SMTP_HOST="sandbox.smtp.mailtrap.io"
SMTP_PORT="2525"
SMTP_USER="your-mailtrap-user"
SMTP_PASS="your-mailtrap-pass"
Resend Test Mode
Resend delivers to verified domains only in test mode. Send to your own email during development.