How to protect your django blog from spam

Last Update: 02.03.2008. By azarai in django | python

I guess almost all people hate spam, but still it’s there. Either they spam your mailbox, forum, blog or whatever. It annoying. But for most communication ways there exist solutions to protect yourself from spam. I am going to talk about one kind of em, the blog comment spam, and the way we are using here to protect ourself from comment spam.

During developing of sergio, our blog engine, it was clear that we were going to use the django comment app. It’s nice and clean, but actually it lacks integrated spam protection. Fortunately there was already django-comment-utils, a great addon lib for comment management. And it contained spam protection via akismet. Great! Just use it and we are done!?

Yes and no. Sure it protects you from spam, but it needs to get trained to get much better. As i had to delete the spam comment anyways in django admin i thought about a way to tell akismet it was spam from the admin page. Akismet allows spam reporting via API and there was born out hack.

First i had to find a way to get your own button, link or whatever into the detail page of my comments model. A look into the Django Book - Extending Django’s Admin Interface reveiled the answer. In our case overwriting the detail page for the specific model (admin/hackedcomments/freecomment/change_form.html). I copied the original version from django and added a button before the historylink.

<li><a href="/admin/markcommentasspam/{{ object_id }}/" class="historylink">{% trans "Mark as SPAM" %}</a></li>

Then i coded the view to mark the comment as spam and mapped it too the url /admin/markcommentasspam.

def mark_comment_as_spam(request, object_id):
    try:
        comment = FreeComment.objects.get(id=object_id)
        akismet_api = Akismet(key=settings.AKISMET_API_KEY,
                                      blog_url='http://codeboje.de/')
        if akismet_api.verify_key():
            akismet_data = { 'comment_type': 'comment',
                                         'referrer': '',
                                         'user_ip': "",
                                         'user_agent': '', 
                                         'comment_author' : comment.person_name,
                                         'comment_author_email' : comment.person_email,
                                         'comment_author_url' : comment.homepage}
            akismet_api.submit_spam(comment.comment, data=akismet_data, build_data=True)
        return HttpResponse("marked comment as spam")
    except:
        return HttpResponse("received error while marking comment as spam")

The attributes person_email and homepage are part of our hacked comments version. Your mileage may vary a bit with your version....