Categories
How To

Gravity Forms and Disallowed Keys

How to send people on your disallowed comment list to the spam bin, and live better.

Table of Contents

Recently Gravity Forms was added to a site I work on. Now, I’ve never used it before, so I was hands off (except for changing the email it sent to) and I know pretty much nothing at all about it. But what I do know is that there’s a real jerk out there who’ll spam it, given a chance.

Unlike other contact form plugins out there, Gravity Forms comes with built in free integration with Akismet! But, like pretty much every other plugin out there, it does not integrate with my disallowed keys.

I’m a big proponent of not reinventing the wheel, and I strongly feel that being able to block someone from comments and contact forms should be a done deal. I opted to mark people who do this as spam, instead of a rejection, so they will never know if I ever saw their email or not. This is a questionable use of the spam settings, but at the same time, it’s been a rough couple of years.

The Process The Process

Since the disallowed_keys list contains emails and words, the first thing I wanted to do was strip out everything that wasn’t an email or an @-domain — that means foobar@example.com is a valid entry, and @spammers-r-us.com is a valid entry, but foobar on it’s own is not. I run through my disallowed list, add everything valid to an array in a new variable.

Before I can pass through the email, though, I need to remove any periods from the username. You see, Gmail allows you to use foobar and foo.bar and fo.o.b.a.r all as the same valid username on your email. Yes. all those would go to the same person. To get around this, I remove all periods and make a clean username.

Also I have to consider the reality of jerks, who do things like foobar+cheater@example.com — Gmail allows you to use the + sign to get clever and isolate emails, which I use myself to track what sign-up spams me. At the same time, I don’t want people to get around my blocks, so I have to strip everything following the plus-sign from the email.

While I’m doing this, I’ll save the domain as it’s own variable, because that will allow me to check if @spammers-r-us.com is on my list or not.

Once I’ve got it all sorted, I do an in-array: if either the exact (clean) email is in the array, or the exact @-domain is in the array, it’s spam and I reject.

Top ↑

The Code The Code

add_action( 'gform_entry_is_spam_1', 'my_spam_filter_gform_entry_is_spam_1', 10, 3 );

function my_spam_filter_gform_entry_is_spam_1( $is_spam, $form, $entry ) {

	// If this is already spam, we're gonna return and be done.
	if ( $is_spam ) {
		return $is_spam;
	}

	// Email is field 2.
	$email = rgar( $entry, '2' );

	// Build a list of valid emails & domains from disallowed_keys
	$disallowed_emails = array();
	$disallowed_array  = explode( "\n", get_option( 'disallowed_keys' ) );

	// Make a list of spammer emails and domains.
	foreach ( $disallowed_array as $spammer ) {
		if ( is_email( $spammer ) ) {
			// This is an email address, so it's valid.
			$disallowed_emails[] = $spammer;
		} elseif ( strpos( $spammer, '@' ) !== false ) {
			// This contains an @ so it's probably a whole domain.
			$disallowed_emails[] = $spammer;
		}
	}

	// Break apart email into parts
	$emailparts = explode( '@', $email );
	$username   = $emailparts[0];       // i.e. foobar
	$domain     = '@' . $emailparts[1]; // i.e. @example.com

	// Remove all periods (i.e. foo.bar > foobar )
	$clean_username = str_replace( '.', '', $username );

	// Remove everything AFTER a + sign (i.e. foobar+spamavoid > foobar )
	$clean_username = strstr( $clean_username, '+', true ) ? strstr( $clean_username, '+', true ) : $clean_username;

	// rebuild email now that it's clean.
	$clean_email = $clean_username . '@' . $emailparts[1];
	
	// If the email OR the domain is an exact match in the array, then we know this is a spammer.
	if ( in_array( $clean_email, $disallowed, true ) || in_array( $domain, $disallowed, true ) ) {
		$return = true;
	}

	// If we got all the way down here, we're not spam!
	return false;
}

Top ↑

Of Note… Of Note…

Before you use this yourself, you will need to customize two things!

  1. gform_entry_is_spam_1 is actually the specific form I’m checking. Form ID 1. Customize that to match your form ID.
  2. $email = rgar( $entry, '2' ); — you may have noticed I put ’email is field 2′ as a note above it. That’s because email is the second field on form 1, so I hard grabbed it. If yours is different, change that.

Also … I actually broke this out into two files, one that just checks “Is this a spammer?” and the Gravity Forms file, so the latter calls spammers.php and checks the email against the is_spammer() function. The reason I did that is because I need to run this same check on Jetpack’s contact form. Both call the same function to know if someone is evil.