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

使用SendGrid API发送邮件时遭遇401未授权错误求助

SendGrid API 401 Unauthorized 错误排查求助

我在通过SendGrid API发送邮件时,向http://localhost:3000/api/mail发起POST请求返回500 Internal Server Error,VS Code终端显示ResponseError: Unauthorized(错误码401)。已配置api/mail.js、.env.local(含SG_API_KEY)及React Contact.js组件,且已验证发件和收件邮箱域名,多次重启服务器后问题仍未解决,请求帮助排查。


相关代码文件

api/mail.js

require("dotenv").config();

const sgMail = require("@sendgrid/mail");

const { SG_API_KEY, FROM_EMAIL, TO_EMAIL } = process.env;

sgMail.setApiKey(SG_API_KEY);

export default async function handler(req, res) {
  const { name, phone} = req.body;
  const msg = {
    to: TO_EMAIL, // 收件邮箱
    from: FROM_EMAIL, // 已验证的发件邮箱
    subject: "Contact",
    html: `<p><strong>Name: </strong>${name}</p>
    <p><strong>Phone Number: </strong>${phone}</p>    
    `,
  };
  
  await sgMail.send(msg);
  console.log("email sent");
  res.status(200).json({ success: true });
}

.env.local

SG_API_KEY = XXX

Contact.js 组件

import React, { useState } from 'react'

function Contact() {
  
  const [mail, setMail] = useState({
    name: '',
    phone:'',
  })

  const {name, phone} = mail

  const handleChange = e => setMail({...mail, [e.target.name]: e.target.value})

  const handleSubmit = async (e) => {
    e.preventDefault();
    await fetch("http://localhost:3000/api/mail", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(mail),
    });
  };

  return (
    <div className='xl:mt-20 lg:mt-20 md:mt-20 mt-14 flex flex-col items-center'>
        <em id='Metropolis' className='uppercase mb-7 xl:text-[109.07px] lg:text-[109.07px] md:text-[89.07px] text-[39px]'>
        Let's be in touch.
        </em>

        <form onSubmit={handleSubmit} method="POST" className='xl:space-x-4 lg:space-x-4 xl:space-y-0 lg:space-y-0 space-y-5 mb-20 flex xl:flex-row lg:flex-row flex-col items-center'>
          
            <input type="text" value={name} onChange={handleChange} name='name' placeholder='YOUR FULL NAME' className='flex-grow border-2 border-black p-4 pl-4 font-Catamaran text-sm text-gray-500 w-[315px]'></input>
            <input type="text" value={phone} onChange={handleChange} name='phone' placeholder='PHONE NUMBER' className='flex-grow border-2 border-black p-4 pl-4 font-Catamaran text-sm text-gray-500 w-[315px]'></input>
            <button className='bg-[#2E2E2E] border-2 border-black text-white p-[14px] xl:w-[210px] lg:w-[210px] w-[315px] hover:bg-white hover:text-black transition duration-300 ease-in-out'>Send Request</button>
        </form>
    </div>
  )
}

export default Contact

完整错误信息

error - ResponseError: Unauthorized
    at C:\Users\ASUS\OneDrive\Desktop\saida-website\node_modules\@sendgrid\client\src\classes\client.js:146:29
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 401,
  response: {
    headers: {
      server: 'nginx',
      date: 'Mon, 20 Feb 2023 13:30:27 GMT',
      'content-type': 'application/json',
      'content-length': '76',
      connection: 'close',
      'access-control-allow-origin': 'https://sendgrid.api-docs.io',
      'access-control-allow-methods': 'POST',
      'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-of, x-sg-elas-acl',
      'access-control-max-age': '600',
      'x-no-cors-reason': 'https://sendgrid.com/docs/Classroom/Basics/API/cors.html',
      'strict-transport-security': 'max-age=600; includeSubDomains'
    },
    body: { errors: [Array] }
  },
  page: '/api/mail'
}

已验证邮箱域名(含gmail.com),使用SendGrid配置的发件邮箱,多次重启服务器仍未解决问题。


排查方案
  1. 检查API密钥有效性

    • 登录SendGrid后台,确认SG_API_KEY是完整复制的,没有多余空格或换行。
    • 确保该密钥拥有Mail Send权限,在API密钥管理页面查看权限列表,若没有则重新生成带对应权限的密钥。
  2. 补全.env.local配置项
    当前.env.local只配置了SG_API_KEY,但代码中用到了FROM_EMAIL和TO_EMAIL,需补充这两个变量:

    SG_API_KEY = 你的完整密钥
    FROM_EMAIL = 你在SendGrid验证过的发件邮箱
    TO_EMAIL = 收件邮箱地址
    
  3. 添加错误捕获逻辑
    当前api/mail.js未捕获sgMail.send的异常,导致请求直接返回500,建议添加try-catch块输出详细错误:

    export default async function handler(req, res) {
      try {
        const { name, phone} = req.body;
        const msg = {
          to: TO_EMAIL,
          from: FROM_EMAIL,
          subject: "Contact",
          html: `<p><strong>Name: </strong>${name}</p>
          <p><strong>Phone Number: </strong>${phone}</p>    
          `,
        };
        
        await sgMail.send(msg);
        console.log("email sent");
        res.status(200).json({ success: true });
      } catch (error) {
        console.error("SendGrid错误详情:", error.response.body.errors);
        res.status(error.code || 500).json({ success: false, error: error.message });
      }
    }
    

    这样能在终端看到SendGrid返回的具体错误原因,比如邮箱未验证、权限不足等。

  4. 确认环境变量加载状态

    • 在api/mail.js开头添加console.log(process.env.SG_API_KEY),确认密钥是否正常读取,若输出undefined说明变量未加载,检查文件名是否为.env.local(不能有拼写错误)。
    • 重启服务器后再次验证变量是否加载。
  5. 检查发件邮箱身份
    即使域名已验证,也要确认FROM_EMAIL是单独验证过的单个邮箱,或者属于已验证域名且在SendGrid中完成了发件人身份配置,避免使用未授权的发件地址。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:35:32