How To Protect A Rails Application Against Spam with Akismet

written October 1 2006 by
Kommen
tagged with
, , , ,
43 Comments so far. Go, post one!
Previous MacBooks sold out?
The Rails Way Next
Akismator — The Better Way To Protect a Rails App Against Spam
Migrations in Ruby on Rails
Exception Notifier - Ruby on Rails plugin
State of Web Development 2006

Spam is more and more a problem for many sites. And there are many approaches to fight spam. One is Akismet.

Akismet is a collaborative effort to make spam a non-issue. While there are Akismet plugins for Typo, WordPress, etc. you have to do some work to use it in your own application.

In this article I will demonstrate how to use Akismet in your own
Rails application to protect it against spammers. As example I will use comments, e.g in a weblog.
I’m assuming you already have your blog up and running, and want to add spam protection with Akismet.

Get an Akismet key

Akismet is free for personal use. But for using it, you have to get a key. Either a commercial or a personal one.
So go to http://akismet.com/ and get one.
For the personal one you will get redirected to the WordPress signup. If you just
want the key for your application, choose the option Just a username, please..

After submitting the form, you’ll get an activation email. Click on the link in the email
to verify your email address. Then you will get another email, which contains your
user data and your Akismet key labeled with API Key:.

Get the Akismet API for Ruby

David Czarnecki has written a Ruby interface that you can use in your application to easily access the Akismet API.
Download the akismet.rb file from here:
http://soakedandsoaped.com/files/akismet.rb
and put it in the lib directory from your Rails application.
The filename has to be akismet.rb. (case sensitive!)

Create a little helper function

In your controller write a little helper function that checks comments for spam.
This could look like this:

 1 
 2   protected
 3   
 4   def check_comment_for_spam(author, text)
 5     @akismet = Akismet.new('< your Akismet key here>', '<your blog url here>') # blog url: e.g. http://sas.sparklingstudios.com
 6     
 7     # return true when API key isn't valid, YOUR FAULT!!
 8     return true unless @akismet.verifyAPIKey 
 9     
10     # will return false, when everthing is ok and true when Akismet thinks the comment is spam. 
11     return @akismet.commentCheck(
12               request.remote_ip,            # remote IP
13               request.user_agent,           # user agent
14               request.env['HTTP_REFERER'],  # http referer
15               '',                           # permalink
16               'comment',                    # comment type
17               author,                       # author name
18               '',                           # author email
19               '',                           # author url
20               text,                         # comment text
21               {})                           # other
22   end

Call the method before saving a comment

Your create method could look like this:

 1 
 2   def create
 3     @comment = Comment.new(params[:comment])
 4     unless check_comment_for_spam(@comment.author, @comment.comment_text)
 5       if @comment.save
 6         flash[:notice] = 'Comment was successfully created.'
 7         redirect_to :action => 'list'
 8       else
 9         render :action => 'new'
10       end
11     else
12       # Spam detected! Do something with the spammer.
13       flash[:notice] = 'Go away!'
14       render :action => 'new'
15     end
16   end

Test your spam protection

You can test your spam protection by trying to create a comment with author set to viagra-test-123
Akismet should always say that this is spam.

You’re done! Akismet is now watching at your comments and blocks spammers!

Help Akismet

Note that you can submit spam also! Use the submitSpam function of the API.

Ressources

43 Comments

Make our day bright and participate!
Permalink to this comment { Jordan Arentsen }
on October 02 2006 (about 06:02 AM)

This looks like it could definitely come in handy. Thanks for adding this.

Permalink to this comment { Jordan Arentsen }
on October 02 2006 (about 06:03 AM)

Alright, um… shoot. You really need to have this close after you send a message. ;-) Sorry!

Permalink to this comment { pundit }
on October 03 2006 (about 16:13 PM)

:)

I think it’s funny how an article on spam-protection ends up having these sorts of multiple-repeat-spam-like comments.

(I know it’s not remotely similar, but still!)

Permalink to this comment { pills-love-test }
on October 03 2006 (about 17:56 PM)

test viagra love pills

Permalink to this comment { pills-love-test }
on October 03 2006 (about 17:56 PM)

you dont use this yourself then…?

Permalink to this comment { Patrick Havens }
on October 03 2006 (about 19:38 PM)

Or, it got passed… It also looks at email address… website addresses…

Permalink to this comment { Patrick Havens }
on October 03 2006 (about 19:39 PM)

and damn… gives you no notification if it worked/was submitted…

Permalink to this comment { Lv. }
on October 06 2006 (about 11:37 AM)

not a easy work

Permalink to this comment { viagra-test-123 }
on October 06 2006 (about 17:34 PM)

bla bla

Permalink to this comment { kommen }
on October 06 2006 (about 17:49 PM)

The message above is from myself…

Currently we use Typo. We plan to write our own small blog system. But we currently don’t have enough time.

Permalink to this comment { Joe }
on October 06 2006 (about 17:55 PM)

In Austria we have to attend a kind of basic military service.. We decided to use Typo as a temporary solution for publishing articles.

Permalink to this comment { Tom Armitage }
on October 11 2006 (about 17:00 PM)

Interesting that you do the checking on submit.

I’ve been working on this problem; I do the checking on submit, but store all comments – because, as well as the is_spam method, there’s also the is_ham one.

I was working for a while on acts_as_akismet. It’s a small, internal tool – nowhere near open-sourceable yet – that stores all the info akismet requires (IP, headers) in the db. It also means that, as long as the model is correctly described, you just drop “acts_as_akismet” into the Comment model (or whatever) and off you go.

It looks like I need to refine it a little, if Rick Olson’s recent comments are anything to go by… but it might see a release at some point. Maybe. Of any interest?

Permalink to this comment { kommen }
on October 11 2006 (about 19:17 PM)

You’re right Tom. Saving every comment would be better. But I wanted to keep the example simple.

I also thought about an acts_as module. Would be very interesting to see what you’ve done and how it works.

Permalink to this comment { Douglas F Shearer }
on October 17 2006 (about 12:35 PM)

I modified a lot of your code, and like Tom, I save all the spam and ham in the database, this allows me to manually moderate the spam at my leisure. Akismet does allow me to publish the ok comments, while checking the spam for false-positives.

I’ve got this pretty much down to a tee, but will need to clean it up before I consider releasing it as an acts_as_akismet plugin.

The previous iteration of my spam protection used CAPTCHA. I’ve compared the two techniques in a little article entitled Reducing Comment Spam – Akismet or CAPTCHA?

Thanks for your article, it certainly allowed me to figure things out.

Permalink to this comment { j french }
on November 06 2006 (about 22:54 PM)

I used Akismet.rb in a few Rails apps and ended up extruding it into a plugin that extends Akismet functionality to the controller object. Other changes include automatic inclusion of remote_ip, user_agent, and http_referer, and the ability to pass a hash of arguments into the public functions rather than the entire parameter list as above.

http://rubyforge.org/projects/ror-akismet/

Permalink to this comment { ydj.dufour@wanadoo.fr }
on November 25 2006 (about 09:26 AM)

I tried to use it.. but it ended with an operation timed out…
nothing going out… so nothing back…

what did I missed ?

Permalink to this comment { spider }
on January 06 2007 (about 02:19 AM)

helpful article

Permalink to this comment { Zach Inglis }
on March 18 2007 (about 08:27 AM)

Nice post.

I shall be using this in an upcoming project.

PS- Would be nice if my the default value for the comments dissapeared on click. Also it’s “Your 2 Cents” rather than “Cent”

Permalink to this comment { Joe }
on March 19 2007 (about 08:55 AM)

Thanks zach. Grammar case closed, default text finally disappears onfocus.

Permalink to this comment { xain }
on March 23 2007 (about 07:19 AM)

I think it only stop robot spammers.

Permalink to this comment { Mike }
on May 07 2007 (about 22:19 PM)

Akismet works great on my sites powered by WordPress and Drupal.

Permalink to this comment { Micah }
on September 08 2007 (about 22:52 PM)

Do you worry about adding a POST to the request/response cycle? If Akismet is not responding, you could tie up your web server (assuming single mongrel here) until the POST times out. Even with a mongrel cluster, a high traffic server could be brought to its knees by a momentary outage of Akismet.

Permalink to this comment { CypeSpulfup }
on November 30 2007 (about 13:51 PM)

This simply prodigy!
http://srubibablo.com
I Will be back!

Permalink to this comment { Julia }
on December 14 2007 (about 09:38 AM)

Hi, just popped in here <a href="http:" />The Outsider – DJ Shadow</a> Why you so think? <a href="http:" />More Adventurous – Rilo Kiley</a> Why you so think? <a href="http:" />Grinderman – Grinderman</a>

Permalink to this comment { Ana Nelson }
on January 08 2008 (about 10:02 AM)

This is a great idea for preventing form spam, I look forward to trying it. I’ve also had a lot of success in reducing form spam just by checking that the HTTP REFERER is somewhere within the same domain (this won’t work if people might have the page containing the form bookmarked).

Re Micah’s comment about the risk of tying up mongrels if the Akismet server doesn’t respond, this is an issue any time you access an external server. And even if you have multiple mongrels they can all get tied up by something like this. You can use something like BackgrounDRb, or just a rake task called by a cron job every few minutes, rather than doing this directly within the request/response cycle. In fact checking comments for spam is mentioned in one of the comments on topfunky’s recent blog post about Beanstalk

Permalink to this comment { דירות }
on April 14 2008 (about 12:18 PM)

Akismet is the best thing since sliced bread!

Permalink to this comment { Ethan Garofolo }
on July 08 2008 (about 16:35 PM)

Hope this wasn’t already mentioned… I was pulling my hair out trying to get key validation working. It turns out, when you put in the address of your blog (or whatever) don’t forget the http:// part of it. From the looks of the other comments, no one else made that mistake, but perhaps there are some lost souls just browsing who have made the same blunder.

Permalink to this comment { Tadd Giles }
on July 21 2008 (about 20:12 PM)

Worked for me. Nice starting point. Thanks for the help!

Permalink to this comment { nick }
on July 29 2008 (about 17:07 PM)

KpnkIB hi! hice site!

Permalink to this comment { nick }
on July 30 2008 (about 07:30 AM)

LeVhQ5 hi! hice site!

Permalink to this comment { nick }
on July 30 2008 (about 20:18 PM)

mYGaYw hi! hice site!

Permalink to this comment { james }
on August 01 2008 (about 04:33 AM)

i say one thing <a>phendimetrazine</a> 581 <a>meridia free shipping</a> fezhl

Permalink to this comment { john }
on August 01 2008 (about 07:41 AM)

hi great site 10x <a>cheap ambien</a> wckp

Permalink to this comment { sylvia }
on August 01 2008 (about 17:25 PM)

i say one thing <a>cheap phentermine</a> 203

Permalink to this comment { kris }
on August 02 2008 (about 16:05 PM)

cool post dude <a>hydrocodone addiction</a> ohuyy <a>meridia</a> >:-((

Permalink to this comment { hottube }
on October 18 2008 (about 13:25 PM)

=) nice work man <a>porno hub</a> =)
<a>eskimo tube</a>

Permalink to this comment { hottube }
on November 16 2008 (about 14:32 PM)

gdf fg hfdh dfgh fh dsdfd f hdfh h <a>pornos</a> gdf gdsf gsh sdgfghj dgf hdfgh fh <a>boob tube</a>

Permalink to this comment { hottube }
on November 16 2008 (about 14:33 PM)

gdf fg hfdh dfgh fh dsdfd f hdfh h <a>pornos</a> gdf gdsf gsh sdgfghj dgf hdfgh fh <a>boob tube</a>

Permalink to this comment { redtub }
on November 16 2008 (about 17:41 PM)

gdf fg hdfh dfg jgfhj ddsg dfh <a>redtub</a> gfd gfdh dfgh fds gdg fg h <a>xtube</a>

Permalink to this comment { hottube }
on November 16 2008 (about 23:32 PM)

gdf hfgdh dfj hj dsg dfgh <a>porno hub</a> dfg dsg dfh dgfh saef gdsf dfgh <a>pornohub</a>

Permalink to this comment { hottube }
on November 17 2008 (about 11:04 AM)

gdf dgh dfsh dg dfgh dfgjh dfh <a>hqtube</a> sdgdsfg fdsh dfgs gsfgsdf dfgh fds h <a>zootube</a>

Permalink to this comment { datebdsm }
on November 18 2008 (about 23:11 PM)

bdsm http://006d1a3.netsolhost.com/moodle/user/view.php?id=119&course=1 bdsm http://129.11.156.202/user/view.php?id=483&course=1 bdsm http://129.24.38.26/moodle/user/view.php?id=2805&course=1 bdsm http://147.102.19.203/user/view.php?id=76&course=1 bdsm http://164.58.224.87/moodle19/user/view.php?id=914&course=1 bdsm http://193.147.33.52/ingles/user/view.php?id=388&course=1 bdsm http://202.91.8.53/e-learning/user/view.php?id=909&course=1 bdsm http://203.157.15.2/belearning/user/view.php?id=11&course=1 bdsm http://4d-elearning.com/user/view.php?id=4645&course=1 bdsm http://80.93.49.210/redu/user/view.php?id=319&course=1 bdsm http://abcd-eu.org/moodle_1_7/user/view.php?id=128&course=1 bdsm http://abcfrancais.net/course/user/view.php?id=92&course=1 bdsm http://academy.sci-finatics.net/user/view.php?id=91&course=1 bdsm http://accfinstore.co.za/elearning/user/view.php?id=134&course=1 bdsm http://achievementinc.net/moodle/user/view.php?id=99&course=1

Permalink to this comment { bdsmsex }
on November 18 2008 (about 23:11 PM)

bdsm http://www.discoversensors.ie/moodle/user/view.php?id=437&course=1 bdsm http://www.discoveryeducatorabroad.com/rockourworld/user/view.php?id=2115&course=1 bdsm http://www.dkwinston.com/test/user/view.php?id=211&course=1 bdsm http://www.docker.com/moodle/user/view.php?id=907&course=1 bdsm http://www.documediainc.com/moodle15/moodle/user/view.php?id=1041&course=1 bdsm http://www.doeaccimphal.org/moodle/user/view.php?id=226&course=1 bdsm http://www.dup-training.com/hair/moodle/user/view.php?id=1934&course=1 bdsm http://www.d-zyndbysharon.com/user/view.php?id=47&course=1 bdsm http://www.earwshs.net/moodle/user/view.php?id=298&course=1 bdsm http://www.easpire.co.uk/moodle/user/view.php?id=136&course=1 bdsm http://www.ecoach.org.uk/moodle/user/view.php?id=62&course=1 bdsm http://www.ecollege.ie/musgrave/user/view.php?id=1078&course=1 bdsm http://www.econometria.it/user/view.php?id=906&course=1 bdsm http://www.edgycation.org/moodle/user/view.php?id=302&course=1

Do participate!

Textile (only links and basic formatting) is allowed.
These are not required