The other day, we had a client that told us they were switching from ColdFusion to PERL. Naturally, this struck us as a totally insane move; higher level languages like ColdFusion were created so that people no longer had to touch things like PERL. The idea of going back to PERL would be like some reverse evolution. After discussing this move with the client, trying to find the root cause of this move, we discovered that it had nothing to do with ColdFusion or PERL specifically. Rather, the client wanted to move to PERL to utilize the generic form handler in Matt's Script Archive. That's it, that was the executive decision to switch programming languages.
Since ColdFusion is awesome and I want our clients to stay on it, I decided to go ahead and build a generic form handler for public consumption. It probably doesn't have all the functionality that Matt's Script Archive generic form handler has, but I think it provides a good deal of functionality with almost no effort. You define the actions of the form processing by providing the following hidden fields:
to_email - This is the email address to which the email will be sent.
from_email - This is the email address from which the email will be sent. If this field is not included, the to_email address will automatically be used for both the to and from field.
subject - The subject text of the outgoing email.
success_url - This is the url to which we should forward the page control once the email has been sent out. If this is not included, the processing page will provide it's own generic success page. This URL must either be an absolute url or one that is relative to the generic form processing template since it will have to perform a relative CFLocation tag.
temp_directory - This is the full path directory in which uploaded files will be stored so that they can be attached to the outgoing email. If you are going to use this, remember to set your FORM encryption type to: enctype="multipart/form-data"; otherwise, the files will not submit as uploaded files. If you don't want to put the temp file path in the form, you can define it in the processing page for the same effect (and public users won't get any insight into your server's directory structure). If you do not include this value, then the uploaded files will not be attached to the outgoing email (and the file fields will be put in the email body).
field_list - This is the comma-delimited list of fields to include in the outgoing email. This is there purely to allow users to provide an explicit field order for the outgoing email. If you do not include this value, then all fields will be included in an arbitrary order (what ever StructKeyList() returns). If you do include this field, only those defined fields will be used.
Implementing the ColdFusion generic form processing is insanely simple. Here is a test page that demonstrates how the hidden fields should be included in the form:
Launch code in new window » Download code as text file »
As you can see, the hidden form fields are just provided as the first elements of the form. Notice also that the form Method points directly to our generic form processor. There is a certain amount of exposure here since the email addresses and the directory structure are out in the open, for any person or bot that knows how to view page source. If you don't want to put those values there, you can always move them directly into the ColdFusion CFParam tags at the top of the email processing page, which is more secure, but also, less flexible.
Here is the ColdFusion page that handles the generic form processing:
Launch code in new window » Download code as text file »
Now, one thing to realize is that the files that get uploaded and attached to the outgoing email don't get deleted from the server. We can't delete them after we send the email since emails don't go out directly. Yes, we could turn off spooling and send the email out directly and then delete the files, but I always hesitate to do that as I feel that it is forcing the eMail server to go against what it wants to do. You can either leave those files on the server, or make sure that the folder they point to gets periodically cleaned out.
When the email goes out, it goes out with both an HTML version and a Text version for clients that cannot handle HTML.
I hope that helps anyone who was thinking of switching from ColdFusion back to PERL :)
Download Code Snippet ZIP File
Comments (11) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
A quick note that the to_email should not be in the form as a hidden field but rather embedded in the action page. What happens is bots look for this, and once they find the form they use it as a mail relay to send their spam to other people. Gets your box on black hole lists, etc.
Posted by Joshua Cyr on Feb 1, 2008 at 9:38 AM
@Joshua,
Absolutely. You can move the to_email into the CFParam in the processing page. My only concern was that cuts of the flexibility a bit; however, less flexibility is better than being blacklisted!
Posted by Ben Nadel on Feb 1, 2008 at 9:42 AM
I'm actually working on something semi related right now where I'm looking to insert contacts into a TO: field from a list of pre-defined contacts, kind of like in Mac Mail/gmail etc. You don't happen to have any tips on how to do this the slickest do you? I know it's going to get messy with a bucket of javascript to handle the type-ahead :(
Posted by Sam Daams on Feb 1, 2008 at 10:02 AM
@Sam,
I think all you would need is a ContactID select box like this:
<option value="1">Ben</option>
<option value="2">Kit</option>
<option value="3">Sherri</option>
Then, on the processing page, you just have a struct that associates the IDs to the user address:
<cfset objContacts = StructNew() />
<cfset objContacts[ 1 ] = "ben@xyz.com" />
<cfset objContacts[ 2 ] = "kit@xyz.com" />
<cfset objContacts[ 3 ] = "sherri@xyz.com" />
Then, just grab the contact based on the submitted ContactID?
Posted by Ben Nadel on Feb 1, 2008 at 10:12 AM
@Ben,
On the subject of deleting file attachments, just to be clear, there is an attribute of cfmail called "spoolenable" which lets you enable or disable spooling on a case-by-case basis. You could set it to "no" for any email which had attachments, and leave it set to yes for all other emails, which would let you spool most of the time, but still delete attachment files in real time so that they don't accumulate on the server.
And as for whether not spooling your email is a bad practice, I think that it's ok as long as it's for just a few emails now and then. They just go into the email server's queue to wait their turn, anyway.
Posted by Tom Mollerus on Feb 1, 2008 at 10:15 AM
@Tom,
Good call on the conditionally spooling. That never occurred to me. I knew about the attribute, but I never thought of giving it a variable rather than a hard-coded yes/no. Sweet action!
Posted by Ben Nadel on Feb 1, 2008 at 10:19 AM
I'm looking to actually include a type ahead, so where you type 'mi' and it brings up 'mike'. Hit enter or the comma and start typing another and so on and so on.
But if I can't figure it out, I'll probably end up going with a check box or something similar :)
Posted by Sam Daams on Feb 1, 2008 at 2:04 PM
Ben:
Thanks for the post. I too had the need to upgrade some forms to move away from using the formmail.pl script. I ended up create a fairly direct port of the perl script to try to mimic all the functionality to create a solution that could be quickly dropped in place for an existing form. Your posting reminded me that I never posted about it nor published it, so thanks for the reminder! I detail more about it on my blog entry:
http://www.mkville.com/blog/index.cfm/2008/2/4/Simple-Form-Processing-and-Emailing-with-CFFormMail
You can find the project posted over at RIA Forge for downloading:
http://cfformmail.riaforge.org/
Mark
Posted by Mark Mazelin on Feb 4, 2008 at 1:17 PM
@Mark,
I saw your post earlier. Looks good to me :)
Posted by Ben Nadel on Feb 4, 2008 at 1:23 PM
I was looking up a amortization formula and ended up running across something i was working on. i am always amazed how that happens, anyway awsome stuff. just wanted to say thanks. j
Posted by jjcuzz on Sep 30, 2008 at 9:39 PM
@JJ,
Glad this helped in some way.
Posted by Ben Nadel on Sep 30, 2008 at 10:09 PM