使用 Netlify lambda 函数从 GatsbyJS 站点发送电子邮件
Using Netlify lambda functions to send emails from a GatsbyJS site
我正在学习本教程 https://dev.to/char_bone/using-netlify-lambda-functions-to-send-emails-from-a-gatsbyjs-site-3pnb I have everything set up but I get the following error in my terminal. I am able to get the hello world app working for the lambda function from here https://www.gatsbyjs.org/blog/2018-12-17-turning-the-static-dynamic/,这是开始第一个教程的先决条件。
RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined
这是带有表格的代码。你还可以在下面看到整个 repo。
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>
)
}
更新
现在根据 Pierre 的回答,我收到了 500 错误
Request from ::ffff:127.0.0.1: POST /sendmail
Response with status 500 in 3 ms.
我想知道它是否与它有关 POST' 来自本地主机,至少我知道现在是 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
第二次更新
我现在在终端中收到以下错误实际上我认为我什至不需要 cc,我认为这是在说我没有价值,所以也许我的 env varaiable SENDGRID_TO_EMAIL没有通过?
Provide at least one of to, cc or bcc
现在如果我像这样添加抄送
const msg = {
to: SENDGRID_TO_EMAIL,
cc:"email@email.com",
from: email,
subject: subject ? subject : 'Contact Form Submission',
html: body,
};
然后我收到 Unauthorized
消息
对于我的环境变量,我的根目录下有一个 .env 文件,其中包含以下内容
SENDGRID_API_KEY=SG.longsting
SENDGRID_TO_EMAIL=myemail@email.com
这是应该获取环境变量的行
const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env
查看 your source code,我很确定 sendgrid send
函数引发异常,并且您没有正确处理它:
try{
await sgMail.send(msg)
return {
statusCode: 200,
body: "Message sent"
}
} catch(e){
return {
statusCode: e.code, // e.code is probably undefined
body: e.message
}
}
我快速查看了 sendgrid SDK,但没有发现任何提示它会抛出错误的 code
属性 对应于有效的 http 状态代码。
结果是您 return 以 undefined
作为状态代码的响应,因此 ERR_HTTP_INVALID_STATUS_CODE
错误。
尝试用以下内容替换您的 catch
块,您至少应该得到正确的响应,希望是来自 sendgrid SDK 的有用错误消息:
try {
// same as before
} catch(e){
return {
statusCode: 500,
body: e.message
}
}
更新
您的问题可能与您的环境变量有关。您应该确保 SENDGRID_API_KEY
和 SENDGRID_TO_EMAIL
设置正确。
对于你的开发环境,我认为你需要在你的函数文件中添加require('dotenv').config()
。
对于您的生产环境 (Netlify),您应该在 UI 中设置变量:https://docs.netlify.com/configure-builds/environment-variables/#declare-variables
最近我遇到了类似的问题,下面附上我对你的问题的解决方案。
文件夹结构 - 一块
Project
|
+-- public
+-- src
| |
| +-- functions
| |
| +-- sendmail.js
|
| +-- components
| |
| +-- ContactForm.js
|
根目录中的 Lambda 函数文件夹
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)
})
},
})
package.json - lambda 函数所需的包
"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"
}
netlify.toml
[build]
command = "npm run build"
functions = "functions"
publish = "public"
盖茨比-config.js
module.exports = {
// other setup
developMiddleware: app => {
app.use(
"/.netlify/functions/",
proxy({
target: "http://localhost:9000",
pathRewrite: {
"/.netlify/functions/": "",
},
})
)
},
}
在 Netlify 上设置适当的 env 变量,你应该可以开始了。希望它对某人有所帮助。
我正在学习本教程 https://dev.to/char_bone/using-netlify-lambda-functions-to-send-emails-from-a-gatsbyjs-site-3pnb I have everything set up but I get the following error in my terminal. I am able to get the hello world app working for the lambda function from here https://www.gatsbyjs.org/blog/2018-12-17-turning-the-static-dynamic/,这是开始第一个教程的先决条件。
RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined
这是带有表格的代码。你还可以在下面看到整个 repo。
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>
)
}
更新
现在根据 Pierre 的回答,我收到了 500 错误
Request from ::ffff:127.0.0.1: POST /sendmail
Response with status 500 in 3 ms.
我想知道它是否与它有关 POST' 来自本地主机,至少我知道现在是 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
第二次更新
我现在在终端中收到以下错误实际上我认为我什至不需要 cc,我认为这是在说我没有价值,所以也许我的 env varaiable SENDGRID_TO_EMAIL没有通过?
Provide at least one of to, cc or bcc
现在如果我像这样添加抄送
const msg = {
to: SENDGRID_TO_EMAIL,
cc:"email@email.com",
from: email,
subject: subject ? subject : 'Contact Form Submission',
html: body,
};
然后我收到 Unauthorized
消息
对于我的环境变量,我的根目录下有一个 .env 文件,其中包含以下内容
SENDGRID_API_KEY=SG.longsting
SENDGRID_TO_EMAIL=myemail@email.com
这是应该获取环境变量的行
const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env
查看 your source code,我很确定 sendgrid send
函数引发异常,并且您没有正确处理它:
try{
await sgMail.send(msg)
return {
statusCode: 200,
body: "Message sent"
}
} catch(e){
return {
statusCode: e.code, // e.code is probably undefined
body: e.message
}
}
我快速查看了 sendgrid SDK,但没有发现任何提示它会抛出错误的 code
属性 对应于有效的 http 状态代码。
结果是您 return 以 undefined
作为状态代码的响应,因此 ERR_HTTP_INVALID_STATUS_CODE
错误。
尝试用以下内容替换您的 catch
块,您至少应该得到正确的响应,希望是来自 sendgrid SDK 的有用错误消息:
try {
// same as before
} catch(e){
return {
statusCode: 500,
body: e.message
}
}
更新
您的问题可能与您的环境变量有关。您应该确保 SENDGRID_API_KEY
和 SENDGRID_TO_EMAIL
设置正确。
对于你的开发环境,我认为你需要在你的函数文件中添加require('dotenv').config()
。
对于您的生产环境 (Netlify),您应该在 UI 中设置变量:https://docs.netlify.com/configure-builds/environment-variables/#declare-variables
最近我遇到了类似的问题,下面附上我对你的问题的解决方案。
文件夹结构 - 一块
Project
|
+-- public
+-- src
| |
| +-- functions
| |
| +-- sendmail.js
|
| +-- components
| |
| +-- ContactForm.js
|
根目录中的 Lambda 函数文件夹
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)
})
},
})
package.json - lambda 函数所需的包
"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"
}
netlify.toml
[build]
command = "npm run build"
functions = "functions"
publish = "public"
盖茨比-config.js
module.exports = {
// other setup
developMiddleware: app => {
app.use(
"/.netlify/functions/",
proxy({
target: "http://localhost:9000",
pathRewrite: {
"/.netlify/functions/": "",
},
})
)
},
}
在 Netlify 上设置适当的 env 变量,你应该可以开始了。希望它对某人有所帮助。