Sending Mails from NodeJS app for free

Nikhil Mohite

Nikhil Mohite / Jan 30, 2023

3 min read

Email is one of the most widely used forms of communication in today's digital world. As a developer, being able to send mails from your NodeJS application can come in handy in variety of situations. Thankfully, there is a great Open-Source module available for NodeJS called Nodemailer that makes it easy to send emails from your application.

Nodemailer is a module for Node.js applications to allow easy as cake email sending

Project Setup

We'll be using NextJS in this tutorial. First, we have to make a simple contact form to take inputs from the user.

Initialize a starting template for NextJS using the below command.

npx create-next-app@latest sending-mails

Installing Nodemailer

npm install nodemailer

Contact form

Then after removing the starter code, create a simple form with the following fields - Email and Message.

import { useState } from "React";

export default function Contact() {
  const [userMail, setUserMail] = useState("");
  const [userMsg, setUserMsg] = useState("");

  return (
      <h1>Contact form</h1>
      <form method="POST" action="/api/mailsend">
            onChange={(e) => setUserMail(}
            onChange={(e) => setUserMsg(}
        <button type="submit">Send message</button>

Styling the form

Applying minimal CSS to the form.

h1 {
  text-align: center;

form {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 10px;

Backend API

The contact form present in the frontend of the application will be sending the user's details to this API via a simple POST request.

import nodemailer from "nodemailer";

export default async function handler(req, res) {
  try {
    if (req.method === "POST") {
      const body = req.body;

      const {  userMail, userMsg } = body;

      // creating a transporter
      const transporter = nodemailer.createTransport({
        host: "",
        port: 465,
        secure: true,
        auth: {
          user: process.env.USER_EMAIL,
          pass: process.env.USER_PASSWORD,

      const emailRes = await transporter.sendMail({
        from: userMail,
        subject: `New message from ${userMail}`,
        html: ${userMsg}

      const info = await emailRes.messageId;
      console.log("Message ID - ", info);
      return res.status(200).json({ data: "Email sent successfully" });

  } catch (error) {
    return res.status(500).json({ error: error.message });

Sending form data to API

After the user submits the form, we have to send the entered data to the backend API /api/mailsend via POST request. Define a function onFormSubmit which will be invoked when the form is submitted.

import { useState } from "React";

export default function Contact() {
+  const onFormSubmit = async (e) => {
+    e.preventDefault();
+    const response = await fetch("/api/mailsend", {
+      method: "POST",
+      headers: {
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({ userMail, userMsg }),
+    });
+    const status = await response.status;
+    console.log(status); // 200 - success
+  };
  return (
      <h1>Contact form</h1>

And that's pretty much it! You can also add error handling to this code. E.g, when the user submits any invalid email.

How does this work?

Visual description of how nodemailer works

Closing Thoughts

Overall it's good compared to other paid services like EmailJS, SendGrid or SendInBlue which have limits on the number of emails per month.