Using SpamGuard with ContactForm for Craft*

I’ve been working a lot using Craft CMS recently. It’s a relative newcomer on the CMS block but already has a lot going for it. However, the downside of being fairly new on the scene is that the plugin community isn’t as large as other platforms such as WordPress and consequently there aren’t as many options available to extend or enhance the core system.

When implementing a simple contact form I experienced this downside at first hand when a form I had implemented using the official plugin began being bombarded with spam. Being very pro-active Pixels & Tonic, the creators of the software, had already updated their plugin to include honeypot captcha as a configuration option. I implemented this solution but unfortunately it did not stop the spam because the spammers were only filling in the required fields.

I was directed by P&T in the direction of SpamGuard by Selvin Ortiz which uses Akismet to filter spam. Documentation was a bit sparse on implementing the plugin as it is in the very early stages of development and it didn't actually work “out of the box” with ContactForm because there aren’t any hooks in CF for it to use. However, Selvin has been working on this and already had an implementation ready to be used although it involves P&T also making an adjustment to their plugin (which I believe they are planning to do).

Selvin was extremely helpful in guiding me through the steps to implement these changes so that I could use them straight away and I will outline them below for the benefit of anyone else who is experiencing spam issues.

(It is worth noting, however, that this is works for me for version 0.4.6 of SpamGuard together with version 1.2 of ContactForm, you use them at your own risk and that any updates to the plugins you apply will result in changes being overwritten.)

1. Modify contactform > controllers > ContactFormController.php

Insert the following code on line 170 just before craft()->email->sendEmail($email);

// @begin: onBeforeSend()
	 $hookParams	 = array('emailModel' => $email);
	 $hookResponses	= craft()->plugins->call('contactFormOnBeforeSend', $hookParams);
	 foreach ($hookResponses as $plugin => $response)
	 {
	 // @see Honeypot behavior above
	 if (false === $response)
	 {
	 $this->returnSuccess();
	 return;
	 }
	 }
// @end: onBeforeSend()

2. Modify spamguard > services > SpamGuardService.php

On line 16 replace SpamGuardPlugin::PLUGIN_HANDLE with 'spamGuard'

Insert the following code on line 177, just before the last curly bracket

public function pluck($key, array $arr=array(), $def=false)
{
 	if (false !== stripos($key, '.'))
 	{
 	 return array_key_exists($key, $arr) ? $arr[$key] : $def;
 	}
 	$keys = explode('.', $key);
 	if (count($keys))
 	{
 	 $result = $arr;
 	 foreach ($keys as $key)
 	 {
 	 if (array_key_exists($key, $result))
 	 {
 	 $result = $result[$key];
 	 }
 	 else
 	 {
 	 return $def;
 	 }
 	 }
 	 return $result;
 	}
 	return $def;
}

3. Modify spamguard > SpamGuardPlugin.php

Insert the following code on line 178, just before the last curly bracket

/**
  * contactFormOnBeforeSend()
  *
  * Allows you to use spamguard alongside the contactform plugin by P&T
  *
  * @since	0.4.7
  * @return	boolean Whether the contact form should send the email
  */
 public function contactFormOnBeforeSend(BaseModel $email)
 {
 	$content	= craft()->spamGuard->pluck('message.body', $_POST, craft()->spamGuard->pluck('message', $_POST));
 	$author	 = craft()->spamGuard->pluck('fromName', $_POST, '');
 	$email	 = craft()->spamGuard->pluck('fromEmail', $_POST, '');
 	if ($this->spamGuardDetectSpam($content, $author, $email))
 	{
 	 return false;
 	}
 }

And that’s it! As long as you have an Akismet API key and have set up ContactForm as per their instructions you should be good to go!

* Spamguard 0.4.7 will be released in 2 days


comments powered by Disqus