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.

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
Very useful sample.
Thanks
Farida
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 ?
Thanks for the most helpful comment about where to put captchas.net login data!
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 .
(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
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.