如何在 Express.js 中发送电子邮件:SMTP 与 API 指南

发布: (2025年12月15日 GMT+8 15:52)
6 min read
原文: Dev.to

Source: Dev.to

前置条件

创建 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

使用 cURLPostmanhttp://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 certificateTLS 验证失败在 transporter 配置中设置 secure: false 并添加 tls: { rejectUnauthorized: false }(仅用于开发)。
550 5.1.1 (recipient not found)to 地址无效检查邮箱地址格式并确认域名存在。
401 Unauthorized from APIAPI 密钥错误或缺失确认 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)在稍后触发发送。

问:如何处理速率限制?
答:遵守邮件服务商文档中的限制。实现指数退避的重试逻辑,或在批量发送时进行分批请求。

Back to Blog

相关文章

阅读更多 »