'My contact form isn't working with Nodemailer. How do I fix it?

I'm trying to implement email functionality with Node.js, React.js, Nodemailer, and OAuth2 on a contact form

I have two files:

contactForm.js

import React, { useState } from "react";

const App = () => {
  
const [mailerState, setMailerState] = useState({
    name: "",
    email: "",
    subject:"",
    message: "",
  });

  function handleStateChange(e) {
    setMailerState((prevState) => ({
      ...prevState,
      [e.target.name]: e.target.value,
    }));
  }

  const submitEmail = async (e) => {
    e.preventDefault();
    console.log({ mailerState });
    const response = await fetch("/api/server", {
      method: "POST",
      headers: {
        "Content-type": "application/json",
      },
      body: JSON.stringify({ mailerState }),
    })
    .then((res) => res.json())
    .then(async (res) => {
      const resData = await res;
      console.log(resData);
      if (resData.status === "success") {
        alert("Message Sent");
      } else if (resData.status === "fail") {
        alert("Message failed to send");
      }
    })
      .then(() => {
        setMailerState({
            name: "",
            email: "",
            subject:"",
            message: "",
        });
      });
  };

  return (
   
    <div className="flex justify-center mb-14">
      <form className="w-full max-w-lg" onSubmit={submitEmail} >
        <div className="flex  flex-wrap -mx-3 mb-6">
          <div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
            <label
            htmlFor="name"
              className="block uppercase tracking-wide text-gray-400 text-xs font-bold mb-2"
            >
              First Name
            </label>
            <input
              className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
              name="name"
              type="text"
              placeholder="Ade"
              required value={mailerState.name}
              onChange={handleStateChange}
            />
          </div>
          <div className="w-full md:w-1/2 px-3">
            <label
              htmlFor="name"
              className="block uppercase tracking-wide text-gray-400 text-xs font-bold mb-2"
            >
              Last Name
            </label>
            <input
              className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
              name="lastname"
              type="text"
              placeholder="Banjo"
              required value={mailerState.name}
              onChange={handleStateChange}
            />
          </div>
        </div>
        <div className="flex flex-wrap -mx-3 mb-6">
          <div className="w-full px-3">
            <label
              htmlFor="email"
              className="block uppercase tracking-wide text-gray-400 text-xs font-bold mb-2"
            >
              E-mail
            </label>
            <input
              className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
              name="email"
              type="email"
              aria-describedby="emailHelp"
              required value={mailerState.email}
              onChange={handleStateChange}
            />
            <p className="text-gray-600 text-xs italic">
              e.g. [email protected]
            </p>
          </div>
        </div>
        <div className="flex flex-wrap -mx-3 mb-6">
          <div className="w-full px-3">
            <label
              htmlFor="message"
              className="block uppercase tracking-wide text-gray-400 text-xs font-bold mb-2"
            >
              Message
            </label>
            <textarea
              className=" no-resize appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500 h-48 resize-none"
              name="message"
              required value={mailerState.message}
              onChange={handleStateChange}
            ></textarea>
            <p className="text-gray-600 text-xs italic">
            </p>
          </div>
        </div>
        <div className="md:flex md:items-center">
          <div className="md:w-1/3">
            <button
              className="shadow bg-indigo-600 hover:bg-indigo-700 focus:ring-indigo-500 focus:ring-offset-indigo-200 text-white w-full transition ease-in duration-200 text-center font-bold py-2 px-1 rounded"
              type="button"
            >
              Send
            </button>
          </div>
          <div className="md:w-2/3"></div>
        </div>
      </form>
      </div>
    
  );
  }

export default App;

and

server.js:

const express = require("express");
const app = express();
const nodemailer = require("nodemailer");
const cors = require("cors");
require("dotenv").config();


// middleware
app.use(express.json());
app.use(cors());


// Setting up SMTP for Nodemailer to send mail
const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    type: "OAuth2",
    user: process.env.EMAIL,
    pass: process.env.WORD,
    clientId: process.env.OAUTH_CLIENTID,
    clientSecret: process.env.OAUTH_CLIENT_SECRET,
    refreshToken: process.env.OAUTH_REFRESH_TOKEN,
  },
});

// verify connection configuration
transporter.verify(function (error, success) {
  if (error) {
    console.log(error);
  } else {
    console.log(`=== Server is ready to take our messages: ${success} ===`);
  }
});


app.post("/api/server", function (req, res) {
  let mailOptions = {
    from: `${req.body.mailerState.email}`,
    to: process.env.EMAIL,
    subject: `Message from: ${req.body.mailerState.email}`,
    text: `${req.body.mailerState.message}`,
  };
 
  transporter.sendMail(mailOptions, function (err, data) {
    if (err) {
      res.json({
        status: "fail",
      });
    } else {
      console.log("== Message Sent ==");
      res.json({
        status: "success",
      });
    }
  });
 });

const port = 5000;
app.listen(port, () => {
 console.log(`Server is running on port: ${port}`);
});

They are both in two different folders: contactForm.js is in Components folder and server.js is in pages/api folder.

The Contact form renders perfectly but the email functionality does not. How do I resolve this?

Thanks in advance



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source