<!--- The email address to which the email will be sent. If you don't want to put email addresses in the public form, you can always put it in the Default attribute of this tag. ---> <cfparam name="FORM.to_email" type="string" /> <!--- 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. ---> <cfparam name="FORM.from_email" type="string" default="#FORM.to_email#" /> <!--- The subject text of the outgoing email. ---> <cfparam name="FORM.subject" type="string" /> <!--- The url to which we should forward the page control once the email has been sent out. If this is not included, the page will just close out when the processing is done. NOTE: This URL must either be an absolute url or one that is relative to THIS PROCESSING TEMPLATE. ---> <cfparam name="FORM.success_url" type="string" default="" /> <!--- 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 put it in the default value here. That way, no public user would see anything about your server's directory structure. ---> <cfparam name="FORM.temp_directory" type="string" default="" /> <!--- This is the comma-delimited list of fields to include in the outgoing email. If you do not include this value, then all fields will be included in an arbitrary order. ---> <cfparam name="FORM.field_list" type="string" default="" /> <!--- ASSERT: At this point, we have paramed the data in the FORM scope. Any data that was required but did not exist will have thrown an error. ---> <!--- Copy the FORM data into the another structure so that we can remove the special Email-related data keys without echoing them in the email body. ---> <cfset REQUEST.EmailData = Duplicate( FORM ) /> <!--- Delete the email meta data. ---> <cfset StructDelete( REQUEST.EmailData, "fieldnames" ) /> <cfset StructDelete( REQUEST.EmailData, "to_email" ) /> <cfset StructDelete( REQUEST.EmailData, "from_email" ) /> <cfset StructDelete( REQUEST.EmailData, "subject" ) /> <cfset StructDelete( REQUEST.EmailData, "success_url" ) /> <cfset StructDelete( REQUEST.EmailData, "temp_directory" ) /> <cfset StructDelete( REQUEST.EmailData, "field_list" ) /> <!--- Build an array to hold the form fields that might have uploaded files. This will be translated into future CFMailParam tags. ---> <cfset REQUEST.Files = ArrayNew( 1 ) /> <!--- Now that we have a clean EmailData structure, we want to see if the user has any files that they are uploading. To do this, we are going to see if any of the form values translates to a temporary file (which is how ColdFusion displays uploaded files - the form field value is not the uploaded file, but rather the temp file on the server). ---> <cfif Len( FORM.temp_directory )> <!--- Loop over all the form fields. ---> <cfloop item="REQUEST.Key" collection="#REQUEST.EmailData#"> <!--- Check to see if this form field has a temp file. This will be a value that starts with a drive letter such as D: and ends with a .tmp file extension. ---> <cfif REFind( "^\w:.+?\.tmp$", REQUEST.EmailData[ REQUEST.Key ] )> <!--- This form field holds the temporary path of an uploaded file. We don't want this to be part of the primary form fields so, remove this key from the form data. ---> <cfset StructDelete( REQUEST.EmailData, REQUEST.Key ) /> <!--- Upload the file to the user-defined temp directory. This is really just moving it from ColdFusion's temp directory to our temp directory and renaming it. ---> <cffile action="upload" destination="#FORM.temp_directory#" filefield="#REQUEST.Key#" nameconflict="makeunique" /> <!--- Now that the file has been uploaded, add the target file path to the array of files that will be attached to the outgoing email. ---> <cfset ArrayAppend( REQUEST.Files, "#CFFILE.ServerDirectory#/#CFFILE.ServerFile#" ) /> </cfif> </cfloop> </cfif> <!--- Check to see if the user had defined the list of fields to use. If not, then just get the list of fields from the data struct (which will be returned in some arbitrary order). ---> <cfif NOT Len( FORM.field_list )> <!--- Get key list for fields. ---> <cfset FORM.field_list = StructKeyList( REQUEST.EmailData ) /> </cfif> <!--- Since this is a generic form handler, we don't have very much formatting. That gives us the ability to easily create both types of mail body - HTML and Plain Text. ---> <!--- Build the HTML version of the email. ---> <cfsavecontent variable="REQUEST.HtmlBody"> <cfoutput> <p> Email processed on #DateFormat( Now(), "mmm d, yyyy" )# at #TimeFormat( Now(), "hh:mm TT" )# </p> <h3> Form Data </h3> <dl> <!--- Loop over the form data. ---> <cfloop index="REQUEST.Key" list="#FORM.field_list#" delimiters=","> <dt> #REQUEST.Key# </dt> <dd> #HtmlEditFormat( REQUEST.EmailData[ Trim( REQUEST.Key ) ] )# </dd> </cfloop> </dl> <!--- Add some additional data about the user and where the form came from. This might help with debugging. ---> <h3> User Data </h3> <dl> <dt> Referrer: </dt> <dd> #CGI.http_referer# </dd> <dt> IP: </dt> <dd> #CGI.remote_addr# </dd> </dl> </cfoutput> </cfsavecontent> <!--- Build the Text version of the email. Don't worry about the leading white spaces in each line. We are going to trim that out afterwards (we are putting it in now so that our code page has nice flow to it). ---> <cfsavecontent variable="REQUEST.TextBody"> <cfoutput> Email processed on #DateFormat( Now(), "mmm d, yyyy" )# at #TimeFormat( Now(), "hh:mm TT" )# -- FORM DATA -- <!--- Loop over the form data. ---> <cfloop index="REQUEST.Key" list="#FORM.field_list#" delimiters=","> #Trim( REQUEST.Key )# #HtmlEditFormat( REQUEST.EmailData[ Trim( REQUEST.Key ) ] )# </cfloop> -- USER DATA -- Referrer: #CGI.http_referer# IP: #CGI.remote_addr# </cfoutput> </cfsavecontent> <!--- Because plain text emails keep all the white space, we have to remove the leading tabs from each line of the above content. This can be done with an easy multiline regex. ---> <cfset REQUEST.TextBody = REReplace( REQUEST.TextBody, "(?mi)^\t+|\t+$", "", "all" ) /> <!--- Send out the email. When using both the plain text and the html mail parts, be sure to use the HTML version LAST. If you put it first, Google Mail will not render the email. ---> <cfmail to="#FORM.to_email#" from="#FORM.from_email#" subject="#FORM.subject#"> <!--- Include the Text version. ---> <cfmailpart type="text/plain">#REQUEST.TextBody#</cfmailpart> <!--- Include the HTML version. ---> <cfmailpart type="text/html">#REQUEST.HtmlBody#</cfmailpart> <!--- Loop over files that we need to attach. ---> <cfloop index="REQUEST.FileIndex" from="1" to="#ArrayLen( REQUEST.Files )#" step="1"> <!--- Attach file. ---> <cfmailparam file="#REQUEST.Files[ REQUEST.FileIndex ]#" disposition="attachment" /> </cfloop> </cfmail> <!--- Now that the email has been sent out, check to see if we have a success url to which me need to forward the user. ---> <cfif Len( FORM.success_url )> <!--- Forward user. ---> <cflocation url="#FORM.success_url#" addtoken="false" /> </cfif> <!--- ASSERT: If we have made it this far, then the user did not provide a success URL. Therefore, we need to provide our own simple success page. ---> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Your Form Has Been Processed</title> </head> <body> <h1> Your Form Has Been Processed </h1> <p> Thank you for taking the time to fill out our form. It has been processed and sent to the appropriate people. </p> <p> <cfoutput> <a href="#CGI.http_referer#">Go back</a> </cfoutput> </p> </body> </html>