E-mail service in NextJs and nodemailer

Oussama ChahidiOussama Chahidi
4 min read

Introduction

In today’s digital landscape, email remains a cornerstone of communication, both for personal use and business interactions. With a myriad of email services available, Gmail stands out as one of the most popular choices, thanks to its user-friendly interface and robust features. But what if you want to harness the power of Gmail programmatically? This is where NextJs and Nodemailer come into play.

NextJs, a powerful React framework, enables developers to build fast and dynamic web applications with ease. When paired with Nodemailer, a versatile module for NodeJs, you can create custom email solutions that leverage Gmail’s capabilities. In this blog post, we’ll explore how to integrate Gmail with NextJs and Nodemailer, allowing you to send emails effortlessly from your web application. Whether you're looking to enhance user engagement, send notifications, or manage communications, this guide will provide you with the essential steps to get started.

Let’s dive in and unlock the potential of email in your NextJs applications !

Create a google email application

Since we gonna the gmail smtp, we need to create an application

1. Login to the google account you want to use , then click on the avatar icon and manage account settings button.
2. Go to Settings > turn on two steps verification
3. in the search bar, look for “App Password“ > create and application by giving it a name and a password will be generated, save that password cause you’ll see it for once.

Now we are done, with gmail , let’s jump to the code.

  1. Create a NextJs project and install nodemailer in it:
npm i nodemailer

Since we using TypeScript, we need to install the nodemailer types

npm i @types/nodemailer --dev
  1. Let’s put the mailer code

create an `.env` and put the USER and PASS values, then create
app > api > mailer > route.ts

// app/api/mailer/route.ts

import nodemailer from 'nodemailer';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const { to } = await request.json();

  // Create a transporter
  const transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 587,
    secure: false, // Use TLS
    auth: {
      user: process.env.NX_PUBLIC_EMAIL_USER,
      pass: process.env.NX_PUBLIC_EMAIL_PASS,
    },
  });


  // Set up email data
  const mailOptions = {
    from: process.env.NX_PUBLIC_EMAIL_USER,
    to,
    subject: "Subject Title",
    html: `HTML TEMPLATE`,
  };

  try {
    // Send mail
    await transporter.sendMail(mailOptions);

    transporter.verify((error, success) => {
      if (error) {
        console.error('Transporter verification failed:', error);
      } else {
        console.log('Server is ready to take our messages:', success);
      }
    });

    return NextResponse.json({ message: 'Email sent successfully' });
  } catch (error) {
    console.error(error);
    return NextResponse.json({ error: 'Failed to send email' }, { status: 500 });
  }
}

On the client side

import React, { useState } from 'react';
import {
  Button,
  Dialog,
  DialogClose,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
  Input,
  Label,
} from '@hirehub/shared';
import { z } from 'zod';
import { Controller, useForm } from 'react-hook-form';
import toast from 'react-hot-toast';

const formSchema = z.object({
  email: z.string().min(1).email(),
});



const InvitationModal = () => {
  const [isOpen, setIsOpen] = useState(false)
  const form = useForm<z.infer<typeof formSchema>>({});
  const {orgName} = useOrgStore()

  function onOpen() {
    setIsOpen(true)
  }

  function onClose() {
    setIsOpen(false)
    form.reset()
  }

  async function submit(values: z.infer<typeof formSchema>) {
    toast.loading("One moment please...", { id: "inviting" });

    try {
      const res = await fetch("/api/mailer", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          to: values.email,
        }),
      });

      if (!res.ok) {
        throw new Error('Network response was not ok');
      }

      toast.dismiss("inviting");
      toast.success("Email invitation has been sent");
      onClose()
    } catch (err) {
      toast.dismiss("inviting");
      console.error(err);
    }
  }


  return (
    <Dialog open={isOpen} onOpenChange={onClose}>
        <Button variant={'ghost'} onClick={onOpen}>Invite People</Button>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Invite People</DialogTitle>
        </DialogHeader>
        <form onSubmit={form.handleSubmit(submit)} className="mt-5">
          <div className="flex flex-col gap-4">
            <Label>Member E-mail</Label>
            <Controller
              name="email"
              control={form.control}
              render={({ field }) => (
                <Input
                  id="email"
                  className="col-span-3"
                  {...field}
                  placeholder="Enter the e-mail"
                />
              )}
            />
            {form.formState.errors.email && (
              <span className="text-red-500 text-sm">
                {form.formState.errors.email.message}
              </span>
            )}
          </div>
          <div className="flex flex-row items-center gap-3 justify-end mt-5">
            <Button variant={'outline'} onClick={onClose}>Cancel</Button>
            <Button>Invite</Button>
          </div>
        </form>
      </DialogContent>
    </Dialog>
  );
};

export default InvitationModal;

That’s it, if you try this . you will receive an email with the used template and from the used emaila

Conclusion

Integrating Gmail with NextJs and Nodemailer opens up a world of possibilities for enhancing your web applications. By leveraging these powerful tools, you can easily send automated emails, notifications, and user communications directly from your application. Throughout this guide, we explored the setup process, from configuring your Gmail account to crafting and sending emails using Nodemailer.

With this foundation, you can now build more interactive and engaging user experiences. Whether you're developing a contact form, a newsletter subscription, or any feature that requires email communication, the combination of Next.js and Nodemailer makes it straightforward and efficient.

As you continue to develop your application, consider exploring additional features like email templates, attachments, and more advanced configurations. Happy coding, and may your emails always land in the inbox !

1
Subscribe to my newsletter

Read articles from Oussama Chahidi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Oussama Chahidi
Oussama Chahidi

Hi, my name is oussama and i am a self-taught full stack javascript developer with interests in computers. I like the expend my knowledge and learn new things each day cause i always see the beauty in mystery.