skip to Main Content

I am following this tutorial 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/ which is a prerequisite to start the first tutorial.

RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined

Here is the code with the form on it. And you can also see the whole repo below.

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>


  )
}

Update

Now Based on Pierre’s answer I am getting the 500 error

Request from ::ffff:127.0.0.1: POST /sendmail 
Response with status 500 in 3 ms.

I wonder if it has to do with it POST’ing from localhost, at least I know it’s sendgrid giving me the error now.

I looked at the npm debugging section and saw this code, not sure exactly where to put it?

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

console error

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

Second Update

I get the following error in terminal now Actually I don’t think I even need a cc, I think it is saying I don’t have a to value, so maybe my env varaiable SENDGRID_TO_EMAIL is not being passed?

Provide at least one of to, cc or bcc 

Now if I add a cc like this

const msg = {
        to: SENDGRID_TO_EMAIL,
        cc:"[email protected]",
        from: email,
        subject: subject ? subject : 'Contact Form Submission',
        html: body,
    };

Then I get a Unauthorized message

For my environment variables there is a .env file at my root that contains the following

SENDGRID_API_KEY=SG.longsting
[email protected]

This is the line that is supposed to grab the env variables

const { SENDGRID_API_KEY, SENDGRID_TO_EMAIL } = process.env

2

Answers


  1. Looking at your source code, I’m pretty sure that the sendgrid send function raises an exception, and that you don’t handle it properly:

    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
        }
    }
    

    I took a quick look at the sendgrid SDK, and I see nothing suggesting that it throws errors with a code property corresponding to a valid http status code.

    The consequence is that you return a response with undefined as status code, hence the ERR_HTTP_INVALID_STATUS_CODE error.

    Try replacing your catch block by the following, and you should at least get a proper response and hopefully, a useful error message from the sendgrid SDK:

    try {
        // same as before
    } catch(e){
        return {
            statusCode: 500,
            body: e.message
        }
    }
    

    Update

    Your issue might be with your environment variables. You should make sure that SENDGRID_API_KEY and SENDGRID_TO_EMAIL are set properly.

    For your development environment, I think you need to add require('dotenv').config() in your function file.

    For your production environment (Netlify), you should set the variables in the UI: https://docs.netlify.com/configure-builds/environment-variables/#declare-variables

    Login or Signup to reply.
  2. Recently I’ve dropped into similar problem and below I’m attaching my solution to your problem.

    folder structure – piece

    Project
     |
     +-- public   
     +-- src
     |  |  
     |  +-- functions
     |      |
     |      +-- sendmail.js
     |
     |  +-- components
     |      |
     |      +-- ContactForm.js
     |
    

    Lambda functions folder in root directory

    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,
        }
      }
    }
    

    Contact form – piece

    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 – packages needed for lambda functions

    "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"
    

    gatsby-config.js

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

    Set proper env variables on Netlify and you should be good to go. Hopefully it helps someone.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search