How to Build and Protect a Contact Form from Spam


For any business, a website is the digital representation of their brand. One crucial component of this website is the contact form, allowing potential clients or customers to reach out directly. Today, we'll walk through creating a simple yet efficient contact form using React for the frontend and Flask for the backend. To protect your site from spam, we'll integrate Google's reCAPTCHA and Bot Butcher.


1. Building the React Contact Form

First, install axios.

npm install axios
    

Then setup a basic React component for our contact form.

// ContactForm.js
import React, { useState } from "react";
import axios from "axios";

function ContactForm() {
  const [message, setMessage] = useState("");

  const handleSubmit = async (event) =>; {
    event.preventDefault();

    try {
      const response = await axios.post("/contact_us", { message });

      if (response.status === 200) {
        // Handle the redirect here if necessary.
      }
    } catch (error) {
      // Handle the error if necessary.
      console.error("There was an error submitting the form:", error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <textarea
        name="message"
        value={message}
        onChange={(e) => setMessage(e.target.value)}
        placeholder="Your Message..."
      />

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

export default ContactForm;
    

2. Setting Up the Flask Backend

Here, we will handle the POST request and redirect back to the GET handler.

#  main.py
from flask import Flask, request, jsonify, redirect, url_for, jsonify

app = Flask(__name__)

@app.route("/contact_us", methods=["POST", "GET"])
def contact_us():
    if request.method == "POST":
        message = request.json.get("message")
        # Store or process the message as necessary.

        return redirect(url_for("contact_us", success=True))

    # Handle the GET request.
    if request.method == "GET":
        success = request.args.get("success")
        if request.args.get("success"):
            return jsonify({"message":"Thank you for your message!", "status_code": 200})
        else:
            return jsonify({"message":"Please leave a message", "status_code": 200})
    return {}, 404

if __name__ == "__main__":
    app.run();
    

3. Integrating reCAPTCHA

Protecting your contact form from spam is crucial. Google's reCAPTCHA provides an efficient way to do this.


React:

First, integrate the reCAPTCHA component in your form.

npm install react-google-recaptcha
    

Then, adjust the ContactForm:

// ContactForm.js
import React, { useState } from "react";
import axios from "axios";
import ReCAPTCHA from "react-google-recaptcha";

function ContactForm() {
  const [message, setMessage] = useState("");
  const [recaptchaValue, setRecaptchaValue] = useState(null);

  const handleSubmit = async (event) => {
    event.preventDefault();

    try {
      const response = await axios.post("/contact_us", { message });

      if (response.status === 200) {
        // Handle the redirect here if necessary.
      }
    } catch (error) {
      // Handle the error if necessary.
      console.error("There was an error submitting the form:", error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <textarea
        name="message"
        value={message}
        onChange={(e) => setMessage(e.target.value)}
        placeholder="Your Message..."
      />


      <ReCAPTCHA
        sitekey="YOUR_RECAPTCHA_PUBLIC_KEY"
        onChange={(value) => setRecaptchaValue(value)}
      />

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

export default ContactForm;
    

Flask:

On the server-side, verify the reCAPTCHA response.

pip install flask-recaptcha
    

Then, adjust your Flask app:

#  main.py
from flask import Flask, request, jsonify, redirect, url_for, jsonify
from flask_recaptcha import ReCaptcha

app = Flask(__name__)
app.config["RECAPTCHA_SITE_KEY"] = "YOUR_RECAPTCHA_PUBLIC_KEY"
app.config["RECAPTCHA_SECRET_KEY"] = "YOUR_RECAPTCHA_SECRET_KEY"

recaptcha = ReCaptcha(app=app)

@app.route("/contact_us", methods=["POST", "GET"])
def contact_us():
    if request.method == "POST":
        if not recaptcha.verify():
            return "Please complete the reCAPTCHA.", 400

        # ...[previous code]
    

4. Integrating Bot Butcher

Sophisticated Bots, and humans, can still defeat reCAPTCHA. Next add Bot Butcher to filter out spam and junk messages that made it through.


On the server-side, send the message to Bot Butcher, and parse the response.

#  main.py
from flask import Flask, request, jsonify, redirect, url_for, jsonify
from flask_recaptcha import ReCaptcha
import requests

app = Flask(__name__)
app.config["RECAPTCHA_SITE_KEY"] = "YOUR_RECAPTCHA_PUBLIC_KEY"
app.config["RECAPTCHA_SECRET_KEY"] = "YOUR_RECAPTCHA_SECRET_KEY"
app.config["BOT_BUTCHER_API_KEY"] = "YOUR_BOT_BUTCHER_API_KEY"
app.config["BOT_BUTCHER_FORM_ID"] = "YOUR_BOT_BUTCHER_FORM_ID"

recaptcha = ReCaptcha(app=app)

def is_spam(message):
    """
    Returns True if message is spam
    """
    headers = {
        "Content-Type": "application/json",
        "x-api-key": app.config["YOUR_BOT_BUTCHER_API_KEY"]
    }
    data = {
        "form": app.config["BOT_BUTCHER_FORM_ID"],
        "message": message
    }
    response = requests.post("https://api.botbutcher.com", json=data, headers=headers)
    payload = response.json()
    return payload.get("spam")


@app.route("/contact_us", methods=["POST", "GET"])
def contact_us():
    """
    Contact Form
    """
    if request.method == "POST":
       if not recaptcha.verify():
           return "Please complete the reCAPTCHA.", 400

       message = request.json.get("message")
       if is_spam(message):
           # email contact form message
       // Store or process the message as necessary.

       return redirect(url_for("contact_us", success=True))

    # Handle the GET request.
    if request.method == "GET":
        if request.args.get("success"):
            return jsonify({"message":"Thank you for your message!", "status_code": 200})
        else:
            return jsonify({"message":"Please leave a message", "status_code": 200})
    return {}, 404

    

Conclusion

Building a contact form is more than just collecting messages. It's about providing a seamless experience for genuine users and filtering out unwanted spam. This guide provides a solid foundation for creating an efficient and secure contact form using React and Flask. With the addition of reCAPTCHA and Bot Butcher, you're ensuring extra layers of protection for your business site.