电子邮件
使用拆分包架构配置事务性邮件提供商
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-nodemailer2. 添加环境变量
将提供商的 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 测试地址:
- 前往 Resend Dashboard 的 Domains
- 点击 Add Domain 并输入你的域名(例如
yourdomain.com) - 将 Resend 提供的 DNS 记录(MX、TXT/SPF、DKIM)添加到你的 DNS 提供商
- 等待 DNS 传播(最多 48 小时),然后点击 Verify
- 更新环境变量:
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].json 的 Email 命名空间下:
{
"Email": {
"hello": "你好,{name}",
"emailVerification": {
"title": "验证你的邮箱",
"heading": "邮箱验证",
"action": "验证邮箱",
"content": "请点击下面的按钮验证你的电子邮件地址。"
}
}
}自定义模板
每个模板接收 name 和 t(翻译函数)作为 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/srcpackages/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 | 自定义 | — |