LogoLaunchSaaS

Email

Configure email providers for transactional emails

Email

LaunchSaaS supports multiple email providers with an extensible architecture. You can easily switch between providers, add custom implementations, or disable email entirely.

Supported Providers

  • Resend - Modern email API with React email templates
  • Custom - Extend with your own email provider

Configuration

Configure your email provider in src/configuration/features.ts:

export const features: Features = {
  email: {
    provider: "resend", // "resend" | "disabled"
  },
  // ... other features
};

Setup Resend

1. Create Resend Account

  1. Sign up at resend.com
  2. Verify your email address
  3. You get 100 emails/day on the free tier

2. Get API Key

  1. Go to API Keys in Resend Dashboard
  2. Click "Create API Key"
  3. Give it a name (e.g., "LaunchSaaS")
  4. Add to your .env file:
RESEND_API_KEY="re_..."

3. Configure Sender Email

For development, use the Resend test email:

RESEND_FROM_EMAIL="[email protected]"

For production, you'll need to verify your domain (see below).

If you are setting up the environment, now you can go back to the Environment Setup guide and continue.

Domain Verification (Production)

To send emails from your own domain:

1. Add Domain

  1. Go to Domains in Resend Dashboard
  2. Click "Add Domain"
  3. Enter your domain (e.g., yourdomain.com)

2. Add DNS Records

Resend will provide DNS records to add:

  • MX records - For receiving bounces
  • TXT records - For domain verification (SPF, DKIM)

Add these records to your DNS provider (e.g., Cloudflare, Namecheap).

3. Verify Domain

  1. Wait for DNS propagation (can take up to 48 hours)
  2. Click "Verify" in Resend Dashboard
  3. Once verified, update your environment variable:
RESEND_FROM_EMAIL="[email protected]"

Email Templates

Email templates are located in src/components/email/ and support internationalization (i18n):

TemplateDescription
email-verification.tsxSent on user signup
reset-password.tsxPassword reset flow
magic-link.tsxPasswordless login
payment-completed.tsxPayment confirmation
welcome.tsxPost-verification welcome

i18n Support

Email templates automatically use the user's preferred locale (stored in the locale field of the user table). The locale is determined in the following order:

  1. User's saved locale preference (from user profile)
  2. Locale from the request (via NEXT_LOCALE cookie set by next-intl)
  3. Default locale (en)

Email translations are defined in messages/[locale].json under the Email namespace:

{
  "Email": {
    "hello": "Hello, {name}",
    "emailVerification": {
      "title": "Verify your email",
      "heading": "Email Verification",
      "action": "Verify Email",
      "content": "Please click the button below to verify your email address."
    }
  }
}

Customizing Templates

Each template component receives name (user's name) and t (translation function) as props:

import type { EmailTemplateProps } from "@/lib/features/email/template";

export function EmailVerificationTemplate({ name, t }: EmailTemplateProps) {
  return (
    <>
      <p>{t("hello", { name })}</p>
      <p>{t("emailVerification.content")}</p>
    </>
  );
}

The template orchestration is handled in src/lib/features/email/template.ts, which uses @daveyplate/better-auth-ui/server for consistent email styling.

Custom Email Provider

To add a custom email provider:

  1. Create a new provider class in rc/lib/email/providers/ implementing the Provider interface
  2. Register in src/lib/email/factory.ts
  3. Add to the Features type in src/schemas/site-configuration.ts

Example:

import { Provider, SendEmailOptions, SendEmailResult } from "../provider";

export class CustomEmailProvider implements Provider {
  async sendEmail(options: SendEmailOptions): Promise<SendEmailResult> {
    // Implement email sending logic
    return { success: true };
  }
}

Register in factory:

case "custom":
  return new CustomEmailProvider();

Disable Email

To disable email functionality (e.g., for local development):

export const features: Features = {
  email: {
    provider: "disabled",
  },
};

When disabled, the system uses a no-op provider that logs emails to console instead of sending them.

References

Next Steps