You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Node.js结合Nodemailer与Google Cloud Functions发信问题求助

排查Nodemailer + Firebase Cloud Functions邮件发送问题

看起来你在从SendGrid转用Nodemailer + Firebase Cloud Functions时遇到了功能异常,我帮你梳理下两段代码里的关键问题,以及对应的修正方案:

第一段代码的核心问题

  • 跨域(CORS)未处理:React前端调用云函数时会触发跨域请求,这段代码没有配置CORS,直接访问会被浏览器拦截。
  • 响应未正确结束:transporter.sendMail是异步操作,但函数最后没有通过res.send/res.status结束响应,导致Cloud Functions可能超时,前端得不到任何反馈。
  • Gmail认证限制:现在Gmail默认禁止使用普通密码登录SMTP服务,你需要开启App Password(前提是账号开启了两步验证),或者改用OAuth2认证方案,否则会出现认证失败。
  • 未使用请求参数:代码里解构了name和dest,但邮件内容和收件人没用到这些变量,这会导致功能不符合预期。

第二段代码的核心问题

  • CORS依赖缺失:代码里调用了cors(req, res, () => {}),但没有导入cors包(比如const cors = require('cors')),会直接报错cors is not defined。
  • HTML内容字段错误:你把HTML内容放在了text字段里,这个字段是用于纯文本内容的,HTML内容应该放在html字段,否则邮件会显示原始标签而不是渲染后的效果。
  • 同样的Gmail认证问题:和第一段代码一样,普通密码无法通过Gmail SMTP认证。

修正后的完整代码示例

先确保你的Cloud Functions目录下安装了必要依赖:

npm install nodemailer cors

然后修改代码如下:

const functions = require("firebase-functions");
const nodemailer = require("nodemailer");
const cors = require("cors")({ origin: true }); // 允许所有跨域请求,生产环境建议限制特定域名

exports.sendMail = functions.https.onRequest((req, res) => {
  // 处理CORS
  cors(req, res, async () => {
    try {
      // 从请求参数中获取数据(推荐用req.body,POST请求更安全)
      const { name, dest } = req.body || req.query;

      // 配置Nodemailer transporter,使用Gmail App Password
      const transporter = nodemailer.createTransport({
        service: "Gmail",
        port: 465,
        secure: true,
        auth: {
          user: "your-gmail-address@gmail.com",
          pass: "your-app-password-here" // 注意:这里是App Password,不是普通密码
        }
      });

      // 邮件配置,动态使用传入的参数
      const mailOptions = {
        from: "Sunny <your-gmail-address@gmail.com>",
        to: dest || "default-recipient@example.com", // 备用收件人防止参数缺失
        subject: `Nytt Avtal från ${name}`,
        html: `<p>Hej! Ni har fått ett nytt avtal från ${name}. Logga in på Sunny för att se kunddetaljer.</p>`
      };

      // 发送邮件(用async/await替代回调,代码更易读)
      const info = await transporter.sendMail(mailOptions);
      functions.logger.info("邮件发送成功:", info);
      return res.status(200).send({ success: true, message: "邮件已发送" });
    } catch (error) {
      functions.logger.error("邮件发送失败:", error);
      return res.status(500).send({ success: false, error: error.toString() });
    }
  });
});

关键注意事项

  1. Gmail认证设置:
    • 先开启账号的两步验证(2FA),然后在Google账号设置里生成App Password(仅用于SMTP登录)。
    • 如果不想开2FA,需要在Google账号的"安全性"里开启"不太安全的应用访问"(不推荐生产环境使用)。
  2. 请求方式:建议前端用POST请求发送表单数据(放在req.body里),而不是GET的query参数,更安全且能传递更多数据。
  3. 日志排查:如果还是有问题,去Firebase Console的"函数"->"日志"里查看具体错误信息,比如认证失败、参数缺失等,这是排查云函数问题的关键。
  4. 生产环境优化:
    • 限制CORS的origin为你的React应用域名,比如cors({ origin: "https://your-react-app.com" })。
    • 用环境变量存储邮箱账号和密码,不要硬编码在代码里(Firebase Functions可以通过firebase functions:config:set设置环境变量)。

内容的提问来源于stack exchange,提问作者Oblicion A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:22:32