DEV Community

Cover image for reCaptcha verification with EmailJS
James Wallis
James Wallis

Posted on • Updated on • Originally published at wallis.dev

reCaptcha verification with EmailJS

This blog is part of a series where I document rebuilding a website that relies on HTML, CSS and Bootstrap in React.js using the Next.js framework to improve performance, reduce costs and increase my workflow for future changes.

The finished website: https://wallisconsultancy.co.uk
The source code: https://github.com/james-wallis/wallisconsultancy

What is EmailJS

In the previous blog I introduced EmailJS, a service designed to send emails on behalf of websites with no backend server, and added to the Wallis Consultancy React.js application that is being built.

What is reCaptcha

reCAPTCHA is a free service from Google that helps protect websites from spam and abuse. A “CAPTCHA” is a turing test to tell human and bots apart. It is easy for humans to solve, but hard for “bots” and other malicious software to figure out. By adding reCAPTCHA to a site, you can block automated software while helping your welcome users to enter with ease.

Source - support.google.com

EmailJS supports Google reCaptcha verification before sending an email and you can restrict it to not send an email if a reCaptcha code is not sent in the request object.

For more detailed information see the topic on the EmailJS website: Adding CAPTCHA verification | EmailJS

Adding reCaptcha verification to EmailJS

An issue with the current wallisconsultancy.co.uk website is that the contact form can be easily abused by spam as it has no "human verification" method.

Let's fix this issue by adding Google reCaptcha support to the website.

Setting up reCaptcha

Creating a Google reCaptcha application

To setup EmailJS for my application we need to create a new application for Google reCaptcha.

To do this:

  1. Navigate to https://www.google.com/recaptcha
  2. Select admin console in the top right of the screen.
  3. Select register a new site
  4. Fill in the details
    • Make sure you select reCAPTCHA v2 as EmailJS does not support v3
    • I gave localhost as the site URL so that I can use it in development. It’s recommended that you keep your development and production reCaptcha separate so I created another application with wallisconsultancy.co.uk as the site URL.

Once you've done this you will be given a secret key, keep this for the next step.

Google reCaptcha sign up form
The Google reCaptcha sign up form

Connecting Google reCaptcha and EmailJS

Next, we need to configure EmailJS to require a reCaptcha verification before sending an email by adding the secret key generated in the previous step to CAPTCHA tab of the EmailJS template section.

reCaptcha setup on EmailJS
Adding the reCaptcha secret key to the EmailJS template

EmailJS is now configured so that it won't send emails without the reCaptcha code.

 Adding reCaptcha to React

Let's modify the React application to send the reCaptcha code to EmailJS in the request object.

I'm using the react-google-recaptcha component to display the reCaptcha box. It supplies an onChange function that has the reCaptcha code as a parameter.

I modified the flow of the contact form like so:

  1. User enters details
  2. On send the page changes to show the reCaptcha instead of the contact form
  3. User completes reCaptcha and the onChange function is called.
  4. React component combines the form values and reCaptcha code into a single params that is sent to EmailJS.

Example usage:

import emailjs from 'emailjs-com';
import ReCAPTCHA from 'react-google-recaptcha';

export default function MessageForm() {
  // This should be implemented as a form
  const [name, email, message] = ['name', 'email', 'message'];


  const sendEmail = (captchaValue) => {
    const params = {
      ...formState,
      'g-recaptcha-response': captchaValue,
    };

    emailjs.send(
      process.env.EMAIL_JS_SERVICE,
      process.env.EMAIL_JS_TEMPLATE,
      params,
      process.env.EMAIL_JS_USER,
    )
      .then(({ status }) => {
        console.log("EMAILJS SENT", status.code);
      }, (err) => {
        console.log("EMAILJS ERROR", err);
      });
  };

  return (
    <ReCAPTCHA
      sitekey={process.env.CAPTCHA_SITE_KEY}
      onChange={sendEmail}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

The complete code for the contact form on the Wallis Consultancy React application can be found on Github.

That's it, we've now setup an EmailJS powered contact form with Google reCaptcha so that we can safely deploy our application without the form being abused by bots to spam to the email recipient.

Round up

In this blog I’ve explored how reCaptcha can reduce the amount of spam sent from a contact form on a website and configured it to work with EmailJS.

In the next blog I will complete the development of wallisconsultancy.co.uk by using plugins to increase the performance of the website and the SEO score.

Discussion (8)

Collapse
pastorsi profile image
Simon Measures

HI James,

In a Vue application I'm stuck with how to combine the form values and reCaptcha code into a single params that is sent to EmailJS. I guess what I basically need is your "Example usage" code for the React application written for a Vue application. Do you happen to have an equivalent code for Vue?

Simon

Collapse
jameswallis profile image
James Wallis Author

Hi Simon,

Unfortunately, I don't have the code for Vue but I've had a look on their docs and it looks to be the same. You should use the .send function documented here: emailjs.com/docs/sdk/send/. Then when calling the .send function, add the field 'g-recaptcha-response' and the reCaptcha code into the params object.

For example if you had a EmailJS template that required a name and message you'd do the following adding in the g-recaptcha-response:

emailjs.send(
      emailJSService,
      emailJSTemplate,
      {
          name: "Simon",
          message: "A new message",
          'g-recaptcha-response': 'your_recaptcha_returned_code',
      },
      emailJSUser, // this is optional
    )
Enter fullscreen mode Exit fullscreen mode

If you send me a link to your code or paste the relevant part as a comment I'm happy to take a look.

Collapse
pastorsi profile image
Simon Measures

Thanks so much, James. I'll take a close look over your guidance and code tomorrow.

I said I was working on a Vue application but actually it's a Nuxt application. You'll understand I'm sure as I see you work with Next.js.

My code is here:
github.com/pastorsi/ghost-nuxt-web...

In the script section of that file, onSubmit for reCaptcha is not actioned because I couldn't get it working. I action EmailJS without reCaptcha.

(My repository is a working repository for a website. The working website contact form here mcea.org.uk/contact.)

All the best,

Simon
Monmouth, UK

Thread Thread
jameswallis profile image
James Wallis Author • Edited on

No problem at all.

I’ve had a look your code and done a bit of research on Nuxt to understand it a bit better.

You’re using .sendForm and passing the e.target as the third parameter. AFAIK Recaptcha only works with the .send function.

So this is what I’d suggest:

  1. Change .sendForm to be .send
  2. For the third parameter pass an object, the keys need to be the same as your EmailJS template. I’ll assume they’re name, email and message. Then add another key: g-recaptcha-response.
  3. Add an ID to the two inputs and text areas, something like id=“form-name” etc.
  4. Populate the object using document.getElementById(). So the EmailJS parameter object and .send function should roughly look like:
const emailsJSParams = {
    name: document.getElementById('form-name').value,
    email: document.getElementById('form-email').value,
    message: document.getElementById('form-message').value,
    'g-recaptcha-response': yourCaptchaResponse,
}

emailjs
        .send(
          'service_bt8lbbb',
          'mcea_contact_form',
          emailsJSParams,
          'user_ddB1kBYjUr7bhz87JDRm5'
        )
Enter fullscreen mode Exit fullscreen mode

I’ve not tested that code block but it should at least put you on the right track!

Let me know how you get on and if you need further assistance.

Thanks, James

Thread Thread
xr0master profile image
Sergey Khomushin

To be honest, the captcha was made for sendForm method, since the captcha is usually part of the form. However, the send method can send any params, including the captcha token.
By the way, this is why the name of the parameter is so strange (g-recaptcha-response), this is the default name from reCAPCHA.

Thread Thread
jameswallis profile image
James Wallis Author

Ah is that right? I ended up using send as I wanted to show the reCaptcha after the form was submitted but before querying EmailJS.
Additionally, I wasn't able to find a guide to use reCaptcha with sendForm whereas I could find one for send emailjs.com/docs/rest-api/send/. Looking again at the docs and your comment I guess that you literally just put the reCaptcha inside the form element and EmailJS will get it out of e.target.

Thread Thread
xr0master profile image
Sergey Khomushin

Yeah, you guess correctly.

Collapse
hjfitz profile image
Harry

👏