如何在 Express.js 中发送电子邮件:SMTP 与 API 指南
Source: Dev.to
前置条件
- 机器上已安装 Node.js。 在此下载最新版本。
- 代码编辑器(例如 Visual Studio Code)。
- 基础的 JavaScript 知识。
- 一个 SendLayer 账户。你可以开始免费试用,免费发送最多 200 封邮件。 在 SendLayer 开始免费试用。
创建 SendLayer 账户后,授权你的发送域名以提升邮件送达率。
搭建 Express.js 服务器
# 创建项目文件夹
mkdir send-email
cd send-email
# 初始化 npm 项目
npm init -y
# 安装依赖
npm install express dotenv
在项目根目录创建 server.js:
// server.js
const express = require('express');
const dotenv = require('dotenv');
dotenv.config(); // 加载环境变量
const app = express();
const port = process.env.PORT || 3000;
// 中间件:解析 JSON 数据
app.use(express.json());
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
运行服务器:
node server.js
你应该会看到:
Server running on port 3000
现在可以通过 http://localhost:3000 访问服务器。
通过 SMTP 发送邮件
安装 Nodemailer
npm install nodemailer
配置环境变量
创建 .env 文件并添加你的 SMTP 凭证(示例使用 SendLayer):
SMTP_HOST=smtp.sendlayer.net
SMTP_PORT=587
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
FROM_EMAIL=sender@example.com
注意: 对于 SendLayer,发件人邮箱必须属于已授权的域(例如
@example.com)。
在 server.js 中加入邮件逻辑
// server.js (continued)
const nodemailer = require('nodemailer');
// 通过 SMTP 发送邮件的函数
const sendEmail = async (to, subject, message) => {
try {
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: false, // TLS (587) 为 false,SSL (465) 为 true
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
const mailOptions = {
from: process.env.FROM_EMAIL,
to,
subject,
text: message,
};
const info = await transporter.sendMail(mailOptions);
console.log('Email sent:', info.messageId);
} catch (error) {
console.error('Error sending email:', error);
throw error;
}
};
// POST 路由,用于触发邮件发送
app.post('/send-email', async (req, res) => {
const { to, subject, message } = req.body;
if (!to || !subject || !message) {
return res.status(400).json({ status: 'error', message: 'Missing required fields' });
}
try {
await sendEmail(to, subject, message);
res.status(200).json({ status: 'success', message: 'Email sent successfully' });
} catch (err) {
res.status(500).json({ status: 'error', message: 'Failed to send email' });
}
});
发送附件(可选)
在 mailOptions 中添加 attachments 数组:
const mailOptions = {
from: process.env.FROM_EMAIL,
to,
subject,
text: message,
attachments: [
{
filename: 'example.pdf',
path: './path/to/example.pdf', // 请更新为正确的路径
},
],
};
测试接口
启动服务器:
node server.js
使用 cURL 或 Postman 向 http://localhost:3000/send-email 发送 POST 请求,JSON 请求体如下:
{
"to": "recipient@example.com",
"subject": "Test Email",
"message": "Hello from Express.js!"
}
成功响应示例:
{
"status": "success",
"message": "Email sent successfully"
}
检查收件箱以确认邮件已送达。
若要发送给多个收件人,只需在 to 字段中用逗号分隔邮箱地址。
通过 API 发送邮件
本节介绍使用邮件服务的 HTTP API(例如 SendLayer)而非 SMTP。该方式在批量发送时提供更好的送达率和可扩展性。
安装 Axios(或任意 HTTP 客户端)
npm install axios
将 API 凭证写入 .env
SENDLAYER_API_KEY=your-api-key
实现基于 API 的发送
// server.js (continued)
const axios = require('axios');
const sendEmailViaAPI = async (to, subject, message) => {
try {
const response = await axios.post(
'https://api.sendlayer.com/v1/email',
{
from: process.env.FROM_EMAIL,
to,
subject,
text: message,
},
{
headers: {
Authorization: `Bearer ${process.env.SENDLAYER_API_KEY}`,
'Content-Type': 'application/json',
},
}
);
console.log('API email sent:', response.data);
return response.data;
} catch (error) {
console.error('API error:', error.response?.data || error.message);
throw error;
}
};
// 使用 API 方法的示例路由
app.post('/send-email-api', async (req, res) => {
const { to, subject, message } = req.body;
if (!to || !subject || !message) {
return res.status(400).json({ status: 'error', message: 'Missing required fields' });
}
try {
await sendEmailViaAPI(to, subject, message);
res.status(200).json({ status: 'success', message: 'Email sent via API' });
} catch (err) {
res.status(500).json({ status: 'error', message: 'Failed to send email via API' });
}
});
使用 API 方法无需管理 SMTP 连接,并且通常提供模板、追踪、限流等更丰富的功能。
常见错误排查
| 症状 | 可能原因 | 解决方案 |
|---|---|---|
Error: self signed certificate | TLS 验证失败 | 在 transporter 配置中设置 secure: false 并添加 tls: { rejectUnauthorized: false }(仅用于开发)。 |
550 5.1.1 (recipient not found) | to 地址无效 | 检查邮箱地址格式并确认域名存在。 |
401 Unauthorized from API | API 密钥错误或缺失 | 确认 SENDLAYER_API_KEY 正确且已在 Authorization 头中传递。 |
| 未收到邮件 | 邮件被归入垃圾箱 | 检查域名的 SPF/DKIM 记录并使用已验证的发件人地址。 |
服务器在 sendMail 时崩溃 | 未捕获的 Promise 拒绝 | 在调用 sendEmail 时使用 try/catch 并返回合适的 HTTP 状态码。 |
常见问答
问:应该使用 SMTP 还是邮件 API?
答:对于简单或低频使用,Nodemailer + SMTP 完全可行。若发送量大、需要更好的送达率以及高级功能(模板、分析),推荐使用邮件 API。
问:如何发送 HTML 邮件?
答:在 mailOptions(SMTP)中添加 html 属性,或在 API 请求体中加入 html 字段。
const mailOptions = {
from: process.env.FROM_EMAIL,
to,
subject,
html: '
## Hello
This is an HTML email.
',
};
问:可以安排邮件发送时间吗?
答:Nodemailer 和大多数邮件 API 本身不提供调度功能。可以使用 node-cron 等任务调度器或任务队列(如 Bull)在稍后触发发送。
问:如何处理速率限制?
答:遵守邮件服务商文档中的限制。实现指数退避的重试逻辑,或在批量发送时进行分批请求。