As mentioned when I began my hiatus, there would be the occasional code post. Here’s one that is born from how annoying someone is.
The Situation
I have a serial harasser. He’s a troll and a semi-stalker who doesn’t understand the meaning of “No.” I’ve blocked him on social media, his emails are blackholes, and as I don’t have contact forms on my sites, nor do I have open comment forms at the moment, it’s a non-issue here.
However, I do have another site which he found and decided to use my contact form to spam me and my co-admin with 10+ emails. When I found out, I blocked his IP address. He was on mobile, though, so I knew this would only last as long as he was on his phone. I needed a better solution.
This is not a rare problem. Especially not for women online. One of the many ways in which men drive women offline is by upping the emotional labor needed to be online. That is, they attack us with message after message, generally in the guise of being ‘a nice guy,’ or ‘just trying to have an open conversation.’ But the reality is that they want to wear you down and get you to do what they want.
It’s exhausting. If you’ve ever gone car shopping and had the dealer call you over and over with the hard sell, it’s like that.
The Paradox
Contact Forms are meant to be a way for people to contact you, outside of the comments on your site. That being so, they really do need to exist outside the confines of the comments, which means your comment moderation list is a bit inappropriate. You want people who are having comment problems to get a hold of you.
At the same time, if you’ve blackholed someone, you don’t. You don’t want them to bother you at all, as reading their messages, even though you’re deleting them, is draining. So you want to be able to block them.
Here’s the problem: most contact forms don’t let you do this out of the box.
Yeah, think on that for a moment.
Here are the top four contact form plugins:
- Contact Form 7 uses WordPress’s Comment Blacklist
- Jetpack Contact Form (aka Grunion) has no blacklisting ability
- Ninja Forms has no (apparently) blacklist
- WPForms has no blacklist (however Bill Erickson has some code for you)
I use Jetpack, and while I may be annoyed I’m also a developer. So I did made an answer.
The Caution
This will not block everyone. If your harasser changes emails a lot, you’re out of luck. And this is the ‘excuse’ I see a lot of the time. Why bother if they’re going to change emails? The answer is obvious. If I can inconvenience them enough, and make it clear I don’t care, they’ll go away.
Also if you do this right, they never know they’ve been blacklisted, so they think they’re getting to you and you’re sipping a damn mai tai.
The Solution
In March 2014, I opened a ticket asking for a way to blacklist people. They have made zero forward momentum on this in the 4.5 years since. So this little red hen is doing it herself.
By using the built in filter for spam (which Akismet uses), this code checks if someone’s on the comment blacklist by IP or email, and if so, flags the message as spam. You don’t get an email. You do still get the message in your spam, which is not a great fix. I’d rather it just get dumped into trash, but there’s no filter I can find for that.
Still. This works, and it shut the guy up.
add_filter( 'jetpack_contact_form_is_spam', 'jetpack_spammers', 11, 2 );
function jetpack_spammers( $is_spam, $form ) {
if ( $is_spam ) {
return $is_spam;
}
if ( wp_blacklist_check( $form['comment_author'], $form['comment_author_email'], $form['comment_author_url'], $form['comment_content'], $form['user_ip'], $form['user_agent'] ) ) {
return true;
}
return false;
}
But. That only helps what’s on the blacklist. And the blacklist has a couple drawbacks. First of all, while it absolutely does handle multiple words (so I can block ‘milady mika’ if I want), it’s a little more complex if you wanted to block someone using gmail and a plus sign in the email address. So if you want to block example+spammer@gmail.com
then you either have to add that in literally or you get creative. I went creative.
add_filter( 'jetpack_contact_form_is_spam', 'jetpack_harassment', 11, 2 );
function jetpack_harassment( $is_spam, $form ) {
// Bail early if already spam
if ( $is_spam ) {
return $is_spam;
}
$badlist = array();
$blacklist = explode( "\n", get_option( 'blacklist_keys' ) );
// Check the list for valid emails. Add the email _USERNAME_ to the list
foreach ( $blacklist as $spammer ) {
if ( is_email( $spammer ) ) {
$emailparts = explode( '@', $spammer );
$username = $emailparts[0];
$badlist[] = $username;
}
}
// Check if the comment author name matches an email we've banned
// You'd think we didn't have to do this but ...
if ( in_array( $form['comment_author'], $badlist ) ) {
return true;
}
// Check if the email username is one of the bad ones
// This will allow spammer@example.com AND spammer+foobar@example.com to get caught
foreach ( $badlist as $bad_person ) {
if ( preg_match( '/' . $bad_person . '/', $form['comment_author_email'] ) ) {
return true;
}
}
return false;
}
My original take was hardcoded in, but this way is more elegant and covers the majority of the ways ‘nice’ people try to get around blocks. Now, if you’ve blocked spammer@example.com
and someone submits a form with spammer+avoid@example.com
this will catch them. It has a higher chance of catching ‘innocents’ (like innocent@spammer.com
) however considering I’m looking for something like rosbeitam@example.com
I’m reasonably confident in this for my personal application.
The Take Away
If you make a contact form, you damn well better make a way for users to block people from the back end, without having to code it.
Merry Christmas, ya filthy animals.