Skip to content

Instantly share code, notes, and snippets.

@szepeviktor
Last active May 15, 2026 11:42
Show Gist options
  • Select an option

  • Save szepeviktor/0758ac761237f17ef315a45c6a546975 to your computer and use it in GitHub Desktop.

Select an option

Save szepeviktor/0758ac761237f17ef315a45c6a546975 to your computer and use it in GitHub Desktop.
Contact Form 7 Robot Trap
<?php
/*
* Plugin Name: Contact Form 7 Robot Trap
* Description: Adds a hidden trap field to Contact Form 7.
* Version: 0.6.0
* Plugin URI: https://wdmarket.com/
* Author: WD Market
* Requires PHP: 7.4
* Requires at least: 6.7
* Requires Plugins: contact-form-7
* Constants: CF7_ROBOT_TRAP_TOLERATE_DNS_FAILURE
*/
declare(strict_types=1);
if (! defined('ABSPATH')) {
exit;
}
/**
* Hidden trap field for Contact Form 7.
*
* Usage:
* Add <code>[robottrap email-verify class:email-verify tabindex:2]</code>
* before the email field, then hide it with:
* <code>div.wpcf7 .email-verify { display:none; }</code>
*
* Fires the robottrap_hiddenfield and robottrap_mx hooks.
*
* WARNING
*
* DNS failures can cause false positives during domain validation.
* Disable domain validation by adding this to wp-config.php:
*
* define('CF7_ROBOT_TRAP_TOLERATE_DNS_FAILURE', true);
*/
add_action('plugins_loaded', 'wpcf7_robottrap_bootstrap');
/**
* Register hooks after Contact Form 7 is loaded.
*/
function wpcf7_robottrap_bootstrap(): void
{
if (! function_exists('wpcf7_add_form_tag') || ! class_exists('WPCF7_FormTag')) {
return;
}
add_action('wpcf7_init', 'wpcf7_add_form_tag_robottrap');
add_filter('wpcf7_validate_robottrap', 'wpcf7_robottrap_validation_filter', 10, 2);
if (! (defined('CF7_ROBOT_TRAP_TOLERATE_DNS_FAILURE') && CF7_ROBOT_TRAP_TOLERATE_DNS_FAILURE)) {
add_filter('wpcf7_validate_email', 'wpcf7_robottrap_domain_validation_filter', 20, 2);
add_filter('wpcf7_validate_email*', 'wpcf7_robottrap_domain_validation_filter', 20, 2);
}
}
/**
* Create the [robottrap] form tag.
*/
function wpcf7_add_form_tag_robottrap(): void
{
wpcf7_add_form_tag(
array('robottrap'),
'wpcf7_robottrap_form_tag_handler',
true
);
}
/**
* Render the [robottrap] form tag.
*
* @param WPCF7_FormTag|array $tag Form tag definition.
* @return string
*/
function wpcf7_robottrap_form_tag_handler($tag): string
{
$tag = new WPCF7_FormTag($tag);
if (empty($tag->name)) {
$tag->name = 'email-verify';
}
$validation_error = wpcf7_get_validation_error($tag->name);
$class = wpcf7_form_controls_class('text');
if ($validation_error) {
$class .= ' wpcf7-not-valid';
}
$atts = array();
/**
* Robots may look for the word "hidden".
*
* $atts['aria-hidden'] = 'true';
*/
$atts['size'] = $tag->get_size_option('40');
$atts['maxlength'] = $tag->get_maxlength_option();
$atts['class'] = $tag->get_class_option($class);
$atts['id'] = $tag->get_id_option();
$atts['tabindex'] = $tag->get_option('tabindex', 'int', true);
$value = (string) reset($tag->values);
if ($tag->has_option('placeholder') || $tag->has_option('watermark')) {
$atts['placeholder'] = $value;
$value = '';
} elseif ('' === $value) {
$value = $tag->get_default_option();
}
$value = wpcf7_get_hangover($tag->name, $value);
$atts['value'] = $value;
$atts['type'] = 'text';
$atts['name'] = $tag->name;
$atts = wpcf7_format_atts($atts);
return sprintf(
'<span class="wpcf7-form-control-wrap %s"><input %s />%s</span>',
sanitize_html_class($tag->name),
$atts,
$validation_error
);
}
/**
* Detect submitted hidden field.
*
* This is the validator function of [robottrap].
*
* @param WPCF7_Validation $result The WPCF7 result object.
* @param WPCF7_FormTag|array $tag The source form tag.
* @return WPCF7_Validation
*/
function wpcf7_robottrap_validation_filter($result, $tag): WPCF7_Validation
{
$tag = new WPCF7_FormTag($tag);
$name = $tag->name;
if (! empty($_POST[$name])) {
$value = sanitize_text_field(wp_unslash($_POST[$name]));
/**
* Counteraction for filled-out hidden field
*
* Only a robot is able to see fields hidden by CSS.
*
* @param string $value Sanitized value of field.
*/
do_action('robottrap_hiddenfield', $value);
$result->invalidate($tag, wpcf7_get_message('spam'));
}
return $result;
}
/**
* Validate email domain.
*
* This is the validator function of [email]. Does robottrap_mx action on invalid email domain.
*
* @param WPCF7_Validation $result WPCF7 result object.
* @param WPCF7_FormTag|array $tag Source form tag.
* @return WPCF7_Validation
*/
function wpcf7_robottrap_domain_validation_filter($result, $tag): WPCF7_Validation
{
$tag = new WPCF7_FormTag($tag);
$name = $tag->name;
$value = isset($_POST[$name])
? trim(sanitize_text_field(wp_unslash($_POST[$name])))
: '';
if (! $result->is_valid($name) || '' === $value) {
return $result;
}
$domain = sanitize_text_field(substr(strrchr($value, '@'), 1));
if (empty($domain) || ! checkdnsrr($domain, 'MX')) {
/**
* Counteraction for empty or MX-less domain part of email addresses
*
* Usually this is a spammer robot.
*
* @param string $domain Email domain.
*/
do_action('robottrap_mx', $domain);
$result->invalidate($tag, wpcf7_get_message('spam'));
}
return $result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment