Notification: 2 unread emails in the email app.

Published: Mar 9, 2024

Last Updated: Mar 9, 2024

Next.js Email Sending with App Router and EmailJS

Building on our recent exploration of integrating EmailJS with Next.js through the Page Route approach, today, we dive into another powerful technique – the App Router approach. If you've been following our journey, welcome back! If you're just joining us, no worries – you're in for a treat. In this post, we'll seamlessly extend our email-sending capabilities in Next.js, exploring the App Router method. So, fasten your seatbelts as we continue to elevate our Next.js game!

The inspiration for this blog post came when Next.js announced the App Route Get Stable feature. Upon migrating my website to leverage the App Route, I was particularly impressed by the new Server Actions and its effectiveness in handling forms on the server. Excited to share my experiences, I'll guide you through integrating EmailJS into Next.js. Ensure you have a basic understanding of the Next.js App Route – if not, check the NextJs Docs.

If you don't have an EmailJS account yet, you can follow the steps outlined in my earlier blog post. In this article, we'll explore two methods for integrating EmailJS into Next.js: using the SDK and the API. I'll be reusing the same form and style from the previous blog.

Assuming you already have a Next.js app set up, let's jump right in!

Approach with EmailJS SDK

In the Next.js App Route, components inside the app are React Server Components by default. This means we cannot use React hooks on the Server Components, necessitating the use of Client Components. Therefore, when using the SDK, we need to employ the useRef React hook, which is only allowed in Client Components.

To get started, install the EmailJS SDK using the following command:

SH
npm install @emailjs/browser

# Or

yarn add @emailjs/browser

Now, create a components/Form.tsx file and copy the code below into it:

TSX

"use client";

import React, { useRef } from "react";
import emailjs from "@emailjs/browser";
//You can find the style in my previous blog post
// https://www.ali-dev.com/blog/how-to-send-emails-from-nextjs-or-reactjs-without-the-backend-using-emailjs
import styles from "@/styles/Contact.module.css";

export const Form = () => {
  const form = useRef(null);

  const sendEmail = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (
      process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID &&
      process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID &&
      process.env.NEXT_PUBLIC_EMAILJS_USER_ID &&
      form.current
    ) {
      emailjs
        .sendForm(
          process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID,
          process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID,
          form.current,
          process.env.NEXT_PUBLIC_EMAILJS_USER_ID
        )
        .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 cover the entire code above as it was explained in detail in the previous blog post. The key difference is that I've moved the form to a separate file. This change is necessary because, as explained earlier, we have to use Client Components with the use client directive.

Now, let's import this component into the Contact page.

Create the Contact route if you haven't already (app/contact/page.tsx) and import the Form component:

TSX
import type { Metadata } from 'next';
import React, { useRef } from "react";
import emailjs from "@emailjs/browser";
import Head from "next/head";
import { Inter } from "next/font/google";
import styles from "@/styles/Contact.module.css";
import {Form} from "@/components/Form";
const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: 'Contact Us',
  description: 'Contact us page',


}

const ContactUs = () => (
    <>
      <div className={`${styles.main} ${inter.className}`}>
        <h1>Contact Us</h1>
        <Form />
      </div>
    </>
  );

export default ContactUs;

If you're familiar with the Next.js Page Route, you'll notice that creating pages differs from the Pages route. If you're new to App Route, I recommend checking the Next.js Docs. Make sure you have all the necessary environment variables before testing. To run your application, use the following commands:

SH
npm run dev

You can access the contact page via the following URL:

http://localhost:3000/contact

In the Next Section, I will explain the second approach using the EmailJs API.

Approach with EmailJS API

In this approach, we will be focusing on the EmailJs API and the NextJs Server Actions to execute the API on the server.

Before getting started, ensure you've set up a .env file with your necessary environment variables. If you haven't done this yet, create one and include the relevant details. For assistance in finding the necessary EmailJS environment variables, please consult the relevant section in my previous blog post. Additionally, you'll require an extra environment variable called accessToken. To locate it in your EmailJS dashboard, simply navigate to the 'Account' section where you can easily find it.

Next, it's essential to grant EmailJS API access for non-browser applications via the EmailJS dashboard. Simply navigate to your dashboard, then proceed to Account > Security. Scroll down to the API Settings section and ensure the 'Allow EmailJS API for non-browser applications' option is checked.

It's time to set up the Contact page. If you haven't done this yet, create the Contact route, for example, in the file app/contact/page.tsx. Don't forget to import the Form component for a smooth integration.

TSX
// You can find the mentioned style in my previous blog post.
// https://www.ali-dev.com/blog/how-to-send-emails-from-nextjs-or-reactjs-without-the-backend-using-emailjs
import styles from "./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.EMAIL_SERVICE_ID,
          template_id: process.env.EMAIL_TEMPLATE_ID,
          user_id: process.env.EMAIL_USER_ID,
          accessToken: process.env.EMAIL_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 (
    <main>
      <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>
    </main>
  );
}

In this snippet, I've optimized form management in Next.js by consolidating logic into the server action, sendEmail. This eliminates the need for useState and shifts the API call for sending emails to the server side. The function ensures secure handling of sensitive data and includes basic form validation.

Now, you should be ready to send emails from your Nextjs app!

Conclusion

In summary, our exploration of EmailJS integration with Next.js using the App Router and Server Actions provides seamless email functionality. Whether you're a seasoned developer or new to Next.js, choose between the SDK and API methods based on your project needs. Refer to Next.js Docs for guidance and enjoy elevated development with enhanced email capabilities. Thanks for joining us—questions or feedback? Reach out. Happy coding!