Published: Mar 9, 2024
Last Updated: Aug 10, 2024
Next.js Email Sending with App Router and EmailJS
Ready to take your Next.js skills to the next level? In our last post, we mastered the art of integrating EmailJS with Next.js using the Page Router approach. But why stop there? Today, we’re diving into something even more powerful – the App Router approach. Whether you're a regular here or just stumbled upon our blog, you're in for an electrifying journey! We’re about to supercharge our email-sending capabilities in Next.js and trust me, you won't want to miss this.
The inspiration for this post hit me like a lightning bolt when Next.js announced the App Route Get Stable feature. As I migrated my website to tap into the full potential of the App Route, I was blown away by the new Server Actions – they're game-changing when it comes to handling forms on the server. I couldn’t wait to share this with you, so buckle up! I'll be your guide through this thrilling integration of EmailJS into Next.js. If you’re new to the Next.js App Route, no worries – a quick look at the Next.js Docs will get you up to speed.
If you haven’t set up your EmailJS account yet, I’ve got you covered with easy steps in a previous post. Today, we’re exploring two exciting methods to integrate EmailJS into Next.js: using the SDK and the API. And guess what? We’ll be reusing the same form and style from before, so it’ll be a smooth ride.
Got your Next.js app ready? Let’s dive in and make some magic happen!
Prerequisites
Before you start, make sure to have the following:
- Basic knowledge of Next.js.
- Node.js and npm installed: download from Node.js official website.
- EmailJS account: if you don't have one, refer to my previous blog post for setup instructions.
- Basic Understanding of JavaScript and React.
- Set Up a Next.js App: Follow the Next.js documentation.
Integrating EmailJS with the SDK
In the Next.js App Route, components are set as React Server Components by default. This comes with a catch – we can't use React hooks directly in Server Components, which means we’ll need to tap into Client Components for this integration. But don’t worry, it’s easier than it sounds!
When working with the SDK, we’ll rely on the useRef
React hook, which is only available in Client Components. This little tweak ensures everything runs smoothly.
Install the EmailJS SDK
Just run the command below, and we’ll be all set to start coding:
npm install @emailjs/browser@4.4.1
# Or
yarn add @emailjs/browser@4.4.1
Note: When following this guide, it's important to use the specified versions of the packages to avoid potential issues. If you choose to use different versions, please refer to the package changelogs to ensure compatibility and prevent any unexpected problems.
Create the Form Component
Now, let’s set up our form. Create a components/Form.tsx
file and paste the following code into it:
"use client";
import React, { useRef } from "react";
import emailjs from "@emailjs/browser";
import styles from "./Contact.module.css";
export const Form = ({ env }: { env: any }) => {
const form = useRef<HTMLFormElement>(null);
const sendEmail = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (
!env.EMAILJS_SERVICE_ID ||
!env.EMAILJS_TEMPLATE_ID ||
!env.EMAILJS_PUBLIC_KEY ||
!form.current
)
throw new Error(
"One of the sendForm params (serviceID, templateID, form, publicKey) is missing. Please check your environment variables"
);
emailjs
.sendForm(
env.EMAILJS_SERVICE_ID,
env.EMAILJS_TEMPLATE_ID,
form.current,
env.EMAILJS_PUBLIC_KEY
)
.then(
(result) => {
alert(result.text);
},
(error) => {
alert(error.text);
}
);
};
return (
<form ref={form} onSubmit={sendEmail} className={styles.form}>
<div className={styles.formGroup}>
<label className={styles.label} htmlFor="user_name">
Name
</label>
<input type="text" id="user_name" name="user_name" required />
</div>
<div className={styles.formGroup}>
<label className={styles.label} htmlFor="email">
Email
</label>
<input type="email" id="email" name="email" required />
</div>
<div className={styles.formGroup}>
<label className={styles.label} htmlFor="message">
Message
</label>
<textarea rows={8} id="message" name="message" required />
</div>
<button className={styles.button} type="submit">
Send
</button>
</form>
);
};
I won’t rehash all the details of the code here, as we covered it thoroughly in our previous post. The main update is that we’ve moved the form into a separate file. This step is essential because, as we discussed earlier, we need to use Client Components with the use client
directive.
Next, create a components/Contact.module.css
file for styling. You can find the required styles in the link below, which refers to the previous blog post:
Link to the previous blog post
Add the Form to the Contact Page
Create or open app/contact/page.tsx
and import the Form component:
import type { Metadata } from "next";
import React from "react";
import { Form } from "../components/Form";
export const metadata: Metadata = {
title: "Contact Us",
description: "Contact us page",
};
const ContactUs = () => (
<>
<h1>Contact Us</h1>
<Form
env={{
EMAILJS_SERVICE_ID: process.env.EMAILJS_SERVICE_ID || "",
EMAILJS_TEMPLATE_ID: process.env.EMAILJS_TEMPLATE_ID || "",
EMAILJS_PUBLIC_KEY: process.env.EMAILJS_PUBLIC_KEY || "",
}}
/>
</>
);
export default ContactUs;
This is how to create a basic page using the Next.js App Directory approach. Also, ensure your environment variables are set before testing.
Set Up Environment Variables
First, create a .env
file in the root level of your project and copy the following environment variables into it:
EMAILJS_SERVICE_ID=
EMAILJS_TEMPLATE_ID=
EMAILJS_PUBLIC_KEY=
To retrieve the environment variables from the EmailJS dashboard you can refer to my previous blog post in the link below:
Link to the previous blog post
To get your application up and running, use the following commands:
npm run dev
You can view the contact page at:
http://localhost:3000/contact
In the next section, I'll walk you through the second approach using the EmailJS API.
Approach with EmailJS API
In this section, we’ll dive into using the EmailJS API along with Next.js Server Actions to handle API requests on the server.
Update .env
File
You’ll also need to add an additional environment variable called EMAILJS_ACCESS_TOKEN
(Private Key of the account
), which you can find in the 'Account' section of your EmailJS dashboard.
EMAILJS_SERVICE_ID=
EMAILJS_TEMPLATE_ID=
EMAILJS_PUBLIC_KEY=
EMAILJS_ACCESS_TOKEN=
Enable API Access
In the EmailJS dashboard, go to Account > Security
and check 'Allow EmailJS API for non-browser applications.'
Set Up the Contact Page
Create a Contact route in app/contact-2/page.tsx
and copy the following
import styles from "../components/Contact.module.css";
export default function ContactPage() {
const sendEmail = async (fromData: FormData) => {
"use server";
const fullname = fromData.get("fullname");
const email = fromData.get("email");
const message = fromData.get("message");
if (!fullname && !email && !message)
return {
status: 400,
message: "Please fill out all fields",
};
try {
const res = await fetch("https://api.emailjs.com/api/v1.0/email/send", {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify({
service_id: process.env.EMAILJS_SERVICE_ID,
template_id: process.env.EMAILJS_TEMPLATE_ID,
user_id: process.env.EMAILJS_PUBLIC_KEY,
accessToken: process.env.EMAILJS_ACCESS_TOKEN,
template_params: {
fullname,
email,
message,
},
}),
});
if (res.ok) {
return {
status: res.status,
message: "Email sent successfully",
};
}
return {
status: 500,
message: "Something went wrong! Email not sent",
};
} catch (error) {
return {
status: 500,
message: "Something went wrong! Email not sent",
};
}
};
return (
<form action={sendEmail} className={styles.form}>
<div className={styles.formGroup}>
<label className={styles.label} htmlFor="fullname">
Full name
</label>
<input type="text" id="fullname" name="fullname" required />
</div>
<div className={styles.formGroup}>
<label className={styles.label} htmlFor="email">
Email
</label>
<input type="email" id="email" name="email" required />
</div>
<div className={styles.formGroup}>
<label className={styles.label} htmlFor="message">
Message
</label>
<textarea rows={8} id="message" name="message" required />
</div>
<button className={styles.button} type="submit">
Send
</button>
</form>
);
}
In this snippet, I’ve streamlined form management in Next.js by moving the logic into the server action function, sendEmail
. This approach eliminates the need for useState
and manages the API call for sending emails directly on the server side. It ensures that sensitive data is handled securely and includes basic form validation.
With this setup, you’re all set to send emails from your Next.js app!
To get your application up and running, use the following commands:
npm run dev
You can view the contact page at:
http://localhost:3000/contact-2
Conclusion
In summary, our exploration of integrating EmailJS with Next.js using the App Router and Server Actions has shown how to implement seamless email functionality. Whether you're an experienced developer or new to Next.js, you can choose between the SDK and API methods based on your project requirements. For additional guidance, refer to the Next.js documentation and enjoy enhanced development with these powerful email capabilities. Thanks for joining us—feel free to reach out with any questions or feedback. Happy coding!