Javascript 使用Netlify lambda函数从GatsbyJS站点发送电子邮件

Javascript 使用Netlify lambda函数从GatsbyJS站点发送电子邮件,javascript,reactjs,aws-lambda,gatsby,netlify,Javascript,Reactjs,Aws Lambda,Gatsby,Netlify,我遵循这个教程,我已经设置好了所有的东西,但是我的终端出现了以下错误。我能够让hello world应用程序在这里为lambda函数工作,这是开始第一个教程的先决条件 RangeError[ERR\u HTTP\u INVALID\u STATUS\u code]:无效状态代码:未定义 这是上面有表格的代码。你也可以在下面看到整个回购协议 import React from 'react' import { HelmetDatoCms } from 'gatsby-source-datocms'

我遵循这个教程,我已经设置好了所有的东西,但是我的终端出现了以下错误。我能够让hello world应用程序在这里为lambda函数工作,这是开始第一个教程的先决条件

RangeError[ERR\u HTTP\u INVALID\u STATUS\u code]:无效状态代码:未定义

这是上面有表格的代码。你也可以在下面看到整个回购协议

import React from 'react'
import { HelmetDatoCms } from 'gatsby-source-datocms'
import { graphql } from 'gatsby'
import Layout from "../components/layout"

export default ({ data }) => {

  const [formState, setFormState] = React.useState({
    name: "",
    email: "",
    subject: "",
    message: "",
  })

  const onChange = (e) => {
    setFormState({...formState, [e.target.name]: e.target.value });
 }

 const submitForm = async (e) => {
  e.preventDefault();

  console.log("test");

  try{
    const response = await fetch("/.netlify/functions/sendmail", {
      method: "POST",
      body: JSON.stringify(formState),
    })

    if (!response.ok) {
      console.log(response);
      return
    }

    console.log("success email");

  } catch(e){

    console.log("error");

  }
}

  return(

  <Layout>

    <article className="sheet">
      <HelmetDatoCms seo={data.datoCmsPricing.seoMetaTags} />

        <section className="left-package-details">

          tests

        <div className="App">
      <form onSubmit={submitForm}>
        <label>
          Name
          <input
            type="text"
            name="name"
            value={formState.name}
            onChange={onChange}
          />
        </label>
        <label>
          Email
          <input
            type="email"
            name="email"
            value={formState.email}
            onChange={onChange}
          />
        </label>
        <label>
          Subject
          <input
            type="textarea"
            name="subject"
            value={formState.subject}
            onChange={onChange}
          />
        </label>
        <label>
          message
          <input
            type="text"
            name="message"
            value={formState.message}
            onChange={onChange}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
    </div>


  )
}
我想知道这是否与从localhost发帖有关,至少我知道它现在是sendgrid给了我错误

我看了npm调试部分,看到了这段代码,不知道该放在哪里

const {
  classes: {
    Mail,
  },
} = require('@sendgrid/helpers');
const mail = Mail.create(data);
const body = mail.toJSON();
console.log(body);
控制台错误

Response {type: "basic", url: "http://localhost:8000/.netlify/functions/sendmail", redirected: false, status: 500, ok: false, …}
type: "basic"
url: "http://localhost:8000/.netlify/functions/sendmail"
redirected: false
status: 500
ok: false
statusText: "Internal Server Error"
headers: Headers {}
body: (...)
bodyUsed: false
__proto__: Response
第二次更新

我现在在终端中出现了以下错误,实际上我甚至不认为我需要抄送,我认为这是说我没有to值,所以可能我的env varaiable SENDGRID_to_电子邮件没有被传递

现在如果我添加一个像这样的cc

const msg = {
        to: SENDGRID_TO_EMAIL,
        cc:"email@email.com",
        from: email,
        subject: subject ? subject : 'Contact Form Submission',
        html: body,
    };
然后我收到一条
未经授权的
消息

对于我的环境变量,在我的根目录下有一个.env文件,其中包含以下内容

SENDGRID_API_KEY=SG.longsting
SENDGRID_TO_EMAIL=myemail@email.com
这是用来获取env变量的行

const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env
现在来看,我很确定sendgrid
send
函数会引发异常,并且您没有正确处理它:

试试看{
等待sgMail.send(msg)
返回{
状态代码:200,
正文:“已发送消息”
}
}捕获(e){
返回{
statusCode:e.code,//e.code可能未定义
正文:e.message
}
}
我快速查看了sendgrid SDK,没有发现任何迹象表明它使用与有效http状态代码对应的
code
属性抛出错误

结果是返回一个带有
undefined
作为状态代码的响应,因此出现
ERR\u HTTP\u INVALID\u status\u code
错误

尝试用以下内容替换您的
catch
块,您至少应该得到正确的响应,并希望从sendgrid SDK获得有用的错误消息:

试试看{
//和以前一样
}捕获(e){
返回{
状态代码:500,
正文:e.message
}
}
更新 您的问题可能与您的环境变量有关。您应该确保
SENDGRID\u API\u键
SENDGRID\u TO\u电子邮件
设置正确

对于您的开发环境,我认为您需要在函数文件中添加
require('dotenv').config()


对于您的生产环境(Netlify),您应该在UI中设置变量:

最近我遇到了类似的问题,下面我将为您的问题附加我的解决方案

文件夹结构-件 根目录中的Lambda函数文件夹 接触式模板 package.json—lambda函数所需的包 netlify.toml gatsby-config.js
在Netlify上设置适当的env变量,您就可以开始了。希望它能帮助别人。

您自己调试过吗?如果没有,请将您的发现和猜测一起添加到帖子中。我完全愿意这样做,我将如何调试它?我已经尝试了我自己能想到的一切。好吧,我现在得到一个500错误,这表明sendgrid SDK给了我一个错误,现在它是从localhost发布的,因为我是在开发人员,这可能与此有关吗?我在上面的问题中添加了更多调试信息,希望能有所帮助。我查看了npm包的调试方面。并且使用了
@sendgrid/helpers
不是sengrid helper给我控制台错误,而是来自您的状态代码,因此除了我在上面添加的控制台消息之外,我不知道任何其他信息。您可以在catch块中执行
console.log(e.message)
吗?我在上面的更新二部分添加了消息和我尝试的内容
SENDGRID_API_KEY=SG.longsting
SENDGRID_TO_EMAIL=myemail@email.com
const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env
Project
 |
 +-- public   
 +-- src
 |  |  
 |  +-- functions
 |      |
 |      +-- sendmail.js
 |
 |  +-- components
 |      |
 |      +-- ContactForm.js
 |
const sgMail = require("@sendgrid/mail")
const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env

exports.handler = async (event, context, callback) => {
  const payload = JSON.parse(event.body)
  const { email, message, name } = payload

  sgMail.setApiKey(SENDGRID_API_KEY)

  const msg = {
    to: SENDGRID_TO_EMAIL,
    from: email,
    subject: `New message from ${name}`,
    text: message,
  }

  try {
    await sgMail.send(msg)
    return {
      statusCode: 200,
      body: "Message sent",
    }
  } catch (err) {
    return {
      statusCode: err.code,
      body: err.message,
    }
  }
}
const formik = useFormik({
    initialValues: { name: "", email: "", message: "" },
    validationSchema,
    onSubmit: (values, { resetForm, setSubmitting }) => {
      axios
        .post("/.netlify/functions/sendmail", values)
        .then(res => {
          console.log(res)
          setSubmitting(false)
          resetForm({})
        })
        .catch(err => {
          console.log(err)
          setSubmitting(false)
        })
    },
  })
"dependencies": {
    "@sendgrid/mail": "^6.5.5",
    "axios": "^0.19.2",
},
"devDependencies": {
    "http-proxy-middleware": "^1.0.3",
    "netlify-lambda": "^1.6.3",
    "npm-run-all": "^4.1.5",
},
"scripts": {
    "develop": "gatsby develop",
    "start": "run-p start:**",
    "start:app": "npm run develop",
    "start:lambda": "netlify-lambda serve src/functions",
    "build": "gatsby build && netlify-lambda build src/functions",
    "build:app": "gatsby build",
    "build:lambda": "netlify-lambda build src/functions"
 }

[build]
  command = "npm run build"
  functions = "functions"
  publish = "public"
module.exports = {
  // other setup

  developMiddleware: app => {
    app.use(
      "/.netlify/functions/",
      proxy({
        target: "http://localhost:9000",
        pathRewrite: {
          "/.netlify/functions/": "",
        },
      })
    )
  },
}