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

ReactJS结合Nodemailer无法发送邮件,求问题排查与解决

问题描述

我正尝试使用ReactJS和Nodemailer实现邮件发送功能。运行代码后,控制台显示“failure”提示,同时出现500错误。我看到有资料提示需开启Google账户的“不太安全的应用”功能,但我的账户无该选项。

客户端代码(App.js)

import "./App.css";
import { useState } from "react";
import axios from "axios";

function App() {
  const [email, setEmail] = useState();
  const [subject, setSubject] = useState();
  const [message, setMessage] = useState();

  const sendMail = () => {
    axios
      .get("http://localhost:4000", {
        params: {
          email,
          subject,
          message,
        },
      })
      .then(() => {
        console.log("success");
      })
      .catch(() => {
        console.log("failure");
      });
  };

  return (
    <div>
      <input
        type="text"
        onChange={(e) => setEmail(e.target.value)}
      />
      // 2 more inputs for subject and message
      <button onClick={sendMail}>Submit</button>
    </div>
  );
}
export default App;

服务端代码(app.js)

const express = require("express");
const nodemailer = require("nodemailer");
const cors = require("cors");
const app = express();
const port = 4000;

app.use(cors());
app.use(express.json({ limit: "25mb" }));
app.use(express.urlencoded({ limit: "25mb" }));
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  next();
});

function sendEmail({ email, subject, message }) {
  return new Promise((resolve, reject) => {
    var transporter = nodemailer.createTransport({
      service: "gmail",
      auth: {
        user: "myemail@gmail.com",
        pass: "google app password",
      },
    });

    const mail_configs = {
      from: "example@gmail.com",
      to: email,
      subject: subject,
      text: message,
    };

    transporter.sendMail(mail_configs, function (error, info) {
      if (error) {
        console.log(error);
        return reject({ message: `An error occurred.` });
      }

      return resolve({ message: "Email sent successfully" });
    });
  });
}

app.get("/", (req, res) => {
  sendEmail(req.query)
    .then((response) => response.send(response.message))
    .catch((error) => res.status(500).send(error.message));
});

app.listen(port, () => {
  console.log(`nodemailer is listening at http://localhost:${port}`);
});
错误分析与解决办法

1. 服务端路由响应逻辑错误(直接触发500错误)

服务端app.get("/")回调里,then((response) => response.send(response.message))写法错误:这里的response是Promise返回的普通对象,没有send方法,必须用Express的res对象发送响应。

修改后的服务端路由代码:

app.get("/", (req, res) => {
  sendEmail(req.query)
    .then((response) => res.send(response.message)) // 替换response.send为res.send
    .catch((error) => res.status(500).send(error.message));
});

2. Gmail认证配置问题

谷歌已移除“不太安全的应用”选项,现在必须通过App Password完成认证,前提是你的谷歌账户已开启两步验证(2FA):

  • 登录谷歌账户,开启两步验证;
  • 进入账户“安全”设置,找到“App Passwords”选项;
  • 生成一个专属的App Password,替换代码中的"google app password";
  • 注意:transporter.auth.user必须与你的谷歌邮箱一致,mail_configs.from建议设置为该邮箱(或已验证的别名)。

3. 客户端状态初始化优化

客户端useState未初始化值,可能导致请求参数为undefined,建议初始化为空字符串:

const [email, setEmail] = useState("");
const [subject, setSubject] = useState("");
const [message, setMessage] = useState("");

4. 改用POST请求(推荐优化)

GET请求存在URL长度限制、敏感信息暴露的风险,建议改用POST请求:

客户端修改:

const sendMail = () => {
  axios
    .post("http://localhost:4000/send-email", {
      email,
      subject,
      message,
    })
    .then(() => {
      console.log("success");
    })
    .catch((err) => {
      console.log("failure", err);
    });
};

服务端修改:

// 添加POST路由
app.post("/send-email", (req, res) => {
  sendEmail(req.body) // 从req.body获取请求参数
    .then((response) => res.send(response.message))
    .catch((error) => res.status(500).send(error.message));
});

额外调试建议

在服务端sendEmail函数中打印完整错误信息,便于精准定位问题:

if (error) {
  console.log("完整错误信息:", error); // 打印详细错误
  return reject({ message: `An error occurred: ${error.message}` });
}

内容的提问来源于stack exchange,提问作者John Beasley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:30:07