0

I am creating a request quote form in nextjs using sendgrid as a thirdparty api for sending emails / submitting request quote from form. I keep receiving the following error and I am unable to link the form to the email.

error - ResponseError: Unauthorized
    at node_modules/@sendgrid/client/src/classes/client.js:146:29
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 401,
  response: {
    headers: {
      server: 'nginx',
      date: 'Wed, 18 Jan 2023 17:25:46 GMT',
      'content-type': 'application/json',
      'content-length': '116',
      connection: 'close',
      'access-control-allow-origin': 'https://sendgrid.api-docs.io',
      'access-control-allow-methods': 'POST',
      'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-of, x-sg-elas-acl',
      'access-control-max-age': '600',
      'x-no-cors-reason': 'https://sendgrid.com/docs/Classroom/Basics/API/cors.html',
      'strict-transport-security': 'max-age=600; includeSubDomains'
    },
    body: { errors: [Array] }
  },
  page: '/api/contact'
}

Under pages/contact.jsx

const contact = () => {
  const [values, setValues] = useState({
    firstName: "",
    lastName: "",
    phone: "",
    email: "",
    zip: "",
    message: "",
  });

  const {firstName, lastName, phone, email, zip, message} = values;

  const handleChange = e => 
    setValues({ ...values, [e.target.name]: e.target.value });

  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      await fetch("http://localhost:3000/api/contact", {
        method: "POST",
        header: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(values),
      });
    } catch (err) {
      console.log(err);
    }
  };

 return (
    <div className='w-full h-screen'>
      <div className='min-h-screen py-40 border border-gray-800 bg-white bg-gradient-to-br from-sjrblue to-sjrblue-200'>
        <div className="container mx-auto">
          <div className="flex flex-col lg:flex-row w-10/12 bg-white rounded-xl mx-auto shadow-lg overflow-hidden">
            <div alt='loaded trailer' className='w-full h-[400px] lg:gap-5 lg:h-auto lg:w-1/2 bg-contactImage bg-cover bg-center text-center shadow-lg shadow-slate-400'></div>

            {/* Request Quote Form */}
            <div className="lg:w-1/2 lg:m-2 p-4 items-center">
              <h2 className='text-3xl mb-4 text-center text-sjrblue'>Company Name</h2>
              <p className='mb-4 text-center'>CONTACT US TODAY FOR A <span className='text-blue font-bold'>FREE</span> JUNK REMOVAL ESTIMATE</p>

              <form onSubmit={handleSubmit}>
                <div className='grid grid-cols-2 gap-1 md:gap-3 lg:gap-5'>
                  <input 
                    type="text" 
                    placeholder='first name' 
                    value={firstName} 
                    onChange={handleChange}  
                    required
                    name='firstName' 
                    className='border border-gray-400 py-1 px-2 shadow-lg shadow-slate-400'
                  />
                  <input 
                    type="text" 
                    placeholder='sur name'
                    value={lastName}
                    onChange={handleChange} 
                    required 
                    name='lastName'
                    className='border border-gray-400 py-1 px-2 shadow-lg shadow-slate-400'
                  />
                </div>
                <div className='mt-5'>
                  <input 
                    type="email" 
                    placeholder='email'
                    value={email}
                    onChange={handleChange} 
                    required 
                    name='email' 
                    className='text-sm border border-gray-400 py-1 px-2 w-full shadow-lg shadow-slate-400'
                  />
                </div>
                <div className='mt-5'>
                  <input 
                    type="tel" 
                    id='phone-number' 
                    onkeydown='phoneNumberFormatter()' 
                    inputmode='tel' 
                    placeholder='phone number 123-456-7890' 
                    pattern='[0-9]{3}-[0-9]{3}-[0-9]{4}' 
                    value={phone}
                    onChange={handleChange} 
                    required 
                    name='phone' 
                    className='text-sm border border-gray-400 py-1 px-2 w-full shadow-lg shadow-slate-400'
                  />
                </div>
                <div className='mt-5'>
                  <input 
                    type="text" 
                    inputmode='numeric' 
                    placeholder='zip code' 
                    maxLength={5}
                    value={zip}
                    onChange={handleChange} 
                    name='zip' 
                    required 
                    className='text-sm border border-gray-400 py-1 px-2 w-full shadow-lg shadow-slate-400'
                  />
                </div>
                <div className='mt-5'>
                  <textarea 
                    name="message" 
                    placeholder='message' 
                    id="" cols="30" 
                    rows="10" 
                    value={message}
                    onChange={handleChange}  
                    required 
                    className='text-sm border border-gray-400 py-1 px-2 w-full shadow-lg shadow-slate-400'>  
                  </textarea>
                </div>
                <div className='mt-5 text-center'>
                  <input type="checkbox" required className='border border-gray-400 w-3 h-3'/>
                  <span className='px-3 text-sm'>I am not a robot</span>
                  <div className='mt-5'>
                    <button className='bg-sjrblue w-full text-enter text-white py-3 rounded  hover:bg-blue-700  duration-300 shadow-lg shadow-slate-400'>Get your FREE estimate</button>
                  </div>
                </div>
              </form>
            </div>

          </div>
        </div>
      </div>  

under pages/api/contact.js

require("dotenv").config();
const sgMail = require("@sendgrid/mail");

const { SG_API_KEY, FROM_EMAIL, TO_EMAIL } = process.env;
sgMail.setApiKey(SG_API_KEY);

export default async function handler(req, res) {
    const {firstName, lastName, phone, email, zip, message} = req.body;

    const msg = {
        to: TO_EMAIL,
        from: FROM_EMAIL,
        subject: '',
        html: `<p><strong>First Name: </strong>${firstName}</p>
        <p><strong>Last Name: </strong>${lastName}</p>
        <p><strong>Phone Number: </strong>${phone}</p>
        <p><strong>Email: </strong>${email}</p>
        <p><strong>Zip: </strong>${zip}</p>
        <p><strong>Message: </strong>${message}</p>
        `,
    };
    await sgMail.send(msg);
    console.log('email sent');
    res.status(200).json({ success: true  });

And I have an .env file in my root files

SG_API_KEY= #API Key
TO_EMAIL=  #verified email
FROM_EMAIL= #email to send form to

Please help! Thank you in advance!

1 Answer 1

1

Twilio developer evangelist here.

Because it's a 401 error, I think it's an issue with how you set up your API key in environment variables.

To set up environment variables, you can use these 3 commands:

echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env
echo "sendgrid.env" >> .gitignore
source ./sendgrid.env

You could also change your API key settings to Full access in the SendGrid console, or it could be the incorrect API key so you could also generate a new one.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.