Sending Emails in NextJs via Nodemailer API
Easy guide to send emails in a Nextjs projects using nodemailer
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.