Earlier today Postmark released a free (*) API to perform SpamAssasin checks. This means you can now integrate a free spam check into your application. The API, documented here, is very easy to use. You simply pass in your email and get either a score back or a score and a full report on how the score was generated. The only real difficult part fo the API is that you are intended to send a full email document. By that I mean the text file that represents what an email looks like "raw". Here's how I built a checker in ColdFusion. I did this all in about twenty minutes so please feel free to do this better/faster/quicker.

First, I did a "typical" self-posting form with basic error checking. The idea is that the form would allow an admin to send out a newsletter to his or her users. The code just handles form and validation. An actual newsletter implementation would take about five more minutes. (cfquery to cfmail is about as simple as you can make it!)

<cfparam name="form.title" default=""> <cfparam name="form.body" default="">

<!--- used for fake email ---> <cfset fromaddress = "raymondcamden@gmail.com">

<cfif structKeyExists(form, "send")> <!--- auto trim ---> <cfset form.title = trim(form.title)> <cfset form.bod = trim(form.body)>

<cfset errors = "">

<cfif not len(form.title)> <cfset errors &= "You must include a title.<br/>"> </cfif>

<cfif not len(form.body)> <cfset errors &= "You must include a body.<br/>"> </cfif>

<cfif not len(errors)> <!--- send the message out ---> <cfoutput> Your message, #form.title#, has been sent to your subscribers. </cfoutput> <cfabort> </cfif>

</cfif>

<form method="post">

<h2>Newsletter</h2>

<cfoutput> <cfif structKeyExists(variables, "errors")> <p> <b>Please correct the following:<br/>#errors#</b> </p> </cfif>

<p> Title: <input type="text" name="title" value="#form.title#"> </p>

<p> Body:<br/> <textarea name="body" cols="60" rows="20">#form.body#</textarea> </p> </cfoutput>

<p> <input type="submit" name="send" value="Send"> </p>

</form>

Next I added the spam check. As I said above, you are expected to mimic a "real" email. If you send just the text (in my case, form.body), you will get dinged badly for missing email headers. I went to Gmail, picked a random message, and viewed the original version. I took those headers and stripped it down as much as possible. In my report I get a few minor dings compared to the original version, but I felt like this was an acceptable compromise.

<cfsavecontent variable="fakemsg"><cfoutput> Date: Mon, 17 Oct 2011 14:14:13 -0400 (EDT) From: #fromaddress# To: #fromaddress# Subject: #form.title#

#form.body# </cfoutput> </cfsavecontent>

<cfhttp url="http://spamcheck.postmarkapp.com/filter" method="post"> <cfhttpparam type="formfield" name="email" value="#trim(fakemsg)#"> <cfhttpparam type="formfield" name="options" value="long"> </cfhttp> <cfset respRaw = cfhttp.filecontent.toString()> <cfset response = deserializeJSON(respRaw)> <cfif response.score gt 5> <cfset errors &= "Your report scored too high on the SpamAssasin check (#response.score#).<br/>"> <!--- possibly show response.report for more detail ---> </cfif>

The report key in the result is a plain text list of how your score was generated. You can display that in a PRE block or - conversely - parse it up and do what you will with it. You can test this below. Note - this will never send any emails, so feel free to test as many times as you would like. I've included the full code below.

  • Note that while this service is free, Postmark said they do not guarantee it will remain free, available, useful, etc for the rest of time.

<cfparam name="form.title" default=""> <cfparam name="form.body" default="">

<!--- used for fake email ---> <cfset fromaddress = "raymondcamden@gmail.com">

<cfif structKeyExists(form, "send")> <!--- auto trim ---> <cfset form.title = trim(form.title)> <cfset form.bod = trim(form.body)>

<cfset errors = "">

<cfif not len(form.title)> <cfset errors &= "You must include a title.<br/>"> </cfif>

<cfif not len(form.body)> <cfset errors &= "You must include a body.<br/>"> <cfelse> <!--- check for spammyness --->

<cfsavecontent variable="fakemsg"><cfoutput> Date: Mon, 17 Oct 2011 14:14:13 -0400 (EDT) From: #fromaddress# To: #fromaddress# Subject: #form.title#

#form.body# </cfoutput> </cfsavecontent>

<cfhttp url="http://spamcheck.postmarkapp.com/filter" method="post"> <cfhttpparam type="formfield" name="email" value="#trim(fakemsg)#"> <cfhttpparam type="formfield" name="options" value="long"> </cfhttp> <cfset respRaw = cfhttp.filecontent.toString()> <cfset response = deserializeJSON(respRaw)> <cfif response.score gt 5> <cfset errors &= "Your report scored too high on the SpamAssasin check (#response.score#).<br/>"> <!--- possibly show response.report for more detail ---> </cfif> </cfif>

<cfif not len(errors)> <!--- send the message out ---> <cfoutput> Your message, #form.title#, has been sent to your subscribers. </cfoutput> <cfabort> </cfif>

</cfif>

<form method="post">

<h2>Newsletter</h2>

<cfoutput> <cfif structKeyExists(variables, "errors")> <p> <b>Please correct the following:<br/>#errors#</b> </p> </cfif>

<p> Title: <input type="text" name="title" value="#form.title#"> </p>

<p> Body:<br/> <textarea name="body" cols="60" rows="20">#form.body#</textarea> </p> </cfoutput>

<p> <input type="submit" name="send" value="Send"> </p>

</form>