Spam leaves no stone unturned. How does one protect those Plone web forms that are open for anonymous web users to spam, such as the Plone contact form?

I found a straight-forward and effective solution offered by the PloneCaptcha’s product. Here are the steps to add this feature to your default Plone contact form.

Example of PloneCaptchas in action

Getting Started

As the product site mentions, you just need a free captchas.net account, and some tweaks to your CMFFormController form template and tweak to your .metadata file to include a new validator.

PloneCaptchas document errata: The site mentions adding your captchas.net captcha_username and captcha_password to config.py, but you add to PloneCaptcha.py

How-To

For Plone’s Contact form, I copied the core templates to my own product’s skin folder so they could be customized for adding the captcha:

contact-info.cpt

Here I added the field, and included PloneCaptcha’s template:

<div class="field"
  tal:define="error errors/captcha|nothing"
  tal:attributes="class python:test(error, 'field error', 'field')">
  <label for="subject">
    Captcha
  </label>
  <span class="fieldRequired" title="Required"
          i18n:attributes="title title_required;"
          i18n:translate="label_required">(Required)</span>

  <div class="formHelp">
    To reduce automated spamming, please enter the letters in the box below so we know you're a genuine human.
  </div>

  <div tal:content="error">Validation error output</div>            

  <div metal:use-macro="here/captcha/macros/edit" />
</div>

contact-info.cpt.metadata

The only change here is in the validators section:

[validators]
validators=validate_captcha, validate_site_feedback

validate_site_feedback.vpy

I also had to tweak this existing form validator so it only returned the customary “please correct the below errors” once — and not one from the PloneCaptcha validator, and one from mine. Since I put the captcha validator first in the list, I just checked to see if the state.errors object already has a captcha error, and if yes, it don’t send another portal message:

if state.getErrors():
    # don't display two portal messages if the captcha validation fails
    if not state.errors.has_key('captcha'):
        context.plone_utils.addPortalMessage(_(u'Please correct the indicated errors.'))
    return state.set(status='failure')
else:
    return state

Commentary

  1. Farida wrote on 06. Sep 2007

    Very useful sample.

    Thanks
    Farida

  2. Ben wrote on 30. Oct 2007

    Hi
    Thanks for the above. I integrated Plone Captcha into my Plone 3 site and it works fine. I wondered if somebody tried to integrate the recent recaptcha.net version into that framework. From my first view to PloneCaptcha.py, it should be possible ?

  3. kees wrote on 25. Jan 2008

    Thanks for the most helpful comment about where to put captchas.net login data!

  4. James Stroud wrote on 21. Feb 2009

    Thanks for this entry. It is helpful However, the package is not “PloneCaptchas” as stated in this blog entry. It is “PloneCaptcha”. Googling “PloneCaptchas” gets one “qPloneCaptchas” which does not use captchas.net. If you use the method here, you do not want qPloneCaptchas. You want PloneCaptcha available at .

  5. James Stroud wrote on 21. Feb 2009

    (I hope this form doesn’t eat too much of this reply because it ate my link above. I also hope formatting comes out.)

    The link to PloneCaptcha is:
    http://sourceforge.net/projects/plonecaptcha/

    For Plone 3.1:

    To install the PloneCaptcha product, simply make a new folder in the zinstance/products folder of you Plone 3.1 site and unzip the PloneCaptcha product into that folder. Add the product in the ZMI.

    Also, the customization to contact-info.cpt can be done completely in the ZMI:
    /portal_skins/plone_templates/contact-info/

    I could not get the custom validator to be recognized and used, so I copied these lines into my custom validate_site_feedback.vpy:

    code_generated = context.portal_captcha.getGeneratedCaptchaCode(hidden_captcha_code)
    if code_generated != code_entered_by_user:
    state.setError(’captcha’,'Please enter the valid captcha code’, new_status=”failure”)

    but then I needed to put in this parameter list at the top of the custom validate_site_feedback.vpy form:

    hidden_captcha_code=”,code_entered_by_user=”,sender_from_address=”,subject=”,message=”

    The validate_site_feedback.vpy script can be changed in the ZMI customization form at:

    /portal_skins/plone_form_scripts/validate_site_feedback/manage_main

  6. Brian Gershon wrote on 22. Feb 2009

    Thanks James for the Plone 3.1 updated info! Also, I fixed the apostrophe and added a direct link to the product in the original blog entry based on your feedback.

Leave a reply