Yasin

Yasin

SMTP 邮件服务使用指南

[我严格遵守规则]

SMTP 邮件服务使用指南

主流邮件服务对比

服务 免费额度 特点 推荐场景
Resend 100封/天 最简单,现代 API,开发体验最佳 个人/创业项目首选
Nodemailer + 163/QQ 免费 国内直接用,无需注册第三方 国内项目最方便
SendGrid 100封/天 老牌,功能全 企业级
AWS SES 62000封/月(EC2) 最便宜,大规模 高量级生产环境
Mailgun 100封/天 API 友好 中等规模

方案一:Resend(最推荐,最简单)

1. 注册获取 API Key

  • 访问 resend.com → 注册 → Dashboard → API Keys → 创建

2. 安装

pnpm add resend

3. 在项目中使用

// src/server/email.service.ts
import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendVerificationEmail(email: string, token: string) {
  const link = `${process.env.NEXT_PUBLIC_APP_URL}/verify?token=${token}`;

  await resend.emails.send({
    from: "AgentsChattingRoom <noreply@yourdomain.com>", // 需要验证域名
    to: email,
    subject: "请验证你的邮箱",
    html: `
      <h2>欢迎注册 AgentsChattingRoom</h2>
      <p>点击下方链接验证你的邮箱:</p>
      <a href="${link}">${link}</a>
      <p>链接 24 小时内有效。</p>
    `,
  });
}

export async function sendPasswordResetEmail(email: string, token: string) {
  const link = `${process.env.NEXT_PUBLIC_APP_URL}/reset?token=${token}`;

  await resend.emails.send({
    from: "AgentsChattingRoom <noreply@yourdomain.com>",
    to: email,
    subject: "重置密码",
    html: `
      <h2>密码重置</h2>
      <p>点击下方链接重置密码:</p>
      <a href="${link}">${link}</a>
      <p>链接 24 小时内有效。如非本人操作,请忽略。</p>
    `,
  });
}

4. 环境变量

RESEND_API_KEY=re_xxxxxxxxxxxx

注意:Resend 免费版只能发到自己邮箱,要发给任意用户需要验证你的域名(在 DNS 添加几条记录)。


方案二:Nodemailer + QQ/163 邮箱(国内零成本)

不需要注册任何第三方服务,用已有邮箱直接发。

1. 安装

pnpm add nodemailer
pnpm add -D @types/nodemailer

2. 获取授权码

  • QQ 邮箱:设置 → 账户 → POP3/SMTP 服务 → 开启 → 获取授权码
  • 163 邮箱:设置 → POP3/SMTP → 开启 → 设置授权码

3. 在项目中使用

// src/server/email.service.ts
import nodemailer from "nodemailer";

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST, // "smtp.qq.com" 或 "smtp.163.com"
  port: 465,
  secure: true, // 使用 SSL
  auth: {
    user: process.env.SMTP_USER, // "your@qq.com"
    pass: process.env.SMTP_PASS, // 授权码(不是邮箱密码)
  },
});

export async function sendVerificationEmail(email: string, token: string) {
  const link = `${process.env.NEXT_PUBLIC_APP_URL}/verify?token=${token}`;

  await transporter.sendMail({
    from: `"AgentsChattingRoom" <${process.env.SMTP_USER}>`,
    to: email,
    subject: "请验证你的邮箱",
    html: `
      <h2>欢迎注册</h2>
      <p>点击链接验证邮箱:<a href="${link}">${link}</a></p>
      <p>24 小时内有效。</p>
    `,
  });
}

export async function sendPasswordResetEmail(email: string, token: string) {
  const link = `${process.env.NEXT_PUBLIC_APP_URL}/reset?token=${token}`;

  await transporter.sendMail({
    from: `"AgentsChattingRoom" <${process.env.SMTP_USER}>`,
    to: email,
    subject: "重置密码",
    html: `
      <h2>密码重置</h2>
      <p>点击链接重置密码:<a href="${link}">${link}</a></p>
      <p>24 小时内有效。</p>
    `,
  });
}

4. 环境变量

# QQ 邮箱
SMTP_HOST=smtp.qq.com
SMTP_USER=your@qq.com
SMTP_PASS=xxxxxxxxxxxxxxxx   # QQ 邮箱授权码

# 或 163 邮箱
SMTP_HOST=smtp.163.com
SMTP_USER=your@163.com
SMTP_PASS=xxxxxxxxxxxxxxxx   # 163 授权码

方案三:SendGrid(企业级)

pnpm add @sendgrid/mail
import sgMail from "@sendgrid/mail";
sgMail.setApiKey(process.env.SENDGRID_API_KEY!);

await sgMail.send({
  from: "noreply@yourdomain.com", // 需要验证域名
  to: email,
  subject: "验证邮箱",
  html: "<p>...</p>",
});

SMTP 协议简述

SMTP(Simple Mail Transfer Protocol)本质就是一个发邮件的网络协议:

你的服务器 → SMTP 服务器 (smtp.qq.com:465) → 对方邮箱服务器 → 收件人

关键参数:

  • host: SMTP 服务器地址
  • port: 465(SSL)或 587(TLS)
  • auth: 用户名 + 授权码(不是密码)
  • from: 发件人(必须是 auth 中的邮箱)