Site icon Mailtrap

EmailJS React: How to Send Emails From a Contact Form Without a Backend

In this EmailJS React tutorial, I will show you how to send emails from your React contact form or app via EmailJS, as well as some alternatives.

Note that I’ll use a 3rd party email service provider since EmailJS doesn’t have built-in sending functionality. For this, I’ll go with Mailtrap Email Delivery Platform, which offers a reliable SMTP and email API with high deliverability rates by design.

Feel free to skip ahead by using one of the following jump links:

Disclaimer: Our developers have written and checked every line of code in this article.

Ready to deliver your emails?
Try Mailtrap for Free

Install and configure EmailJS

EmailJS is a service that allows you to send emails directly from client-side applications without needing a backend. 

Here’s what you need to do:

Before integrating EmailJS in your project, you need to create a free account. For demoing purposes, you can use the free tier. However, if you want to send attachments, you need to have at least a Personal Plan subscription.

As you’ve signed up, navigate to the Notifications section in the account tab and add an email with the same domain as your Mailtrap’s account.

Next, go to Email Services and select Mailtrap as your email service provider (ESP)

Then, configure the service by providing the following details:

Username and Password: Find your credentials by going to your Mailtrap dashboard and then navigating to Sending Domains > Integration > SMTP. (if you can’t find your API key there, go to Settings > API Tokens)

Service ID: A unique identifier for this service. You can name it something like “mailtrap_service” or any name you like.

Email Feature – Select “Sending” from the dropdown menu.

Note: If you experience issues when trying to configure Mailtrap in EmailJS, uncheck “Send test email to verify configuration”.

Go to Email Templates and create a new template. Add placeholders like {{name}}, {{email}}, and {{{html_message}}} in the email body where the user input will go. When the emails are sent, these get replaced with the sender’s name, email and message HTML content accordingly. 

On the right sidebar, set your ‘From Email’ field to use your Mailtrap Account’s email domain, otherwise, Mailtrap will block the SMTP requests if they aren’t sent from the same domain. Also, do not tick the “Use Default Email Address” box.

Finally, navigate to the account section → API Keys, and save your Public Key. 

All said and done, you need to have 2 IDs (Service and Template ID) and 1 Public Key.

Create React contact form

First, to create a working directory and set up everything to use React without much fuss, Vite is the optimal solution. It provides a quick and simple way to set up a preconfigured React project using a React template. You can install it via:

npm:

npm create vite@latest emailjs-react --template react

Or yarn:

yarn create vite emailjs-react --template react

In the directory, create an src folder to store the source code, that is, HTML and JavaScript files:

mkdir src

In the src folder, delete all the unnecessary files coming with the default React template since we only need App.jsx and main.jsx files:

Also, since we won’t use CSS for this example, remove the following line in main.jsx:

import './index.css'

Similarly, in the App.jsx remove all imports and all the code in the App function:

function App() {}

export default App;

Now, we have successfully configured everything we need to create a contact form in React, so let’s get to it. First, create a components folder and a contact-us.jsx file inside the form, just like so:

In the contact-us.jsx file, create a React Component for the form, which we will connect to EmailJS later on. We’ll also add some basic styles so that inputs are positioned properly:

const ContactUs = () => {
  return (
    <form
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 12,
        width: 300,
      }}
    >
      <label>Name</label>
      <input type="text" name="name" required />

      <label>Email</label>
      <input type="email" name="email" required />

      <label>Message</label>
      <textarea name="html_message" required></textarea>

      <button type="submit">Send</button>
    </form>
  );
};

export default ContactUs;

Important: Make sure all input names match the names you use in your EmailJS template.

Finally, let’s connect the component so that it’s rendered when we run our React application and center the form on the page:

import ContactUs from "./components/contact-us";

function App() {
  return (
    <div style={{ display: "flex", justifyContent: "center" }}>
      <ContactUs />
    </div>
  );
}

export default App;

To verify that the form is being correctly rendered when we run the application, we can use:

npm:

npm run dev

Or yarn:

yarn dev

This is how your terminal should look like:

Click on the local host link to open the page, which should show your rendered form:

Want to add an additional layer of security to your React contact form or web app? Consider adding an email validation logic to your sign-up form, which will protect you against spammers and bots.

Send email in React using EmailJS

In this step, we’ll add EmailJS and make the form send emails on click using the data filled in. 

First, we need to store Public Key, Service ID and Template ID somewhere. With Vite, we can do it safely using environment variables. The keys would still be exposed to the client, but it’s safer than using keys directly in the code.

So let’s create a .env.local file and add the mentioned keys and IDs there from the EmailJS dashboard:

VITE_PUBLIC_KEY=your_public_key
VITE_TEMPLATE_ID=your_template_id
VITE_SERVICE_ID=your_service_id

Important: Environment variables in Vite must have a VITE_ prefix for them to be imported correctly in the code.

Let’s install the EmailJS SDK so that we can use it in the React code.

npm:

npm install @emailjs/browser

yarn:

yarn add @emailjs/browser

Now we have to make sure EmailJS is being properly initialized in the React application. To do this, modify the App.js file, add the emailjs.init call, and pass the environment variable that corresponds with the Public Key

The code below initializes EmailJS as soon as the React application is mounted on the page:

import { useEffect } from "react";
import emailjs from "@emailjs/browser";

import ContactUs from "./components/contact-us";

function App() {
  useEffect(() => {
    emailjs.init(import.meta.env.VITE_PUBLIC_KEY);
  }, []);

  return (
    <div style={{ display: "flex", justifyContent: "center" }}>
      <ContactUs />
    </div>
  );
}

export default App;

Note: 

If you want your emails to strictly behave as plain-text, you can replace the triple brackets with double brackets like {{message}} in your EmailJS dashboard when editing the template. 

Additionally, make sure to replace the html_message name in the message field with message in your index.html file:

<label>Message</label>
<textarea name="message" required></textarea>

Send HTML email

To send HTML email, open contact-us.jsx file and copy/paste the following code inside it:

import { useRef } from "react";
import emailjs from "@emailjs/browser";

const ContactUs = () => {
  const form = useRef();

  const sendEmail = async (e) => {
    e.preventDefault();

    try {
      const response = await emailjs.sendForm(
        import.meta.env.VITE_SERVICE_ID,
        import.meta.env.VITE_TEMPLATE_ID,
        form.current
      );
      console.log("Email was successfully sent!", response);
    } catch (error) {
      console.error("Failed to send an email", error);
    }
  };

  return (
    <form
      ref={form}
      onSubmit={sendEmail}
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 12,
        width: 300,
      }}
    >
      <label>Name</label>
      <input type="text" name="name" required />

      <label>Email</label>
      <input type="email" name="email" required />

      <label>Message</label>
      <textarea name="html_message" required></textarea>

      <button type="submit">Send</button>
    </form>
  );
};

export default ContactUs;

Run the app similarly and open the browser. Additionally, you could open the developer console to see the logs. If everything was set up correctly, after submitting the form, you should see something like this.

You should also receive an email in your Mailtrap Email Logs accordingly.

Send email with attachment

Open the Attachments tab in your selected template, then click Add Attachment, select Form File Attachment, and enter the parameter name that you’re going to use later in your HTML code. Once you’re done, don’t forget to click Apply and Save the template.

Next, let’s add a new input in the React form that will be responsible for file selection. Here’s a code snippet you can insert into the contact-us.jsx file:

import { useRef } from "react";
import emailjs from "@emailjs/browser";

const ContactUs = () => {
  const form = useRef();

  const sendEmail = async (e) => {
    e.preventDefault();

    try {
      const response = await emailjs.sendForm(
        import.meta.env.VITE_SERVICE_ID,
        import.meta.env.VITE_TEMPLATE_ID,
        form.current
      );
      console.log("Email was successfully sent!", response);
    } catch (error) {
      console.error("Failed to send an email", error);
    }
  };

  return (
    <form
      ref={form}
      onSubmit={sendEmail}
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 12,
        width: 300,
      }}
    >
      <label>Name</label>
      <input type="text" name="name" required />

      <label>Email</label>
      <input type="email" name="email" required />

      <label>Message</label>
      <textarea name="html_message" required></textarea>

      <input type="file" name="my_file" />

      <button type="submit">Send</button>
    </form>
  );
};

export default ContactUs;

As you see, the only thing that changed is that we added a new input with my_file name. The attachment is added to the sent email with the same file name as the file we selected in the input. 

Important: Make sure the input’s name matches the name you provided in the attachments tab in your template, similarly to how we did it on the previous steps.

When you run your React app and open it in the browser, you should see a form, now with a new file select field, which would send the data that you typed in the inputs on submit, as well as the attachment you selected.

And here it is in the Mailtrap Email Logs:

Send email to multiple recipients

To send emails to multiple recipients, let’s go to the template and add {{carbon_copy}} in the Bcc field. This way the email would be sent to the recipients listed in the Bcc field. You can use static emails for the field, to send to some specific recipients. 

For this example, we’ll use a template value so that we can dynamically pass the recipients by mentioning them in the form.

And in contact-us.jsx, add a new receivers field to the React form:

import { useRef } from "react";
import emailjs from "@emailjs/browser";

const ContactUs = () => {
  const form = useRef();

  const sendEmail = async (e) => {
    e.preventDefault();

    try {
      const response = await emailjs.sendForm(
        import.meta.env.VITE_SERVICE_ID,
        import.meta.env.VITE_TEMPLATE_ID,
        form.current
      );
      console.log("Email was successfully sent!", response);
    } catch (error) {
      console.error("Failed to send an email", error);
    }
  };

  return (
    <form
      ref={form}
      onSubmit={sendEmail}
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 12,
        width: 300,
      }}
    >
      <label>Name</label>
      <input type="text" name="name" required />

      <label>Email</label>
      <input type="email" name="email" required />

      <label>Message</label>
      <textarea name="html_message" required></textarea>

      <label>Recipients</label>
      <input type="text" name="carbon_copy" />

      <input type="file" name="my_file" />

      <button type="submit">Send</button>
    </form>
  );
};

export default ContactUs;

Important: Make sure the new input name matches the name you use in your EmailJS template for Bcc.

If you want to learn more about Cc and Bcc, be sure to check out our dedicated article. 👀

Send emails using SMTP

If EmailJS does not meet your security requirements or if you need more fluidity with creating content emails dynamically in code (which EmailJS doesn’t fully allow since it’s template-based), consider such backend-based solutions as Nodemailer (SMTP-based).

Nodemailer is probably one of the most popular solutions for this since it makes sending emails from Node.js applications a breeze.

Here’s what you need to do to use it:

Step 1. Create a directory and a new folder with any name that you want:

mkdir nodemailer-mailtrap
cd nodemailer-mailtrap

In the directory, let’s create an src folder where we’ll store our source code:

mkdir src

Step 2. Install the dependencies using npm or yarn:

npm:

npm init -y
npm install nodemailer dotenv

yarn:

yarn init -y
yarn add nodemailer dotenv

Step 3. Create a .env file and fill it with the Mailtrap credentials:

MAILTRAP_USER=your_smtp_user
MAILTRAP_PASS=your_smtp_pass

Step 4. Add email-sending functionality

When the dependencies are installed, create an index.js file in the src folder and copy/paste the following code inside it:

require("dotenv").config();

const nodemailer = require("nodemailer");

const transporter = nodemailer.createTransport({
  host: "live.smtp.mailtrap.io",
  port: 587,
  auth: {
    user: process.env.MAILTRAP_USER,
    pass: process.env.MAILTRAP_PASS,
  },
});

const mailOptions = {
  from: "your-email@your-domain.com",
  to: "recipient@example.com",
  subject: "Test Email",
  text: "Hi from Mailtrap!",
};

transporter.sendMail(mailOptions, (error, info) => {
  if (error) {
    console.log("Error:", error);
  } else {
    console.log("Email sent:", info.response);
  }
});

Run the code using the command below:

node src/index.js

Send HTML email

To send an HTML email, simply use the html property instead of text property, just like so:

require("dotenv").config();

const nodemailer = require("nodemailer");

const transporter = nodemailer.createTransport({
  host: "live.smtp.mailtrap.io",
  port: 587,
  auth: {
    user: process.env.MAILTRAP_USER,
    pass: process.env.MAILTRAP_PASS,
  },
});

const mailOptions = {
  from: "your-email@your-domain.com",
  to: "recipient@example.com",
  subject: "Test Email",
  html: `
    <h1>Hi from Mailtrap!</h1> 
    <p>This is a test email sent from Node.js (Nodemailer) using Mailtrap.</p>
  `,
};

transporter.sendMail(mailOptions, (error, info) => {
  if (error) {
    console.log("Error:", error);
  } else {
    console.log("Email sent:", info.response);
  }
});

Send emails using API

For the email API approach, we’ll use the official Mailtrap SDK. The library is regularly maintained and updated by a team of developers and lets you automate your email-sending process.

First, create a new folder and the directory:

mkdir mailtrap-sdk
cd mailtrap-sdk

In the directory, create an src folder where we’ll store our source code:

mkdir src

Next, let’s install the dependencies using:

npm:

npm init -y
npm install mailtrap dotenv

Or yarn:

yarn init -y
yarn add mailtrap dotenv

Now, to store the credentials safely in the application, create a .env file and fill it with the Mailtrap API Token:

MAILTRAP_TOKEN=your_token

Once you install the dependencies, create an index.js file in the src folder and paste the following code inside:

require("dotenv").config();

const { MailtrapClient } = require("mailtrap");

const TOKEN = process.env.MAILTRAP_TOKEN;
const SENDER_EMAIL = "sender@freelance.mailtrap.link";
const RECIPIENT_EMAIL = "artem15052003@gmail.com";

const client = new MailtrapClient({ token: TOKEN });

const sender = { name: "Mailtrap Test", email: SENDER_EMAIL };
const recipient = { email: RECIPIENT_EMAIL };

const sendEmail = async () => {
  try {
    const response = await client.send({
      from: sender,
      to: [recipient],
      subject: "Hi from Maitrap!",
      text: "Hi from Mailtrap! This is a test message",
    });
    console.log(response);
  } catch (error) {
    console.error(error);
  }
};

sendEmail();

Run the code using:

node src/index.js

Send HTML email

For sending HTML emails we use html property instead of text property:

require("dotenv").config();

const { MailtrapClient } = require("mailtrap");

const TOKEN = process.env.MAILTRAP_TOKEN;
const SENDER_EMAIL = "sender@freelance.mailtrap.link";
const RECIPIENT_EMAIL = "artem15052003@gmail.com";

const client = new MailtrapClient({ token: TOKEN });

const sender = { name: "Mailtrap Test", email: SENDER_EMAIL };
const recipient = { email: RECIPIENT_EMAIL };

const sendEmail = async () => {
  try {
    const response = await client.send({
      from: sender,
      to: [recipient],
      subject: "Hi from Maitrap!",
      html: `<h1>Hi from Mailtrap! This is a test message</h1>`,
    });
    console.log(response);
  } catch (error) {
    console.error(error);
  }
};

sendEmail();

Test email and email sending on staging

With a lot of code comes great responsibility, so you need to make sure it’s error-free and that your HTML/CSS designs are rendered correctly. You also need to test whether your emails are hitting spam filters and check if your domain isn’t getting blacklisted.

The solution you can use for all of the above is Mailtrap Email Sandbox, another inseparable part of Mailtrap Email Delivery Platform.

With Mailtrap Email Sandbox, you can inspect the HTML/CSS of your emails and easily spot and fix any errors in the code. This way, your messages will look the way you intend them to, whether they’re opened in Outlook, Thunderbird, even an iPhone.

Additionally, you can check both HTML and text versions of your emails, inspect the source code, and more.

Then, once everything looks good, move on to checking your spam score. By keeping it below 5, you prevent a significant amount of potential email deliverability issues your project/app could face in production.

So, without further ado, let me show you how easy to use Mailtrap Email Sandbox is!

EmailJS

Here, you just need to switch from sending to email testing in your EmailJS dashboard. Simply update your Username and Password, switch the email feature from Sending to Testing, and then click Update Service

SMTP

To start testing your emails, follow these steps:

const transport = nodemailer.createTransport({
  host: "sandbox.smtp.mailtrap.io",
  port: 2525,
  auth: {
    user: "1a2b3c4d5e6f7g",
    pass: "1a2b3c4d5e6f7g"
  }
});

API

If you want to integrate Mailtrap API for testing, automation, and testing automated sequences, copy/paste the code snippet below:

require("dotenv").config();

const { MailtrapClient } = require("mailtrap");

const client = new MailtrapClient({
  token: process.env.MAILTRAP_API_TOKEN,
  testInboxId: Number(process.env.TEST_INBOX_ID),
  accountId: Number(process.env.ACCOUNT_ID),
});

const sendTestEmail = async () => {
  try {
    const response = await client.testing.send({
      from: { email: "no-reply@your-domain.com", name: "Your App" },
      to: [{ email: "test@example.com" }],
      subject: "Test Email via API",
      text: "This is a test email sent via Mailtrap API.",
    });
    console.log("Test email sent via API SDK:", response);
  } catch (error) {
    console.error("Error sending email via API:", error);
  }
};

sendTestEmail();

Now, let’s create a .env file and fill it with the Mailtrap API Token. This way, the credentials can be stored safely in the application: 

MAILTRAP_API_TOKEN=your_api_token_here
TEST_INBOX_ID=your_inbox_id
ACCOUNT_ID=your_account_id

You can find your test inbox ID by checking the URL of the open sandbox page, and you can find your account ID by going to account settings in the Mailtrap dashboard.

Further reading:

Exit mobile version