← Back to list

Step-by-Step: Integrating Nodemailer for Email Functionality in Next.js

In the dynamic landscape of web development, effective communication with users is essential. nodemailer is a powerful Node.js module that…

Kyaw Thu in Stackademic · 2024-05-02 16:22 · 7 claps · 4.8 min read
#nodemailer #nextjs #typescript #email #react
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Step-by-Step: Integrating Nodemailer for Email Functionality in Next.js

Photo by Brett Jordan on Unsplash

Photo by Brett Jordan on Unsplash

In the dynamic landscape of web development, effective communication with users is essential. nodemailer is a powerful Node.js module that simplifies the process of receiving messages from your contact form in you email. In this guide, we’ll explore how to integrate nodemailer into your Next.js application, unlocking the potential for enhanced user engagement and communication.

Advantages of using Nodemailer

  1. Flexibility and Customization
  2. Ease of Use
  3. Support for Various Transport Methods
  4. Reliability and Scalability
  5. Active Community and Support

Installing Nodemailer

npm install nodemailer

If you are using TypeScript, you will need to add type definitions. You can copy the following code.

npm install --save @types/nodemailer

Next JS API Route

I will be using Next.js 14 App Router; therefore, you might need to adjust the code if you are using other versions of Next.js.

Inside the app folder, create a folder named api. Inside the api folder, create another folder. You can give any name you like for that folder, but I will name it contact. Inside the contact folder, create route.ts.

The file structure will be as follows:

app
  api
    contact
      route.ts

I will go step by step to create a POST function inside the route.ts file.

First, we will import NextResponse from next/server and nodemailer from Nodemailer.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

For the next part, you might want to create a .env file in your root folder and add it to the .gitignore file.

Inside the .env file, add the following code.

EMAIL="your-email@email.com"
PASSWORD="your-email-password"

You can add your email and password directly in the route.ts file, but it is a good practice to hide your sensitive information inside the .env or .env.local file.

Now, let’s get back to route.ts file.

We will extract the email and password from the .env file inside the route.ts file.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

Make sure that the spelling of EMAIL and PASSWORD is the same as the one inside the .env file.

We can start creating a POST function to send customer’s message directly to our email inbox.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

export async function POST(request: Request) {

}

We can use try and catch block inside the POST function to catch errors that might happen.

We will implement the catch block first before implementing the try block. All we need to know is return a NextResponse to let the client side know the error.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

export async function POST(request: Request) {
  try {
  } catch (error) {
    return new NextResponse("Failed to send message.", { status: 500 })
  }
}

We can implement the try block now.

We will be expecting name, email, and message from the client side. You can include additional information if you want for your website, but for the sake of this tutorial, I will only include name, email, and message.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

export async function POST(request: Request) {
  try {
    const { name, email, message } = await request.json();
  } catch (error) {
    return new NextResponse("Failed to send message.", { status: 500 })
  }
}

Now, let’s start the nodemailer part.

We will create transporter first. We will need to provide the email service we want to use. You can use any service you like, but I will be using “zoho.” It works well with nodemailer, and it is simple to set up.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

export async function POST(request: Request) {
  try {
    const { name, email, message } = await request.json();

    const transporter = nodemailer.createTransport({
      service: "zoho",
      host: "smtpro.zoho.in",
      port: 465
      secure: true,
      auth: {
        user,
        pass,
      },
    });
  } catch (error) {
    return new NextResponse("Failed to send message.", { status: 500 })
  }
}

After creating a transporter, we can create mailOptions to add email content. You can customize text property. For this tutorial, I will use a simple string template.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

export async function POST(request: Request) {
  try {
    const { name, email, message } = await request.json();

    const transporter = nodemailer.createTransport({
      service: "zoho",
      host: "smtpro.zoho.in",
      port: 465
      secure: true,
      auth: {
        user,
        pass,
      },
    });

    const mailOptions = {
      from: "user",
      to: "the-email-you-want-to-receive-the-message",
      subject: "New message from your-website",
      text: `Name: ${name}\nEmail: ${email}\nMessage: ${message}`,
    };
  } catch (error) {
    return new NextResponse("Failed to send message.", { status: 500 })
  }
}

Finally, you can send the message to youremail using transporter.sendMail() and return the success response to your client side. Don’t forget to include the await keyword.

import { NextResponse } from "next/server";
import nodemailer from "nodemailer";

const user = process.env.EMAIL;
const pass = process.env.PASSWORD;

export async function POST(request: Request) {
  try {
    const { name, email, message } = await request.json();

    const transporter = nodemailer.createTransport({
      service: "zoho",
      host: "smtpro.zoho.in",
      port: 465
      secure: true,
      auth: {
        user,
        pass,
      },
    });

    const mailOptions = {
      from: "user",
      to: "the-email-you-want-to-receive-the-message",
      subject: "New message from your-website",
      text: `Name: ${name}\nEmail: ${email}\nMessage: ${message}`,
    };

    await transporter.sendMail(mailOptions);

    return NextResponse.json(
      { message: "Message sent successfully" },
      { status: 200 },
    );
  } catch (error) {
    return new NextResponse("Failed to send message.", { status: 500 })
  }
}

That’s all we need for the API route. We can safely use it in our client side.

Client Side

I won’t go into detail for the client side, but I will include a source code for you.

For your reference, I use Shadcn UI Form to implement the contact form for the client side. If you still haven’t, you should check out Shadcn UI for its beautiful and well-designed ready-to-use React components.

If you use Shadcn UI Form, you can use the code below for your onSubmit function. Otherwise, you might need to adjust a little bit to handle form submission.

I use Axios to perform a POST request. It is a promise based HTTP client for the browser and node.js. It is simple to use.

async function onSubmit(values: z.infer<typeof formSchema>) {
    try {
      await axios.post("/api/contact", {
        name: values.name,
        email: values.email,
        message: values.message,
      });
      form.reset();
      toast("Message received. I will contact you as soon as I can.");
    } catch (error) {
      toast.error("Failed to send message. Please try again.");
    }
  }

Thank you so much for reading this post, and I’d love to hear your thoughts! Feel free to share your experiences and recommend a better approach in the comment below.

If you like the post and want to support me, you can clap the post or buy me a coffee.

If you need a frontend developer for your web development project, contact me.

Stackademic 🎓

Thank you for reading until the end. Before you go:


메타데이터
post_id
6730f2a658df
slug
step-by-step-integrating-nodemailer-for-email-functionality-in-next-js-6730f2a658df
url
https://blog.stackademic.com/step-by-step-integrating-nodemailer-for-email-functionality-in-next-js-6730f2a658df
canonical_url
https://blog.stackademic.com/step-by-step-integrating-nodemailer-for-email-functionality-in-next-js-6730f2a658df
author_url
https://medium.com/@evanch98
status
ok
fetched_at
2026-06-20 20:29:01