Docs/modules/邮件

邮件

NextShip 使用 Resend 发送邮件,使用 React Email 构建邮件模板。

设置

环境变量

RESEND_API_KEY=re_xxx

Resend 客户端

// src/lib/email.ts
import { Resend } from "resend";
 
export const resend = new Resend(process.env.RESEND_API_KEY);

创建邮件模板

邮件模板是 emails/ 目录中的 React 组件:

// emails/welcome.tsx
import {
  Html,
  Head,
  Body,
  Container,
  Section,
  Text,
  Button,
  Hr,
} from "@react-email/components";
 
interface WelcomeEmailProps {
  name: string;
  loginUrl: string;
}
 
export function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
  return (
    <Html>
      <Head />
      <Body style={main}>
        <Container style={container}>
          <Section>
            <Text style={heading}>欢迎使用 NextShip!</Text>
            <Text style={paragraph}>
              你好 {name},感谢你的注册。我们很高兴有你的加入!
            </Text>
            <Button style={button} href={loginUrl}>
              进入控制台
            </Button>
            <Hr style={hr} />
            <Text style={footer}>
              © 2024 NextShip. 保留所有权利。
            </Text>
          </Section>
        </Container>
      </Body>
    </Html>
  );
}
 
const main = {
  backgroundColor: "#f6f9fc",
  fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
};
 
const container = {
  backgroundColor: "#ffffff",
  margin: "0 auto",
  padding: "40px 20px",
  borderRadius: "8px",
};
 
const heading = {
  fontSize: "24px",
  fontWeight: "bold",
  marginBottom: "20px",
};
 
const paragraph = {
  fontSize: "16px",
  lineHeight: "26px",
  marginBottom: "20px",
};
 
const button = {
  backgroundColor: "#000000",
  color: "#ffffff",
  padding: "12px 24px",
  borderRadius: "6px",
  textDecoration: "none",
};
 
const hr = {
  borderColor: "#e6ebf1",
  margin: "30px 0",
};
 
const footer = {
  color: "#8898aa",
  fontSize: "12px",
};

发送邮件

import { resend } from "@/lib/email";
import { WelcomeEmail } from "@/emails/welcome";
 
export async function sendWelcomeEmail(to: string, name: string) {
  await resend.emails.send({
    from: "NextShip <noreply@yourdomain.com>",
    to,
    subject: "欢迎使用 NextShip!",
    react: WelcomeEmail({
      name,
      loginUrl: `${process.env.NEXT_PUBLIC_APP_URL}/login`
    }),
  });
}

常用邮件模板

密码重置

export function PasswordResetEmail({ resetUrl }: { resetUrl: string }) {
  return (
    <Html>
      <Body style={main}>
        <Container style={container}>
          <Text style={heading}>重置密码</Text>
          <Text style={paragraph}>
            点击下方按钮重置密码。此链接将在 1 小时后过期。
          </Text>
          <Button style={button} href={resetUrl}>
            重置密码
          </Button>
        </Container>
      </Body>
    </Html>
  );
}

发票

export function InvoiceEmail({
  amount,
  invoiceUrl
}: {
  amount: string;
  invoiceUrl: string;
}) {
  return (
    <Html>
      <Body style={main}>
        <Container style={container}>
          <Text style={heading}>收到付款</Text>
          <Text style={paragraph}>
            感谢您支付 {amount}。
          </Text>
          <Button style={button} href={invoiceUrl}>
            查看发票
          </Button>
        </Container>
      </Body>
    </Html>
  );
}

预览邮件

React Email 提供预览服务器:

pnpm email:dev

http://localhost:3001 打开

域名验证

生产环境需要在 Resend 中验证域名:

  1. 进入 Resend 控制台 -> Domains
  2. 添加你的域名
  3. 将 DNS 记录添加到你的域名提供商
  4. 等待验证(通常几分钟)

最佳实践

  • 生产环境使用已验证的域名
  • 营销邮件包含退订链接
  • 在不同邮件客户端中测试邮件
  • 保持模板简洁且适配移动端