Spam-Resistant ColdFusion Form Processing, without Captcha
This page was used as the demonstration materials for the ColdFusion Meetup on October 15, 2009.
Source code for the CF processing is below . View recorded CF Meetup
This simple form represents a typical contact form for a company website,
with Name, Email Address, optional Phone Number and of course, the Message being sent.
Though quite normal-looking on the surface, this form is, in fact, embedded with super powers of defense.
We are preventing fraudulent submissions in a number of ways, including blocking html content in all form fields, comparing the submitted info to a list of known 'bad words',
and a secret weapon, invisible to the average user (hint: disable css in your browser and scroll down).
About
Sample Contact Form
Source Code for the Form and CF Processing
<!--- START PROCESSING --->
<cfif isDefined('form.senderFrom')>
<!--- VALIDATE FIELDS --->
<!--- check email --->
<cfif NOT len(trim(form.senderFrom)) gt 6 or NOT isValid('email',form.senderFrom)>
<cfset request.formError = 'A valid email address must be provided'>
<!--- message --->
<cfelseif NOT len(trim(form.senderMessage))>
<cfset request.formError = 'Be sure to include a message'>
<!--- honeypot --->
<cfelseif len(trim(form.email_address))>
<cfset request.formError = 'Spam!! <br />(Run away! Run away!)'>
</cfif>
<!--- /end VALIDATE FIELDS --->
<!--- CHECK FOR UNWANTED CONTENT--->
<!--- loop all form variables --->
<cfloop index="f" list="#form.fieldnames#">
<!--- set variable for field value --->
<cfset value="#evaluate('form.#f#')#">
<!--- BANNED WORDS --->
<cfset bannedWordsList = "herring,albatross,dragon,grail,lumberjack">
<!--- loop the banned words list and see if we have a match --->
<!--- Check for banned words --->
<cfloop list="#bannedWordsList#" delimiters="," index="w">
<cfif FindNoCase(w,value)>
<cfset request.formerror="<br />Beg your pardon? <br />Your WHAT hurts?">
<cfbreak>
</cfif>
</cfloop>
<!--- / end BANNED WORDS --->
<!--- HTML BLOCK --->
<cfset leftChar = '<' >
<cfset rightChar = '>' >
<!--- look for both characters contained in our content --->
<cfif findNoCase(leftChar, value) AND findNoCase(rightChar, value)>
<cfset request.formerror = "Text only please - no HTML">
<cfbreak>
</cfif>
<!--- / end HTML BLOCK --->
</cfloop>
<!--- / end CHECK FOR UNWANTED CONTENT --->
<fieldset>
<legend>
<cfif isDefined('request.formerror') and len(trim(request.formerror))>
Error!
<cfelse>
Thank You
</cfif>
</legend>
<!--- SHOW RESPONSE --->
<cfif isDefined('request.formerror') and len(trim(request.formerror))>
<p><strong>ERROR: <cfoutput>#request.formerror#</cfoutput></strong></p>
<p>Go <a href="javascript:history.back()">back</a> and try again</p>
<cfelse>
<p>Thank you. <br /><br />Your message has been sent and we will reply soon!</p>
</cfif>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</fieldset>
<!--- IF FORM NOT SUBMITTED (show the form) --->
<cfelse>
<fieldset><legend>Sample Contact Form</legend>
<cfform name="contactForm" action="#cgi.SCRIPT_NAME#" method="post">
<div>
<label for="senderName">Name: </label><cfinput type="text" name="senderName" size="48" value="" required="true" message="Your Name is required">
</div>
<div>
<label for="senderFrom">Email: </label><cfinput type="text" name="senderFrom" size="48" value="" required="true" validate="email" message="Email Address is required">
</div>
<div>
<label for="senderPhone">Phone: </label><input type="text" name="senderPhone" size="20" value="">
</div>
<div>
<label for="senderPhone">Your Message:</label><textarea name="senderMessage" cols="30" rows="12" style="width:310px;"></textarea>
</div>
<div style="text-align:center">
<input type="submit" value="Submit">
</div>
<div id="email_wrapper">
<input type="text" name="email_address" value="" size="20">
</div>
</cfform>
</fieldset>
</cfif>
<!--- / end IF FORM SUBMITTED --->