Last active
May 15, 2026 11:42
-
-
Save szepeviktor/0758ac761237f17ef315a45c6a546975 to your computer and use it in GitHub Desktop.
Contact Form 7 Robot Trap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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