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.
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!