Fixing WPMU 2.8.4 and the ignored Banned Email Domains option

wpmufunctions_iconI’ve been having a heck of a time battling sploggers at UCalgaryBlogs.ca – roaches that create accounts and blogs so they can foist their spam links to game Google (thanks for providing spammers with such a powerful incentive, Google).

There’s an option in WordPress Multiuser to ban email domains – provide the domains, one per line, into a text box, and it will reject any roaches trying to create accounts from those domains.

The biggest offenders have been myspace.info and myspacee.info – and although they’ve been in my Banned Email Domains list for months, they just keep getting through. I figured there was some exploit they were using, but couldn’t find a thing.

So, today, I took a look through the code of WPMU 2.8.4, to see if I could find what was going on. Turns out, it’s a really simple fix. There’s a function in wp-includes/wpmu-functions.php, called is_email_address_unsafe() – it’s supposed to check the contents of the Banned Email Domains option field, and reject addresses from the flagged domains.

Except it wasn’t. Rejecting, I mean. It was letting everyone through, because of a simple bug in the code. It was written to treat the value of the option as an array and to directly walk through each item of the array. But, the option is stored as a string, so it needs to be converted to an array first. Easy peasy. Here’s my updated is_email_address_unsafe() function, which goes around line 880 of wpmu-functions.php:

function is_email_address_unsafe( $user_email ) {
	$banned_names_text = get_site_option( "banned_email_domains" ); // grab the string first
	$banned_names = explode("\n", $banned_names_text); // convert the raw text string to an array with an item per line
	if ( is_array( $banned_names ) && empty( $banned_names ) == false ) {
		$email_domain = strtolower( substr( $user_email, 1 + strpos( $user_email, '@' ) ) );
		foreach( (array) $banned_names as $banned_domain ) {
			if( $banned_domain == '' )
				continue;
			if (
				strstr( $email_domain, $banned_domain ) ||
				(
					strstr( $banned_domain, '/' ) &&
					preg_match( $banned_domain, $email_domain )
				)
			)
			return true;
		}
	}
	return false;
}

The fix is in the first 2 lines of the function – getting the value of the string, and then exploding that into the array which is then used by the rest of the function. I’ve tested the updated function out on UCalgaryBlogs.ca and it seems to work just fine. Hopefully the fix will get pulled into the next update of WPMU so everyone with Banned Email Domains can breathe a bit more easily.