Sending Emails in NextJs via Nodemailer API

Sheraz ManzoorSheraz Manzoor
4 min read

Sending emails is a common requirement in many web applications, whether it's for user registration, password resets, notifications, newsletters or other purposes. In this blog detailed post, I'll tell you how to send emails in a Next.js application using Nodemailer, a popular Node.js library for sending emails.

Why use nodemailer?

Nodemailer is a robust and easy-to-use library that supports various email transport methods, including SMTP, Gmail, and more. It's highly configurable and can be used to send HTML emails, attachments, and even template-based emails. And the most important thing, it is free!!

Setting Up Your Next.js Project

After setting up your nextjs projects install the nodemailer library: npm install nodemailer If you are using typescript like me, then you will also need to install it within its types: npm i --save-dev @types/nodemailer

Configure Nodemailer

Next, configure nodemailer and export a function called sendMail or whatever is best fit for you. Here is complete code of Nodemailer configuration.

lib/send-mail.ts

'use server';
import nodemailer from 'nodemailer';
const SMTP_SERVER_HOST = process.env.SMTP_SERVER_HOST;
const SMTP_SERVER_USERNAME = process.env.SMTP_SERVER_USERNAME;
const SMTP_SERVER_PASSWORD = process.env.SMTP_SERVER_PASSWORD;
const SITE_MAIL_RECIEVER = process.env.SITE_MAIL_RECIEVER;
const transporter = nodemailer.createTransport({
  service: 'gmail',
  host: SMTP_SERVER_HOST,
  port: 587,
  secure: true,
  auth: {
    user: SMTP_SERVER_USERNAME,
    pass: SMTP_SERVER_PASSWORD,
  },
});

export async function sendMail({
  email,
  sendTo,
  subject,
  text,
  html,
}: {
  email: string;
  sendTo?: string;
  subject: string;
  text: string;
  html?: string;
}) {
  try {
    const isVerified = await transporter.verify();
  } catch (error) {
    console.error('Something Went Wrong', SMTP_SERVER_USERNAME, SMTP_SERVER_PASSWORD, error);
    return;
  }
  const info = await transporter.sendMail({
    from: email,
    to: sendTo || SITE_MAIL_RECIEVER,
    subject: subject,
    text: text,
    html: html ? html : '',
  });
  console.log('Message Sent', info.messageId);
  console.log('Mail sent to', SITE_MAIL_RECIEVER);
  return info;
}

In the above file, we set up Nodemailer with Gmail's SMTP service and create a sendEmail function that sends an email using the provided options. NOTE: You will need to generate an app password for implementing nodemailer. You can generate this app password in manage account settings of your google account, but you will need to enable two-step-verification first! Use that app password as your nodemailer SMTP_SERVER_PASSWORD, for username, write the You Gmail address.

All set, now add .env.local because we cannot expose our passwords or other sensitive information:

SMTP_SERVER_USERNAME=your-email-address
SMTP_SERVER_PASSWORD=your-app-password
SMTP_SERVER_HOST=email-smtp.us-east-1.amazonaws.com
SITE_MAIL_RECIEVER=mail-receiver email

Send FormData via nodemailer

Now lets run our function to send formData to my email:

'use client';
import { useForm } from 'react-hook-form';
import { Form, FormField, FormControl, FormItem, FormMessage } from '../ui/form';
import { Input } from '../ui/input';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { Textarea } from '../ui/textarea';
import { sendMail } from '@/lib/send-mail';
import { toast } from 'sonner';
import { Button } from '../ui/button';
const contactFormSchema = z.object({
  name: z.string().min(2, { message: 'Please Enter Your Name' }),
  email: z.string().email({ message: 'Please Enter a Valid Email Address' }),
  message: z
    .string()
    .min(10, { message: 'Please make sure your message is at least 10 characters long.' }),
});
export default function ContactForm() {
  const form = useForm<z.infer<typeof contactFormSchema>>({
    resolver: zodResolver(contactFormSchema),
    defaultValues: {
      name: '',
      email: '',
      message: '',
    },
  });
  const isLoading = form.formState.isSubmitting;
  const onSubmit = async (values: z.infer<typeof contactFormSchema>) => {
    const mailText = `Name: ${values.name}\n  Email: ${values.email}\nMessage: ${values.message}`;
    const response = await sendMail({
      email: values.email,
      subject: 'New Contact Us Form',
      text: mailText,
    });
    if (response?.messageId) {
      toast.success('Application Submitted Successfully.');
    } else {
      toast.error('Failed To send application.');
    }
  };
  return (
    <Form {...form}>
      <form
        className="grid grid-cols-3 items-center p-4 lg:p-6"
        onSubmit={form.handleSubmit(onSubmit)}
      >
        <div className="col-span-3 flex flex-col gap-4 lg:col-span-3 lg:gap-6">
          <h2 className="lg:text-xl">Enter Your Good Name Here:</h2>
          <FormField
            control={form.control}
            name="name"
            render={({ field }) => (
              <FormItem>
                <FormControl>
                  <Input placeholder="John Doe" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <h2 className="lg:text-xl">Enter Your Email Address:</h2>
          <FormField
            control={form.control}
            name="email"
            render={({ field }) => (
              <FormItem>
                <FormControl>
                  <Input placeholder="john@example.com" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <h2 className="lg:text-xl">Enter Your Message Here:</h2>
          <FormField
            control={form.control}
            name="message"
            render={({ field }) => (
              <FormItem>
                <FormControl>
                  <Textarea
                    {...field}
                    placeholder="My question is which framework do you prefer to use?"
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <Button disabled={isLoading}>{isLoading ? 'Sending.....' : 'Send'}</Button>
        </div>
      </form>
    </Form>
  );
}

The above is a simple contact form, when form submission is successful it will show a success toast otherwise an error toast.

Conclusion

Sending emails in a Next.js application is straightforward with Nodemailer. By following the steps outlined in this blog post, you can easily integrate email functionality into your Next.js projects, whether for contact forms, notifications, newsletters or other purposes. Give it a try and see how it can enhance your application's communication capabilities!

Feel free to ask questions if you have any. Please leave you feedback as well.

0
Subscribe to my newsletter

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

Written by

Sheraz Manzoor
Sheraz Manzoor

I am an experienced Frontend Developer currently working at Infinity Devs as a MERN Stack Developer. With a deep passion for creating intuitive and dynamic web applications, I specialize in technologies like React, Next.js, Typescript, zod, SaaS and Tailwind CSS. I pride myself on delivering clean, efficient, and responsive designs that not only meet but exceed client expectations. In my career, I have worked on everything from tiny websites for small businesses to complete custom web applications. With such a strong understanding of client needs, I utilize my own technical capabilities to create new solutions. By making my user experiences better or performance faster Key Skills: -Frontend Technologies: React, Next.js, HTML, CSS, JavaScript, Tailwind CSS -Version Control: Git, GitHub -Responsive Design: Mobile-first development, cross-browser compatibility -Collaboration: Excellent communication skills, experience in agile environments Professional Approach: -Shared Ownership: I believe in collaborative effort and shared responsibility to ensure the success of every project. -Rapid Execution: Efficiently managing time and resources to deliver quality work promptly -Show and Tell: Regular updates and transparency with clients to ensure alignment and satisfaction -Bias for Action: Prioritizing proactive measures to tackle challenges head-on -Systematic Approach: Methodical planning and execution to maintain high standards -Design Thinking: Emphasizing empathy and creativity to solve complex problems and deliver user-centric solutions Interests: When I’m not coding, you can find me exploring the latest in tech, reading about advancements in AI, or enjoying a good book. I also have a keen interest in photography and love capturing moments in nature.