Welcome to the third entry on my series about creating a mailing list application in ColdFusion. The previous entries are linked to at the bottom of this article. In this entry I'm going to talk about the actual mail tool (and it's about time). In general, this is a pretty simple tool, but I do have one neat trick in it I think you will like. As with the previous entry, this script should be considered an "Admin Only" tool and should be placed behind a protected folder. Here is the script:
<!--- Just used to tell admin how many people will get the email --->
<cfset members = application.maillist.getMembers()>
<cfif members.recordCount is 0>
<p>
Sorry, but your mailing list does not have any subscribers. It is sad to be lonely.
</p>
<cfabort>
</cfif>
<cfparam name="form.subject" default="">
<cfparam name="form.body" default="">
<cfset errors = "">
<cfif structKeyExists(form, "send")>
<cfif not len(trim(form.subject))>
<cfset errors = errors & "You must include a subject.<br />">
</cfif>
<cfif not len(trim(form.body))>
<cfset errors = errors & "You must include a body.<br />">
</cfif>
<cfif errors is "">
<cfloop query="members">
<cfset theBody = form.body>
<!--- replace columns --->
<cfloop index="col" list="#members.columnList#">
<cfset theBody = replaceNoCase(theBody, "%" & col & "%", members[col][currentRow], "all")>
</cfloop>
<cfmail to="#email#" from="#application.maillistfrom#" subject="#form.subject#">#theBody#</cfmail>
</cfloop>
<!--- remove values --->
<cfset form.subject = "">
<cfset form.body = "">
<!--- show confirmation --->
<p>
<b>Your email has been sent.</b>
</p>
</cfif>
</cfif>
<cfoutput>
<p>
Please enter your mail in the form below. It will be mailed to #members.recordCount# member(s).
</p>
<cfif errors is not "">
<p>
<b>#errors#</b>
</p>
</cfif>
<form action="sendmail.cfm" method="post">
<b>Subject:</b> <input type="text" name="subject" value="#form.subject#"> <br />
<textarea name="body" cols="40" rows="10">#form.body#</textarea><br />
<input type="submit" name="send" value="Send Message">
</form>
</cfoutput>
A majority of this page is a simple form, so let me focus on the parts that are interesting. First off - it makes sense to add a simple sanity check before allowing the administrator to send the mail. This is done here:
<cfset members = application.maillist.getMembers()>
<cfif members.recordCount is 0>
<p>
Sorry, but your mailing list does not have any subscribers. It is sad to be lonely.
</p>
<cfabort>
</cfif>
You can't always rely on the common sense of your users, even your administrator users.
So outside of this, everything else is a simple form. But pay attention to how I send the email. Here is the relevant code portion:
<cfloop query="members">
<cfset theBody = form.body>
<!--- replace columns --->
<cfloop index="col" list="#members.columnList#">
<cfset theBody = replaceNoCase(theBody, "%" & col & "%", members[col][currentRow], "all")>
</cfloop>
<cfmail to="#email#" from="#application.maillistfrom#" subject="#form.subject#">#theBody#</cfmail>
</cfloop>
So what is going on here? I'm looping over every record from the members query. If you remember, this is the record set containing all my subscribers. This is a query that contains, right now, an email and token field. As I mentioned back in the first entry, a "real" site may have more fields, like name, age, etc. What I've done is built code to let the admin use "tokens" in the email. If the admin enters something like this:
Hi, %name%
And name exists as a column in the query, it will automatically be replaced with the value from the members query. This lets the administrator write a more personalized email. It will also let us set up the unsusbscribe functionality that I'll be talking about in the next entry. As before, you can find the code attached to the entry.