Creating a Mailing List in ColdFusion (Part 4)
In my last entry, I talked about the code behind sending out an entry to the list subscribers. While in general this was rather simple, I built in a variable replacement system that let the emails be personalized for each list member. Today I'm going to add a critical part of the application - the unsubscribe feature. As part of this feature I will discuss how the variable replacement system is used to help with this feature.
As always, I like to start with code and then describe what I'm doing. Today's code may be a bit confusing at first - but it will make sense:
<cfif structKeyExists(url, "token") and isValid("uuid", url.token)>
<cfset application.maillist.unsubscribe(url.token)>
<p>
You have been unsubscribed from the mail list.
We hope you subscribe again in the future!
</p>
<cfelse>
<p>
Sorry, but you were not unsubscribed. Please ensure that you have copied the URL correctly
from your mail client.
</p>
</cfif>
Seems a little brief, right? All I'm doing is checking for the existence of a URL variable named token. If it exists and is a valid UUID (who here also loves the isValid() function?), then I call the same unsubscribe I had mentioned in part two If for some reason the token didn't exist or wasn't valid, I present an error message asking folks to check their mail client.
So where did this value come from? As you can guess, it came from their email address. Remember that the unsubscribe method uses the token I associated with each user. Also remember that I allow for variable substitution in each email sent to the subscribers. I can put this all together and allow for a custom unsubscribe link by simply adding this to the email:
http://someurl/unsubscribe.cfm?token=%token%
When the user gets his or her email, the token value at the end will equal their own token. When clicked, everything will be automatic. They will be automatically removed from the list. Since I'm using UUIDs, this also ensures that no one else can unsubscribe a member since it will be (near) impossible to guess another UUID value.
That's it for this installment. Luckily this series is actually quite simple and not "exploding" as the Model-Glue series did. I have one more entry planned and that is a verification service. While the code so far should be enough, when it comes to mail services, you typically want to go above and beyond and really be sure the person wants to subscribe. By the way - is anyone reading this series? The first two entries got decent responses, but the last one had no comments.
Comments
Thanks for the tutorial!
Will you throw in an extra benefit and show us how to do a mail spool (I think that is what it's called)? If we send out several hundred/thousand emails, it is nice to have the script pause for a few seconds every 100 emails or so. How is this done?
This will only work if the email is sent and received as HTML, but it could still be good to know how to do.
Still don't fancy padding this tutorial out? ;¬)
href="foo.cfm?r=%token%"
Of course, foo.cfm would need to notice it. I'd actually write something in Application.cfc to notice url.r and log it (token plus script loading).
In short, even advanced coders can benefit from seeing a step-by-step series of someone else's code.
As usual, well written, easy to read, and the example code is clear and concise. Thanks.
I understand that CF can send out tons of emails at a time, but I've gathered that if you send out that many emails all at once your domain can become registered in some db out there as a source of spam. Some developers have gotten around this by pausing the process for a few secconds every 100 or so emails.
Maybe it's just a conspiracy theory... ha, ha.
The method I found and re-use is to send each message to a database instead of actually mailing it out. And then have a scheduled script that runs every so often, checks the count of rows in the database and sends a burst of messages (deleting each message after it's been sent).
Wish I could remember where I grabbed the code -- it was from a tutorial somewhere online.
An exception occurred when invoking a event handler method from Application.cfc The method name is: onRequest.
followed by a bunch of stuff I don't understand. But you can look at it here if you want: http://www.dragonfireinteractive.com/list/sendmail...
Just type in anything in the subject and body field to test it out.
Right, cause I need to tell you that...
Sorry.
Im trying my hosting company for help but they've admitted to me they just lost their coldfusion genius so I better submit a "ticket" for support.
anyway, thanks for any help in the matter.
Carlos
<cfset application.maillistfrom = "ray@camdenfamily.com">
please change the addy
<cfcomponent output="false">
<cfset this.name = "MailListDemo">
<cfset this.applicationTimeout = createTimeSpan(0,2,0,0)>
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.maillist = createObject("component", "maillist").init("maillist")>
<cfset application.maillistfrom = "carlos@dragonfireinteractive.com">
<cfreturn true>
</cffunction>
<cffunction name="onApplicationEnd" returnType="void" output="false">
<cfargument name="applicationScope" required="true">
</cffunction>
<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfargument name="thePage" type="string" required="true">
<cfif structKeyExists(url, "reinit")>
<cfset onApplicationStart()>
</cfif>
<cfreturn true>
</cffunction>
<cffunction name="onRequest" returnType="void">
<cfargument name="thePage" type="string" required="true">
<cfinclude template="#arguments.thePage#">
</cffunction>
<cffunction name="onRequestEnd" returnType="void" output="false">
<cfargument name="thePage" type="string" required="true">
</cffunction>
<cffunction name="onError" returnType="void" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfdump var="#arguments.exception#" label="Error">
</cffunction>
<cffunction name="onSessionStart" returnType="void" output="false">
</cffunction>
<cffunction name="onSessionEnd" returnType="void" output="false">
<cfargument name="sessionScope" type="struct" required="true">
<cfargument name="appScope" type="struct" required="false">
</cffunction>
</cfcomponent>
When should I have done that?
Also, I thought that you set the mail server by specifying a valid email address (from my domain) on line 8 of application.cfm. Is this not the case?
According to the knowledge base articles, they advise me to do the follwoing (but Im concerned I will mess up your app if I try it):
For those on ColdFusion MX hosting plans, you can use the following code:
server="mail.YourDomain.com"
username=“AnyEmail@YourDomain.com”
password=“YourEmailPassword”
from="AnyEmail@YourDomain"
to="AnyEmail@AnyDomain.com"
subject="Any Subject">
This is the body of the message.
Any ideas?
Sorry for the delay - been a busy day.
Btw, what the heck is a model glue app?

