How to Send Emails with Next JS, Nodemailer, React Hook Form, Tailwind CSS Cover

How to Send Emails with Next JS, Nodemailer, React Hook Form, Tailwind CSS

In today's fast-paced digital world, effective communication remains a cornerstone of successful business interactions. Email remains a reliable tool for reaching out to users, clients, and customers. In this tutorial, we'll explore how to leverage the power of Next.js, React Hook Form, Tailwind CSS, and Nodemailer to create a seamless email-sending experience within your web application.

Prerequisites


Before we dive in, make sure you have a basic understanding of Next.js, React Hook Form, Tailwind CSS, and Nodemailer. If you're new to these technologies, check out the respective documentation and resources to get familiar with them.

Setting Up the Project

To get started, you can clone the GitHub repository we've prepared for this tutorial. This repository contains a sample project that integrates all the necessary technologies.

GitHub Repo Link

Installing Dependencies

Before we proceed, let's install the required packages using npm or yarn:

npm install react-toastify dotenv
# or
yarn add react-toastify dotenv

Configuring Environment Variables

Using dotenv, you can securely manage environment variables. Create a .env file in your project root and add the necessary configurations:

GMAIL_USER=your@gmail.com
GMAIL_PASS=your-password

Creating the Email Form

Our first step is to set up a basic form using React Hook Form. This will allow users to input their email content and recipient details efficiently. React Hook Form provides a simple way to manage form states and validation.

import { MailIcon, PhoneIcon } from "@heroicons/react/outline";
import React from "react";
import { useForm } from "react-hook-form";
import { useState } from "react";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

export default function Home() {
  const [contactDetail, setContactDetail] = useState([]);
  const {
    register,
    handleSubmit,
    watch,
    reset,
    formState: { errors },
  } = useForm();
  const onSubmit = (data) => {
    fetch("/api/contact", {
      method: "POST",
      headers: {
        Accept: "application/json, text/plain, */*",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    })
      .then((res) => {
        // console.log("Response received", res);
        if (res.status === 200) {
          // console.log("Response succeeded!");
          toast("Thank you for contacting us!");
        } else {
          // console.log("Email/Password is invalid.");
          toast("Email/Password is invalid.");
        }
      })
      .catch((e) => console.log(e));
    reset();
  };

  // console.log("contact Detail", contactDetail);

  return (
    <>
      <div className="h-screen relative bg-white">
        <div className="absolute inset-0">
          <div className="absolute inset-y-0 left-0 w-1/2 bg-gray-50" />
        </div>
        <div className="h-full relative max-w-7xl mx-auto lg:grid lg:grid-cols-5">
          <div className="bg-gray-50 py-16 px-4 sm:px-6 lg:col-span-2 lg:px-8 lg:py-24 xl:pr-12">
            <div className="max-w-lg mx-auto">
              <h2 className="text-2xl font-extrabold tracking-tight text-gray-900 sm:text-3xl">
                Get in touch
              </h2>
              <p className="mt-3 text-lg leading-6 text-gray-500">
                Nullam risus blandit ac aliquam justo ipsum. Quam mauris
                volutpat massa dictumst amet. Sapien tortor lacus arcu.
              </p>
              <dl className="mt-8 text-base text-gray-500">
                <div>
                  <dt className="sr-only">Postal address</dt>
                  <dd>
                    <p>742 Evergreen Terrace</p>
                    <p>Springfield, OR 12345</p>
                  </dd>
                </div>
                <div className="mt-6">
                  <dt className="sr-only">Phone number</dt>
                  <dd className="flex">
                    <PhoneIcon
                      className="flex-shrink-0 h-6 w-6 text-gray-400"
                      aria-hidden="true"
                    />
                    <span className="ml-3">+1 (555) 123-4567</span>
                  </dd>
                </div>
                <div className="mt-3">
                  <dt className="sr-only">Email</dt>
                  <dd className="flex">
                    <MailIcon
                      className="flex-shrink-0 h-6 w-6 text-gray-400"
                      aria-hidden="true"
                    />
                    <span className="ml-3">support@example.com</span>
                  </dd>
                </div>
              </dl>
              <p className="mt-6 text-base text-gray-500">
                Looking for careers?{" "}
                <a href="#" className="font-medium text-gray-700 underline">
                  View all job openings
                </a>
                .
              </p>
            </div>
          </div>
          <div className="bg-white py-16 px-4 sm:px-6 lg:col-span-3 lg:py-24 lg:px-8 xl:pl-12">
            <div className="max-w-lg mx-auto lg:max-w-none">
              <form
                onSubmit={handleSubmit(onSubmit)}
                method="POST"
                className="grid grid-cols-1 gap-y-6"
              >
                <div>
                  <label htmlFor="fullName" className="sr-only">
                    Full name
                  </label>
                  <input
                    type="text"
                    name="fullName"
                    id="fullName"
                    autoComplete="name"
                    className="block w-full shadow-sm py-3 px-4 placeholder-gray-500 focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
                    placeholder="Full name"
                    {...register("fullName", { required: true })}
                  />
                </div>
                <div>
                  <label htmlFor="email" className="sr-only">
                    Email
                  </label>
                  <input
                    id="email"
                    name="email"
                    type="email"
                    autoComplete="email"
                    className="block w-full shadow-sm py-3 px-4 placeholder-gray-500 focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
                    placeholder="Email"
                    {...register("email", { required: true })}
                  />
                </div>
                <div>
                  <label htmlFor="phone" className="sr-only">
                    Phone
                  </label>
                  <input
                    type="text"
                    name="phone"
                    id="phone"
                    autoComplete="tel"
                    className="block w-full shadow-sm py-3 px-4 placeholder-gray-500 focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
                    placeholder="Phone"
                    {...register("phone", { required: true })}
                  />
                </div>
                <div>
                  <label htmlFor="message" className="sr-only">
                    Message
                  </label>
                  <textarea
                    id="message"
                    name="message"
                    rows={4}
                    className="block w-full shadow-sm py-3 px-4 placeholder-gray-500 focus:ring-indigo-500 focus:border-indigo-500 border border-gray-300 rounded-md"
                    placeholder="Message"
                    defaultValue={""}
                    {...register("message", { required: true })}
                  />
                </div>
                <div>
                  <button
                    type="submit"
                    className="inline-flex justify-center py-3 px-6 border border-transparent shadow-sm text-base font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                  >
                    Submit
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
      <ToastContainer />
    </>
  );
}

Integrating Nodemailer

Nodemailer makes it incredibly straightforward to send emails from your application. You'll need to install it using npm or yarn:

npm install nodemailer
# or
yarn add nodemailer

Here's a basic example of how you can use Nodemailer to send an email using the data from the form:

export default async function (req, res) {
  require("dotenv").config();

  let nodemailer = require("nodemailer");
  const transporter = nodemailer.createTransport({
    port: 465,
    host: "smtp.gmail.com",
    auth: {
      user: process.env.email,
      pass: process.env.password,
    },
    secure: true,
  });
  const mailData = {
    from: "usmanasifdev@gmail.com",
    to: "jusmanasif435@gmail.com",
    subject: `Message From Usman Asif Dev`,
    //   text: req.body.message + " | Sent from: " + req.body.email,
    html: `
    <div><strong>Name:</strong> ${req.body.fullName}</div>
    <br/>
    <div><strong>Email:</strong> ${req.body.email}</div>
    <br/>
    <div><strong>Phone:</strong> ${req.body.phone}</div>
    <br/>
    <div><strong>Message:</strong> ${req.body.message}</div>
    <br/>
    <p>Sent from:
      ${req.body.email}</p>`,
  };
  await new Promise((resolve, reject) => {
    transporter.sendMail(mailData, function (err, info) {
      if (err) {
        console.log(err);
        reject(err);
      } else {
        console.log(info);
        resolve(info);
      }
    });
  });
  res.status(200).json({ status: "OK" });
}

Conclusion

By combining the capabilities of Next.js, React Hook Form, Tailwind CSS, and Nodemailer, you can seamlessly integrate email sending functionality into your web application. This tutorial provides a foundation for building more advanced features, such as email templates, attachments, and dynamic recipient lists.

Remember, effective communication is key to success, and with the right tools at your disposal, you can create a polished and user-friendly email sending experience.

Feel free to explore the GitHub repository for the complete code and experiment further with the possibilities!