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

如何使用SendGrid发送认证邮件?代码运行返回Forbidden错误如何解决?

这是我遇到的错误截图

问题核心原因与解决方案

SendGrid返回403 Forbidden属于权限/配置类错误,按以下优先级排查即可解决:

  • API密钥配置错误
    首先确认process.env.MAIL_KEY是否正确读取到了SendGrid后台生成的完整权限API密钥,注意密钥生成后只会显示一次,丢失后需要重新生成,且密钥必须开通Mail Send权限,权限受限的密钥会直接返回403。
  • 发件人身份未验证
    SendGrid要求发件人邮箱(即你代码中process.env.EMAIL_FROM对应的地址)必须先在SendGrid后台完成单 sender 验证,或者完成整个发件域名的验证,未验证的发件人发信会直接被拦截返回403。
  • 账户状态异常
    检查你的SendGrid账户状态,新账户未完成身份验证、发信额度用完、被平台判定违规冻结发信权限,都会触发403错误。
  • 环境变量加载异常
    临时增加一行打印代码console.log(process.env.MAIL_KEY, process.env.EMAIL_FROM),确认运行环境的环境变量被正确读取,避免配置项为空或者读取错误。

你代码存在的额外逻辑问题

你当前的User.findOne是异步查询,查询回调还没返回时,下方的发信逻辑就已经执行,哪怕用户邮箱已经被注册,邮件还是会被发送,需要调整逻辑把发信流程放到查询回调内部,确认无重复用户后再执行发信,调整后的参考代码如下:

const sgMail = require('@sendgrid/mail')
sgMail.setApiKey(process.env.MAIL_KEY)

const { name, email, password } = req.body;
console.log(name, email, password)
const errors = validationResult(req);

if (!errors.isEmpty()) {
  const firstError = errors.array().map(error => error.msg)[0];
  return res.status(422).json({
    errors: firstError
  });
} 

User.findOne({
  email
}).exec(async (err, user) => {
  if (err) {
    return res.status(500).json({errors: '用户查询失败'})
  }
  if (user) {
    return res.status(400).json({
      errors: 'Email is taken'
    });
  }
  // 确认无重复用户后再执行发信逻辑
  const token = jwt.sign(
    {
      name,
      email,
      password
    },
    process.env.JWT_ACCOUNT_ACTIVATION,
    {
      expiresIn: '5m'
    }
  );

  const emailData = {
    from: process.env.EMAIL_FROM,
    to: email,
    subject: 'Account activation link',
    html: `
              <h1>Please use the following to activate your account</h1>
              <p>${process.env.CLIENT_URL}/users/activate/${token}</p>
              <hr />
              <p>This email may contain sensitive information</p>
              <p>${process.env.CLIENT_URL}</p>
          `
  };

  try {
    await sgMail.send(emailData)
    return res.json({
      message: `Email has been sent to ${email}`
    });
  } catch(err) {
    console.log(err)
    return res.status(400).json({
      success: false,
      errors: errorHandler(err)
    });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 22:48:01