Search code examples
javascriptreactjsaws-lambdagatsbynetlify

Using Netlify lambda functions to send emails from a GatsbyJS site


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

Solution

  • 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