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

NodeJS后端Nodemailer对接Gmail遇认证错误,求.env配置方法

NodeJS中Nodemailer对接Gmail的环境变量配置问题

我在NodeJS后端应用里用Nodemailer对接Gmail时碰到了问题,试过OAuth和双因素认证两种方式,分别出现以下错误:

  • 要么是 Error Error: Mail command failed: 530-5.7.0 Authentication Required.
  • 要么是 Nodemailer Error: Missing credentials for "PLAIN"

OAuth方式配置(触发"Authentication Required"错误)

import nodemailer from "nodemailer";

interface mailOptions {
  from: string;
  to: string;
  subject: string;
  html: string;
}

const transporter = nodemailer.createTransport({
  host: "smtp.gmail.com",
  service: "gmail",
  port: "587",
  secure: false,
  auth: {
    type: "OAuth2",
    user: 'EMAIL',
    pass: 'EMAIL PASSWORD',
    clientId: 'CLIENTID',
    clientSecret: 'CLIENT SECRET',
    refreshToken: 'OAUTH REFRESH TOKEN',
  },
});

transporter.verify((err, success) => {
  err
    ? console.log(err)
    : console.log(`=== Server is ready to take messages: ${success} ===`);
});

export const sendMail = (mailOptions: mailOptions) =>
  transporter.sendMail(mailOptions, function (err, data) {
    if (err) {
      console.log("Error " + err);
    } else {
      console.log("Email sent successfully");
    }
  });

双因素认证方式配置(触发"Missing credentials for 'PLAIN'"错误)

import nodemailer from "nodemailer";

interface mailOptions {
  from: string;
  to: string;
  subject: string;
  html: string;
}

const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: 'EMAIL',
    pass: '2 FACTOR GENERATED PASSWORD FOR THE APP',
  },
});

transporter.verify((err, success) => {
  err
    ? console.log(err)
    : console.log(`=== Server is ready to take messages: ${success} ===`);
});

export const sendMail = (mailOptions: mailOptions) =>
  transporter.sendMail(mailOptions, function (err, data) {
    if (err) {
      console.log("Error " + err);
    } else {
      console.log("Email sent successfully");
    }
  });

控制器代码

ForgotPassword: async (req: Request, res: Response) => {
  try {
    const user = await userSchema.findOne({ email: req.body.email });
    const username = user?.username;

    if (user) {
      const secret = process.env.ACCESS_TOKEN + user.password;
      const payload = {
        email: user.email,
        id: user._id,
      };
      const token = jwt.sign(payload, secret, { expiresIn: "15m" });
      const link = `http://localhost:${process.env.PORT}/user/reset-password/${user._id}/${token}`;

      // console.log(link, token);

      // Add in logic for sending the link via email to user here

      const mailOptions = {
        from: 'EMAIL',
        to: 'EMAIL',
        subject: "Password Reset",
        html: "HTML",
      };

      sendMail(mailOptions);

      res.status(200).send("Password reset link has been sent to your email");
    } else {
      res.status(404).send("User not found!");
    }
  } catch (e: unknown) {}
},

补充说明

问题似乎出在环境变量加载上,我把邮箱和双因素认证生成的应用密码直接写进代码里就能正常运行,请问该怎么配置环境变量解决这个问题?


环境变量配置解决方案

1. 安装并配置dotenv

先在项目中安装dotenv包:

npm install dotenv

在项目根目录创建.env文件,填入你的敏感信息(替换为实际值):

# 双因素认证专用
GMAIL_USER=你的Gmail邮箱地址
GMAIL_APP_PASSWORD=双因素认证生成的应用密码

# OAuth专用(若使用OAuth认证)
GMAIL_CLIENT_ID=你的OAuth客户端ID
GMAIL_CLIENT_SECRET=你的OAuth客户端密钥
GMAIL_REFRESH_TOKEN=你的OAuth刷新令牌

2. 在代码中加载环境变量

在Nodemailer配置文件的最顶部添加以下代码,确保环境变量被加载:

import dotenv from 'dotenv';
dotenv.config();

3. 修改Nodemailer配置代码

双因素认证方式修改后:
const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: process.env.GMAIL_USER,
    pass: process.env.GMAIL_APP_PASSWORD,
  },
});
OAuth方式修改后(注意移除多余的pass字段):
const transporter = nodemailer.createTransport({
  host: "smtp.gmail.com",
  service: "gmail",
  port: 587, // 改为数字类型,避免字符串解析问题
  secure: false,
  auth: {
    type: "OAuth2",
    user: process.env.GMAIL_USER,
    clientId: process.env.GMAIL_CLIENT_ID,
    clientSecret: process.env.GMAIL_CLIENT_SECRET,
    refreshToken: process.env.GMAIL_REFRESH_TOKEN,
  },
});

4. 修改控制器中的mailOptions

把硬编码的邮箱替换为环境变量,同时动态设置收件人:

const mailOptions = {
  from: process.env.GMAIL_USER,
  to: user.email, // 动态获取用户邮箱,而非硬编码
  subject: "Password Reset",
  html: `<p>点击链接重置密码:<a href="${link}">${link}</a></p>`,
};

5. 关键注意事项

  • 务必将.env文件添加到.gitignore中,防止敏感信息泄露到代码仓库
  • 环境变量名称要和代码中process.env.xxx的名称完全一致,大小写敏感
  • OAuth认证方式不需要填写pass字段,这是导致"Authentication Required"错误的常见原因
  • 端口号建议使用数字类型(如587),而非字符串,避免配置解析异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:01:04