WPForms Spam Filtering Using the Comment Blacklist Field

WordPress Comment Blacklist Field

I’ve recently begun getting spam messages through my contact forms that are submitted by humans, not bots, so they don’t get stopped by the standard honeypot setting in WPForms, my form plugin of choice.

If you’ve ever used Contact Form 7, you might know that it uses the values that you enter into your Comment Blacklist field to stop spam messages being successfully submitted by people.

I wanted to create something similar for WPForms, that was easy to maintain, and add new terms to, and used the existing comment blacklist. I also didn’t want the overhead of another plugin just to do this, so I created a solution in PHP.

I came across an excellent solution from Bill Erickson, that blocks specific email addresses from submitting spam, but I needed a few extra features.

Firstly, I wanted to look at more than just the email address. I wanted to be able to scan the contents of the name, email and message fields for spammy terms.

Secondly, I wanted to be able to search for partial matches, not exact matches, because of course spam is always evolving, and the terms might change slightly.

And thirdly, I wanted an easy way to add terms to my list, instead of having to edit my function each time a new term popped up. I considered using Advanced Custom Fields to do this, but then realised it made a lot more sense to use the existing Comment Blacklist field, in the same way that Contact Form 7 does.

My WPForms Spam Blacklist Solution using a Custom Function

I blended the code from Bill’s WPForms Email Blacklist function and the code from the WP Core function wp_blacklist_check to create the function below.

When you add this code to your site, the form submission is not added to your WPForm entries, no emails are sent to you, and the user just sees a blank response, so they have no indication that their submission has not been successful.

If you have logging enabled, the honeypot value should show up in your WPForms Log.

Step 1. Add this code to your theme’s functions.php file

This code has been written to suit my contact form, which has a name field, and email field and a message field.

If your forms have other fields that you want to check for spam terms, you’ll need to assign these values to variables and add these variables to the pattern matching section.

To find out which fields your form is using, you can add a

print_r($fields)

line, and do a test form submission to see the full array of terms that your specific form includes.

// Filter out spam messages on forms
/**
* WPForms Spam Filter Using the Comment Blacklist
*
* @author Nikki Stokes
* @link https://thebizpixie.com/article/stop-wpforms-spam-using-comment-blacklist-field/
*
* @param string $honeypot, empty if not spam, honeypot text is used in WPForms Log
* @param array $fields
* @param array $entry
* @param array $form_data
*/
function nhs_wpforms_email_blacklist( $honeypot, $fields, $entry, $form_data ) {

	//print_r( $form_data );
	
	// Get comment blacklist values
	$mod_keys = trim( get_option( 'blacklist_keys' ) );
	if ( '' == $mod_keys ) {
	}
	else{
		$words = explode( "\n", $mod_keys );
		
		// Assign field content to variables
		foreach( $form_data['fields'] as $id => $field ) {
			if( 'email' == $field['type'] ){
				$email = $entry['fields'][$id];
			}
			if( 'name' == $field['type'] ){
				if ( $field['format'] == 'first-last' ) {
					$name = $entry['fields'][$id][1];
				}
				else {
					$name = $entry['fields'][$id];
				}
			}
			if( 'text' == $field['type'] ){
				$text = $entry['fields'][$id];
			}			
			if( 'textarea' == $field['type'] ){
				$message = $entry['fields'][$id];
				$message_without_html = wp_strip_all_tags( $message );
			}
		}

		// Step through spam terms in turn
		foreach ( (array) $words as $word ) {
			$word = trim( $word );

			// Skip empty lines
			if ( empty( $word ) ) {
			continue; }

			// Escape terms so that '#' chars in the spam words don't break things
			$word = preg_quote( $word, '#' );

			// Match form fields to spam terms
			$pattern = "#$word#i";
			if ( preg_match( $pattern, $name )
				|| preg_match( $pattern, $email )
				|| preg_match( $pattern, $text )
				|| preg_match( $pattern, $message )
				|| preg_match( $pattern, $message_without_html )
				) {
				$honeypot = '[Blacklist] ' . $name . ', ' . $email . ', ' . $message;
			}
		}
	}

	return $honeypot;
}
add_filter( 'wpforms_process_honeypot', 'nhs_wpforms_email_blacklist', 10, 4 );

Step 2. Add spammy terms to your comment blacklist

Go to Settings > Discussion and scroll to your Comment Blacklist.

Add any terms that match the kinds of spam you’ve been getting in here. Keep in mind two things:

  1. These terms will be unique to your site and the spam you’re getting
  2. Make sure that your terms don’t filter out legitimate messages, based on your site’s audience and content

WordPress Comment Blacklist Field

I’m really pleased with this solution, because finally I can stop getting all that rubbish in my inbox and my database, and it’s easy for me to update in the future.

Good luck and happy spam blocking!

Please share this content

About the author 

I’ve had a love affair with systems, technology and data for as long as I can remember. I’ve been building websites for over 20 years, running online businesses for more than 15, and teaching myself how to use gazillions of software programs since the very first moment I got my hands on a computer. I’m a geek and proud of it!

Share your thoughts...

Your email address will not be published. Required fields are marked

  1. Thank you so much for sharing this information. I’ve been getting tons of emails written in Russian. Do you know how to block those?

    1. Hi Peggy,

      I’ve been getting some of those myself. One thing I’ve done is add “.ru” to my honeypot terms to eliminate Russian email addresses, although mostly this won’t make much difference because that’s not the address that’s used.

      The other thing I’ve done is use Google Translate to translate the email message, and then identify which words are the spammiest in Russian and add these to my list as well, in Russian!

      Hopefully this helps you reduce those annoying Russian messages a little!

  2. This is an excellent function, many thanks for developing it.

    May I suggest two slight modifications as follows:

    1) There is no need to have an empty ‘if’ clause and have the code in the else clause, this is generally considered to be bad form. A better way would be to use if ( ” !== $mod_keys ), move the code to the if clause and dispense with the else clause entirely.

    2) Since you are not using this function as a spam word counter, once you have determined that the text is spam, that is after the first match, you can break out of the loop. So under the line that stars with “$honeypot = ‘[Blacklist] ‘ add a break;

    Thanks.

    1. Hi Mark,

      You’re most welcome and thanks for the great feedback.

      I wrote the code with the empty ‘if’ clause simply because it made more sense to me that way, and I like self-evident code that’s easy to understand when I come back to it in five years’ time.

      But you’re right that it’s less efficient to do it that way, and your suggestion would work even better. I haven’t tested it, so I won’t update my code just yet, but it’s definitely a great idea, especially to improve speed.

      And again, adding the break in the loop would definitely make the code faster. If you don’t put it in, you’d see all of the terms that were considered spam, but one really is enough!

      I appreciate you taking the time to make these suggestions and heartily agree with both of them.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}