使用 Gatsby 函数设置 sendgrid 表单的授权/CORS 问题

问题描述

我正在尝试设置一个表单,使用 sendgrid 和 Gatsby 函数将信息发送到我的电子邮件。 我试过关注 gatsby sendgrid example 和 YouTube 视频 "four real world solutions using gatsby functions...",但最终我都收到了授权/CORS 错误

*控制台错误

Error Screen

*response.body.errors

enter image description here

*已验证的单个发件人

enter image description here

我尝试了一些事情,例如:

  • 在我的函数周围添加 cors middleware(虽然我不是 100% 我做对了)
  • 设置res.set({"Content-Type": "application/json" Authorization: `Bearer ${process.env.SENDGRID_API_KEY}` });
  • 设置res.setHeader('Access-Control-Allow-Origin','*')
  • 创建新的 API 密钥
  • 测试 gatsby 开发和构建,清除缓存等

我的想法用完了,所以任何建议将不胜感激:)

当前表单和api的代码如下:

src/api/sendgrid.js

const sgMail = require('@sendgrid/mail')
console.log("api key:" + process.env.SENDGRID_API_KEY,process.env.SENDGRID_AUTHORIZED_EMAIL)
sgMail.setApiKey(process.env.SENDGRID_API_KEY)


export default async (req,res) => {
    res.set({"Content-Type": "application/json",Authorization: `Bearer ${process.env.SENDGRID_API_KEY}`
    });
    const msg = {
        to: 'myemail@gmail.com',// Change to your recipient
        from: process.env.SENDGRID_AUTHORIZED_EMAIL,// Change to your verified sender
        subject: 'Sending with SendGrid is Fun',text: 'and easy to do anywhere,even with Node.js',html: '<strong>and easy to do anywhere,even with Node.js</strong>',}
      sgMail
      .send(msg)
      .then(() => {
          console.log('Email sent'); console.log(msg);
      })
      .catch((error) => {
          
          console.error(error);console.log('there was an error');
          return res.status(500).json({
              error: error.response,})
          
      })

      return res.status(200)
    

}

src/pages/components/contact.js

const Contact = () => {

    const [serverState,setServerState] = useState({
        formSent: false,});

    const {
        register,handleSubmit,formState: { errors },} = useForm()
      const onSubmit = data => {
        fetch(`/api/sendgrid`,{
          method: `POST`,body: JSON.stringify(data),headers: {
            "content-type": `application/json`,},})
          .then(res => res.json())
          .then(body => {
            console.log(`response from API:`,body);
          })
      }
    
      console.log({ errors })
    return(
        <div style={{ display: "grid",width: "100%",}} id="contactSection" >


      
        <div
            style={{
            // By using the same grid area for both,they are stacked on top of each other
            gridArea: "1/1",position: "relative",// This centers the other elements inside the hero component
            placeItems: "center",display: "grid",}}
        >

        <ContactDiv>
        {/* class={serverState.formSent ? "sent" : ""} */}
            <span 
            // css={styles(serverState.formSent)}
            >
                <h1>Message Sent</h1>
                <p>I'll be in touch shortly. Regards,Daniel.</p>
            </span>
            {/* <MobileId id="contactM"/> */}
            <h1 id="contactM">Need a Website?</h1>
            <ContactInfo>
            <p>For a free project consultation call,email or use the form below.</p>
            <p>Mobile:<br/> 022 078 0868</p>
            <p>Email:<br/> daniel@thoughtfulhq.com</p>
            </ContactInfo>
            <div>
                <form 
                onSubmit={handleSubmit(onSubmit)}
                // action="/api/sendgrid" method="POST"
                >
                    <label htmlFor="name">
                            <p>Name:</p>
                            <input 
                                type="text" 
                                name="name" 
                                required  
                                {...register("Name",{ required: true,maxLength: 100 })}  
                            />
                    </label>
                    <label htmlFor="email">
                        <p>Email:</p>
                        <input 
                            type="email" 
                            name="email" 
                            required
                            {...register("Email",pattern: /^\S+@\S+$/i })}
                        />
                    </label>
                    <label htmlFor="message">
                        <p>Project Details:</p>
                        <textarea 
                            name="message" 
                            id="message" 
                            rows="5" 
                            required
                            {...register("Message",maxLength: 2000 })} 
                        />
                    </label>
                    <button type="submit">Submit</button>
                </form>
            </div>
        </ContactDiv>
        </div>
        </div>
    )
    
}

export default Contact;

解决方法

这里是 Twilio SendGrid 开发者布道者。

正如我们在评论中发现的那样,您的 SendGrid API 密钥被错误地存储在您的 .env 文件中。环境变量应该存储在每个变量的新行中,变量名和值之间没有空格,例如:

SENDGRID_API_KEY=SG.xxx
SENDGRID_AUTHORIZED_EMAIL=sender@example.com

另外要注意的是,您不应在对前端请求的响应中设置 Authorization 标头。如果他们调查响应标头,这将向使用该表单的任何人公开您的 SendGrid API 密钥。我建议删除该行:

    res.set({"Content-Type": "application/json",Authorization: `Bearer ${process.env.SENDGRID_API_KEY}`
    });

来自src/api/sendgrid.js