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

Nodemailer发件报错No recipients defined及收件地址无效问题求助

问题原因
  1. 初始版本No recipients defined报错原因:
    你封装的getAdminEmail函数采用回调式写法,没有对外层返回任何值,同时你没有处理异步逻辑,调用时直接同步取值拿到的是undefined,导致管理员邮件的收件人为空。
  2. 修改后RFC-5321规范报错原因:
  • SuperAdminListModel.find({})返回的是符合条件的文档数组,你没有取数组的第一个元素,直接把整个数组当邮箱地址传入,类型不匹配。
  • 你拿到的管理员邮箱字符串前后被意外添加了单引号,RFC 5321标准规定纯邮箱地址不允许包裹多余的引号符号,因此被 Gmail 接口拒绝。
  • 隐藏问题:你在dispatch_emails函数内两次调用res.send(),同一个HTTP请求只能返回一次响应,后续会触发请求已发送的报错。
  • 配置错误:你写的secureConnection: 'false'是无效配置,Nodemailer对应配置字段为secure,且接受布尔值而非字符串。
修复方案
  1. 修正管理员邮箱获取逻辑:
// 把RegisterAdminUser内获取邮箱的代码替换为如下
const superAdminRes = await SuperAdminListModel.findOne({});
if (!superAdminRes?.superadmin_email) {
  return res.status(500).json({ error: '系统未配置管理员邮箱' });
}
// 清除邮箱前后多余的引号和空白字符
const adminEmail = superAdminRes.superadmin_email.replace(/['"\s]+/g, '');
  1. 重写dispatch_emails函数,修复配置错误和重复返回的问题:
const dispatch_emails = async (admin_email, user_email, fullname, company_name) =>{
  const transporter = nodemailer.createTransport({
    service: 'gmail',
    host: 'smtp.gmail.com',
    port: 587,
    auth: {
        user: '你的发件Gmail地址',
        pass: '你的Gmail应用密码'
    },
    secure: false,
    tls: {
        rejectUnauthorized: false
    }
  });

  const userMailOptions = {
    from: '你的发件Gmail地址',
    to: user_email,
    subject: 'Account Registration Successful!',
    html: `<h3>Attention,${fullname}</h3>
    <p><h3>Your Account has been successfully setup.</h3></p>
    <p>Please allow a maximum of 24 - 48 Hours for Review and succesful setup and approval of your online account.</p>
    </br>Regards,</br> Online Services.`
  };

  const adminMailOptions = {
    from: '你的发件Gmail地址',
    to: admin_email,
    subject: `Account Registration for ${user_email}, Fullname : ${fullname} (${company_name})`,
    html: `<h3>Attention Admin</h3>
    <p>A new User has registered with the following Information: </br>
    <strong>Username : ${user_email}</strong></br>
    <strong>Company Name : ${company_name}</strong></br>
    <strong>Registration Date: ${(new Date()).toLocaleString()}</strong></br>
    Regards</br>Online Services.</p>`
  };
  // 并行发送两封邮件统一返回结果
  return Promise.all([
    transporter.sendMail(userMailOptions),
    transporter.sendMail(adminMailOptions)
  ])
}
  1. 修正注册逻辑中的响应返回位置,添加邮件发送错误处理:
// 把bcrypt.hash的回调替换为如下
bcrypt.hash(req.body.password, salt, async (err, hash) => {
  if (err) {
    return res.status(500).json({ error: err });
  }
  newUser.password = hash;
  await newUser.save();
  try {
    // 传入清理后的管理员邮箱
    await dispatch_emails(adminEmail, newUser.email, newUser.fullname, newUser.company_name);
    const payload = {
        _id: newUser._id,
        email: req.body.email,
    };
    const token = jwt.sign(payload, services.JWT_KEY, {
        expiresIn: 31556926,
    });
    return res.status(200).json({
        message: "User registered Successfully",
        token: token,
        user: newUser,
    });
  } catch (mailError) {
    console.error('邮件发送失败:', mailError);
    // 可根据业务调整,也可返回注册成功提示邮件发送异常
    return res.status(500).json({ error: '邮件发送失败' });
  }
})
// 删掉原来bcrypt.genSalt回调外层的res.return,避免提前返回

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:09:03