LogoLaunchSaaS

电子邮件

使用拆分包架构配置事务性邮件提供商

LaunchSaaS 通过拆分包设计提供邮件支持。核心包 @launchsaas/email 定义接口和 Email 服务;每个提供商是独立的包,按需安装。

更新时间:2026-03-15

架构

@launchsaas/email              ← 接口 + Email 类(始终需要)
@launchsaas/email-resend       ← Resend(推荐,支持 Serverless)
@launchsaas/email-nodemailer   ← Nodemailer(SMTP,仅 Node.js)

你只需添加实际使用的提供商包,避免引入不需要的 SDK。

LaunchSaaS 默认使用 @launchsaas/email-resend。在你自己的应用中,可以安装任意偏好的提供商 — Resend、Nodemailer 或自定义包。

设置邮件功能

1. 安装提供商包

在你的应用目录中选择一个提供商:

# Resend(推荐 — 支持 Serverless 和 Edge)
pnpm add @launchsaas/email-resend

# Nodemailer / SMTP(仅限 Node.js 运行时)
pnpm add @launchsaas/email-nodemailer

2. 添加环境变量

将提供商的 keys 导出添加到应用的 env.ts,以便在启动时验证环境变量:

// src/env.ts
import { keys as emailKeys } from "@launchsaas/email-resend";

export const env = createEnv({
  extends: [
    // ... 其他 keys
    emailKeys,
  ],
  // ...
});

然后在 .env 中设置变量:

# Resend
RESEND_API_KEY="re_..."
RESEND_FROM_EMAIL="[email protected]"

# — 或者 — Nodemailer (SMTP)
SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USER="[email protected]"
SMTP_PASS="your-password"
SMTP_FROM_EMAIL="[email protected]"
SMTP_SECURE="false"

3. 在 instrumentation.ts 中初始化

打开 src/instrumentation.ts,取消注释你选择的提供商对应的代码块:

// src/instrumentation.ts
export async function register() {
  // 选项 A — Resend(推荐)
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { Email } = await import("@launchsaas/email");
    const { ResendEmailProvider } = await import("@launchsaas/email-resend");
    Email.init(ResendEmailProvider.create());
  }

  // 选项 B — Nodemailer (SMTP)
  // if (process.env.NEXT_RUNTIME === "nodejs") {
  //   const { Email } = await import("@launchsaas/email");
  //   const { NodemailerEmailProvider } = await import("@launchsaas/email-nodemailer");
  //   Email.init(NodemailerEmailProvider.create());
  // }
}

register() 内的动态 import() 确保提供商 SDK 只在 Node.js 服务端运行时加载,并能受益于 Tree-shaking。

4. 验证是否正常工作

启动开发服务器,触发一封邮件(例如注册获得验证邮件)。检查 Resend Dashboard 或 SMTP 日志。

Resend:域名验证(生产环境)

要从自己的域名发送邮件而非 Resend 测试地址:

  1. 前往 Resend Dashboard 的 Domains
  2. 点击 Add Domain 并输入你的域名(例如 yourdomain.com
  3. 将 Resend 提供的 DNS 记录(MX、TXT/SPF、DKIM)添加到你的 DNS 提供商
  4. 等待 DNS 传播(最多 48 小时),然后点击 Verify
  5. 更新环境变量:RESEND_FROM_EMAIL="[email protected]"

电子邮件模板

LaunchSaaS 在 src/components/email/ 中提供了示例模板,你可以将其复制到自己的应用中并自定义:

模板发送时机
email-verification.tsx用户注册时
reset-password.tsx密码重置流程
magic-link.tsx无密码登录
payment-completed.tsx支付确认
welcome.tsx验证完成后的欢迎邮件

i18n 支持

模板自动使用用户保存的语言(按以下顺序回退:请求语言 → 默认 en)。翻译定义在 messages/[locale].jsonEmail 命名空间下:

{
  "Email": {
    "hello": "你好,{name}",
    "emailVerification": {
      "title": "验证你的邮箱",
      "heading": "邮箱验证",
      "action": "验证邮箱",
      "content": "请点击下面的按钮验证你的电子邮件地址。"
    }
  }
}

自定义模板

每个模板接收 namet(翻译函数)作为 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>
    </>
  );
}

自定义邮件提供商

要集成 LaunchSaaS 未内置的提供商,可创建新的 email-xxx 包:

1. 创建包

mkdir -p packages/email-myservice/src

packages/email-myservice/package.json

{
  "name": "@launchsaas/email-myservice",
  "version": "0.1.0",
  "private": true,
  "main": "./src/index.ts",
  "exports": {
    ".": "./src/index.ts"
  },
  "dependencies": {
    "@launchsaas/email": "workspace:*",
    "@launchsaas/errors": "workspace:*",
    "@t3-oss/env-nextjs": "^0.13.10",
    "my-email-sdk": "^1.0.0",
    "zod": "^4.0.0"
  }
}

packages/email-myservice/src/keys.ts

import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const keys = createEnv({
  server: {
    MYSERVICE_API_KEY: z.string().optional(),
    MYSERVICE_FROM_EMAIL: z.string().optional(),
  },
  experimental__runtimeEnv: {},
});

packages/email-myservice/src/provider.ts

import type { EmailProvider, SendEmailOptions } from "@launchsaas/email";

export class MyServiceEmailProvider implements EmailProvider {
  readonly name = "myservice";

  static create(): MyServiceEmailProvider {
    return new MyServiceEmailProvider();
  }

  async send(options: SendEmailOptions): Promise<void> {
    // 在这里调用 my-email-sdk
  }
}

packages/email-myservice/src/index.ts

export { MyServiceEmailProvider } from "./provider";
export { keys } from "./keys";

2. 在应用中接入

pnpm add @launchsaas/email-myservice

keys 添加到 env.ts,并在 instrumentation.ts 中初始化:

// instrumentation.ts
export async function register() {
  const { Email } = await import("@launchsaas/email");
  const { MyServiceEmailProvider } =
    await import("@launchsaas/email-myservice");
  Email.init(MyServiceEmailProvider.create());
}

禁用邮件功能

若要完全禁用邮件功能,只需在 instrumentation.ts 中不调用 Email.init()Email.enabled() 将返回 false,依赖邮件的功能(Magic Link、邮箱验证)会自动跳过。

如果禁用了邮件功能,建议同时在 features 配置中设置 magicLink: false,避免用户看到一个静默失败的登录选项。

提供商对比

提供商包名运行时免费额度
Resend@launchsaas/email-resend任意(HTTP)100 封/天
Nodemailer@launchsaas/email-nodemailer仅 Node.js取决于 SMTP 服务商
自定义@launchsaas/email-xxx自定义

参考资料