Recaptcha con Nodejs y React.

December 20, 2019 • ☕️ 3 minutos de lectura

reCAPTCHA

Básicamente sirve para evitar que se envíen formularios automatizados por bots y de esta manera prevenir envio de spam y ataques automatizados.

Para usarlo, deberemos acceder a https://www.google.com/recaptcha/. Debemos tener una cuenta de gmail para ello.

Hacemos click en Admin Panel nos llevará a una página donde configuraremos reCaptcha. Es importante elegir la versión V2, ya que será la que usaremos en este tutorial, además de añadir el dominio para el que lo usaremos.

⚠️Si quieres realizar pruebas en local, deberás añadir localhost con dominio.

Creación de reCaptcha

El siguiente paso nos mostaré las claves que usaremos más adelante.

Claves reCaptcha

Configurando cliente React

import React, { Component, useContext, useEffect, useState } from "react"
import axios from "axios"
import { useInputValue } from "../../hooks/useInputValue"
var Recaptcha = require("react-recaptcha")

export default function Contactar({ disabled, onSubmit, title }) {
  const [error, setError] = useState("")
  const [token, setToken] = useState("")
  const [submit, setSubmit] = useState(false)
  const name = useInputValue("")
  const email = useInputValue("")
  const message = useInputValue("")

  // Función que se ejecutará después de recibir el token.
  var callback = function() {
    console.log("Done!!!!")
  }

  // Recibimos el token y almacenamos su respuesta en un estado con el hook useState.
  var verifyCallback = function(response) {
    setToken(response)
  }

  // Función que enviará los datos del formulario a nuestros servidor.
  const handleSubmit = event => {
    event.preventDefault()

    let data = {
      name: name.value,
      email: email.value,
      message: message.value,
      token: token,
    }

    axios
      .post("http://localhost:4444/api/send-mail", data)
      .then(res => {
        setSubmit("Enviado con éxito")
      })
      .catch(() => {
        setError("Mensaje no enviado")
      })
  }

  return (
    <div className="row justify-content-center">
      <div className="col-md-6">
        <form id="feedback-form" disabled={disabled} onSubmit={handleSubmit}>
          <h2>Contactar</h2>
          <div className="form-group">
            <div className="input-group input-group-alternative mb-3">
              <input
                className="form-control"
                disabled={disabled}
                placeholder="Nombre"
                {...name}
                type="text"
                name="nombre"
                noValidate
              />
            </div>
          </div>

          <div className="form-group">
            <div className="input-group input-group-alternative mb-3">
              <input
                className="form-control"
                type="email"
                disabled={disabled}
                placeholder="Email"
                {...email}
                name="email"
                noValidate
              />
            </div>
          </div>

          <div className="form-group">
            <div className="input-group input-group-alternative mb-3">
              <textarea
                className="form-control"
                type="email"
                disabled={disabled}
                placeholder="Mensaje"
                {...message}
                name="message"
                noValidate
              />
            </div>
          </div>

          <div className="submit">
            <button
              type="submit"
              className="btn  btn-lg btn-block"
              disabled={submit ? true : false}
            >
              ENVIAR
            </button>
          </div>
          <Recaptcha
            sitekey="6Lf63ckUAAAAAP8cVXqTJ0bFIcyquY7sif-tgr6O"
            render="explicit"
            verifyCallback={verifyCallback}
            onloadCallback={callback}
          />
          {submit && <div className="alert success">{submit}</div>}
          {error && <div className="alert error">{error}</div>}
        </form>
      </div>
    </div>
  )
}

Configurando servidor node & express

const express = require("express");
const bodyParser = require("body-parser");
const nodemailer = require("nodemailer");
const cors = require("cors");
const fetch = require("isomorphic-fetch");
const app = express();

const port = 4444;

app.use(
  bodyParser.urlencoded({
    extended: true
  })
);
app.use(bodyParser.json());

app.use(cors());

app.listen(port, () => {
  console.log("We are live on port 4444");
});

app.get("/api", (req, res) => {
  res.send("Welcome to my api");
});

app.post("/api/send-mail", (req, res) => {
  const secret_key = "6Lf63ckUAAAAADJcRN MovivvKpsBkhYVQr2w7kFx";
  const token = req.body.token;
  const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`;

  fetch(url, {
    method: "post"
  })
    .then(response => response.json())
    .then(google_response => {
      if (google_response.success === true) {
        var data = req.body;
        console.log(req.body);
        console.log(google_response);

        var smtpTransport = nodemailer.createTransport({
          service: "Gmail",
          port: 465,
          auth: {
            user: "tuemail@gmail.com",
            pass: "tusupercontraseña."
          }
        });

        var mailOptions = {
          from: data.email,
          to: "tuemail@gmail.com",
          replyTo: data.email,
          subject: `Información sobre: Puerta Bormujos ${data.email}`,
          html: `<p>${data.name}<br/>
                ${data.email}<br/>
                ${data.phone}<br/>
                <hr/>      
                <p>${data.message}</p>`
        };

        smtpTransport.sendMail(mailOptions, (error, response) => {
          if (error) {
            res.send(error);
          } else {
            res.send("Success");
          }
          smtpTransport.close();
        });
      }
    })
    .catch(error => res.json({ error }));
});