JavaScript 从服务器发送邮件,而非直接从浏览器发送。客户端代码无法打开 SMTP 连接,而将邮件凭据放在页面中等于把它们交给任何打开开发者工具的人。因此真正的问题是选择哪种服务器端方式:通过 Nodemailer 这样的库使用 SMTP,还是向邮件 API 发送 HTTP 请求。本文展示两种方式。
为什么浏览器不能发送邮件?
邮件投递通过 SMTP(一种 TCP 协议)进行。浏览器不向 JavaScript 暴露原始 TCP 套接字,因此客户端无法与邮件服务器通信。即使可以,SMTP 凭据或 API 密钥也会暴露在任何人都能读取的代码中。浏览器收集表单输入并提交到后端,由后端发送邮件。这种分离就是整个模式。
如何在 Node 后端使用 SMTP 发送邮件?
Nodemailer 是 Node 中用于 SMTP 的标准库。你只需配置一次 transport,然后调用 sendMail:
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: "smtp.example.com",
port: 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
await transporter.sendMail({
from: "you@yourdomain.com",
to: "recipient@example.org",
subject: "Your receipt",
text: "Thanks for your order.",
html: "<p>Thanks for your order.</p>",
});
这在长期运行的服务器上效果很好。完整演练(包括附件和本地测试)请参阅使用 Nodemailer 发送邮件。
如何通过 HTTP 邮件 API 发送?
另一种方式是发送 HTTP 请求。你的后端使用 fetch 调用邮件 API,这样无需运行邮件服务器,而且无论你是在传统主机还是 serverless 函数上,行为都相同:
const res = await fetch("https://api.bird.com/v1/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BIRD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "you@yourdomain.com",
to: "delivered@bird.dev",
subject: "Hello from JavaScript",
html: "<p>It works.</p>",
}),
});
if (!res.ok) {
throw new Error(`Send failed: ${res.status}`);
}
密钥始终保存在服务器上的环境变量中,绝不发送到客户端。
使用 Bird 发送
Bird Node SDK 封装了同样的 HTTP 调用,让你跳过手动 fetch,直接获得类型化的结果:
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.email
.send({
from: "you@yourdomain.com",
to: ["delivered@bird.dev"],
subject: "Hello from Node",
html: "<p>It works.</p>",
})
.safe();
delivered@bird.dev 沙箱地址始终接受邮件,因此第一次运行即可确认你的配置。如果你用 React 组件构建邮件正文,可以搭配 React Email,它会将组件渲染为你在 html 中传入的 HTML。
常见问题
客户端 JavaScript 能发送邮件吗?
不能。浏览器无法打开 SMTP 连接,客户端代码中的任何凭据都会暴露。浏览器将表单数据发送到后端,由后端发送邮件。
应该使用 Nodemailer 还是 HTTP API?
如果你在长期运行的服务器上并且可以控制 SMTP,Nodemailer 是不错的选择。当你希望避免运维邮件服务器时,HTTP API 更简单,而且在 SMTP 套接字不可用的 serverless 平台上,它是更可靠的选择。
API 密钥应该存放在哪里?
存放在服务器端的环境变量中,在运行时读取。它绝不能出现在前端代码或公开仓库中。
JavaScript 本身不能投递邮件,需要服务器来完成。如需深入了解 API 方式,邮件产品概览和邮件发送指南涵盖了各个环节。