Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the jQuery Conference 2009 (Cambridge, MA) with:

Sending Random SMS Text Messages With ColdFusion To Make Her Feel Loved

By Ben Nadel on
Tags: ColdFusion

If you are anything like me, then you find coding in ColdFusion so much fun that when you're doing it, you tend forget about most other things like work and friends and loved ones and how early the cat wakes you up in the morning or why it's so freakin' hot in the office. As a result, those close to you might feel neglected. Here is a small, stand alone ColdFusion application that will help maintain the quality of your relationship by periodically prompting you to send a text message (SMS Message) to your girl friend (yes, I am aware of how sad this is). All you need are a few files and a scheduled ColdFusion task.

The first file is the XML data file that will define the text messages that the system will randomly select from:

  • <messages>
  •  
  • <message>
  • Hey honey, I was just thinking of you
  • </message>
  •  
  • <message>
  • Wish I was at home with you.
  • </message>
  •  
  • <message
  • mintime="4:00 PM">
  • This day is so long! Why can't we be home together already?!?
  • </message>
  •  
  • <message
  • mintime="3:00 PM"
  • days="Fri">
  • Thank god it's Friday. Just a few more hours till we can spend the weekend together.
  • </message>
  •  
  • <message
  • maxtime="11:00 AM">
  • I know I just saw you a few hours ago, but I am already missing you something wicked.
  • </message>
  •  
  • </messages>

Notice that there are some message node attributes being used:

mintime: This is the minimum value at which time a message can be considered valid for selection. For instance, the message "The day is so long" doesn't really make sense in the morning; and so, it is not valid until 4:00 PM.

maxtime: This is the maximum value at which time a message can be considered valid for selection. For instance, morning-related messages shouldn't be used in the afternoon.

days: This is a comma-delimited list of three-letter days in which the message is valid. For instance, weekend-related messages should not be valid early in the week, and therefore might have a Thr,Fri days attribute value.

You can, of course, put as many messages that you want. Each text message has a max length that it can be, which depends on the cellular carrier. I am not doing any validation checking for that.

The next file is the Application.cfc ColdFusion component where we define the application initialize it. The bulk of the initization imports the XML data files. We import not only the SMS message XML file, we also import a app_data.xml data file. This file contains information about the current state of the application including the time at which the next message can be send and the last three message IDs that were used.

  • <cfcomponent
  • output="true"
  • hint="Handle the application level events.">
  •  
  •  
  • <!--- Define application. --->
  • <cfset THIS.Name = "SMS Messages {#Hash( GetCurrentTemplatePath() )#}" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 2, 0, 0, 0 ) />
  • <cfset THIS.SessionManagement = false />
  • <cfset THIS.SetClientCookies = false />
  •  
  •  
  • <!--- Set page request settings. --->
  • <cfsetting
  • requesttimeout="20"
  • showdebugoutput="false"
  • enablecfoutputonly="true"
  • />
  •  
  •  
  • <cffunction
  • name="OnApplicationStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="Fires when the application is first run or manually reset.">
  •  
  • <!--- Define the local scope. --->
  • <cfset var LOCAL = StructNew() />
  •  
  •  
  • <!---
  • Since this application might get called
  • manually, we cannot depend on a single threaded
  • environment. But, we also have to consider the
  • environment... what are the chances that two
  • concurrent requests might come in? Zero. But, in
  • the stride of good practice, I will implement good
  • locking proactices anyway.
  • --->
  • <cflock
  • scope="APPLICATION"
  • type="EXCLUSIVE"
  • timeout="10"
  • throwontimeout="true">
  •  
  • <!--- Clear the application scope. --->
  • <cfset StructClear( APPLICATION ) />
  •  
  • <!---
  • Read in the XML file that contains are
  • defines our library of random text messages
  • (SMS Messages).
  • --->
  • <cffile
  • action="READ"
  • file="#ExpandPath( './messages.xml' )#"
  • variable="LOCAL.MessageData"
  • />
  •  
  •  
  • <!---
  • Parse the message data into an application-
  • scoped XML data structure.
  • --->
  • <cfset APPLICATION.MessagesXML = XmlParse(
  • LOCAL.MessageData
  • ) />
  •  
  •  
  • <!---
  • The XML is great, but for our purposes, it
  • would be easier to work with a query object
  • (we are going to need to query for messages
  • based on dynamic criteria). Therefore, we
  • are going to convert our XML object into a
  • ColdFusion query object.
  • --->
  • <cfset APPLICATION.Messages = QueryNew(
  • "id, message, min_time, max_time, days",
  • "INTEGER, VARCHAR, DECIMAL, DECIMAL, VARCHAR"
  • ) />
  •  
  •  
  • <!---
  • Now, let's get a short hand reference to the
  • messages array within our XML document.
  • --->
  • <cfset LOCAL.Messages = APPLICATION.MessagesXML.Messages.XmlChildren />
  •  
  • <!---
  • Loop over the messages and each one of them
  • to the message query.
  • --->
  • <cfloop
  • index="LOCAL.MessageIndex"
  • from="1"
  • to="#ArrayLen( LOCAL.Messages )#"
  • step="1">
  •  
  • <!---
  • Get a short hand reference to the message
  • (XML Node) that we are currently looking at.
  • --->
  • <cfset LOCAL.Message = LOCAL.Messages[ LOCAL.MessageIndex ] />
  •  
  •  
  • <!--- Add a new row to the query. --->
  • <cfset QueryAddRow( APPLICATION.Messages ) />
  •  
  • <!---
  • Add the ID of the message. This is just
  • going to be the index of the XML child.
  • --->
  • <cfset APPLICATION.Messages[ "id" ][ LOCAL.MessageIndex ] = JavaCast( "int", LOCAL.MessageIndex ) />
  •  
  • <!---
  • Store the message. Be sure to trim the
  • message we the XML data might have white
  • space. When sending a SMS text message,
  • data efficiency is HIGH priority.
  • --->
  • <cfset APPLICATION.Messages[ "message" ][ LOCAL.MessageIndex ] = JavaCast( "string", Trim( LOCAL.Message.XmlText ) ) />
  •  
  • <!---
  • When storing the min time, check to see
  • if the attribute exists and is a valid
  • date/time object. If it does not exist,
  • then we are going to store a null value.
  • --->
  • <cfif (
  • StructKeyExists( LOCAL.Message.XmlAttributes, "mintime" ) AND
  • IsNumericDate( LOCAL.Message.XmlAttributes.mintime )
  • )>
  •  
  • <!--- Store the time as a decimal. --->
  • <cfset APPLICATION.Messages[ "min_time" ][ LOCAL.MessageIndex ] = JavaCast( "float", LOCAL.Message.XmlAttributes.mintime ) />
  •  
  • <cfelse>
  •  
  • <!---
  • The time did not exists. Store a NULL
  • value that can be checked in our query
  • of queries.
  • --->
  • <cfset APPLICATION.Messages[ "min_time" ][ LOCAL.MessageIndex ] = JavaCast( "null", 0 ) />
  •  
  • </cfif>
  •  
  • <!---
  • When storing the max time, check to see
  • if the attribute exists and is a valid
  • date/time object. If it does not exist,
  • then we are going to store a null value.
  • --->
  • <cfif (
  • StructKeyExists( LOCAL.Message.XmlAttributes, "maxtime" ) AND
  • IsNumericDate( LOCAL.Message.XmlAttributes.maxtime )
  • )>
  •  
  • <!--- Store the time as a decimal. --->
  • <cfset APPLICATION.Messages[ "max_time" ][ LOCAL.MessageIndex ] = JavaCast( "float", LOCAL.Message.XmlAttributes.maxtime ) />
  •  
  • <cfelse>
  •  
  • <!---
  • The time did not exists. Store a NULL
  • value that can be checked in our query
  • of queries.
  • --->
  • <cfset APPLICATION.Messages[ "max_time" ][ LOCAL.MessageIndex ] = JavaCast( "null", 0 ) />
  •  
  • </cfif>
  •  
  •  
  • <!---
  • When storing the valid days, check to see
  • if the value exists. If it does not exist,
  • then we are going to store a NULL value.
  • --->
  • <cfif StructKeyExists( LOCAL.Message.XmlAttributes, "days" )>
  •  
  • <!--- Store the days. --->
  • <cfset APPLICATION.Messages[ "days" ][ LOCAL.MessageIndex ] = JavaCast( "string", LCase( LOCAL.Message.XmlAttributes.days ) ) />
  •  
  • <cfelse>
  •  
  • <!---
  • Days did not exists. Store a NULL
  • value that can be checked in our
  • query of queries.
  • --->
  • <cfset APPLICATION.Messages[ "days" ][ LOCAL.MessageIndex ] = JavaCast( "null", 0 ) />
  •  
  • </cfif>
  •  
  • </cfloop>
  •  
  •  
  •  
  • <!---
  • In addition to the actual message data, we
  • are going to need data about the state of
  • the application. Let's set up a default
  • data structure value.
  • --->
  • <cfset APPLICATION.Settings = StructNew() />
  •  
  • <!---
  • This is the file path to our application
  • settings data file. We will need this to init
  • here, but also to update the file later.
  • --->
  • <cfset APPLICATION.Settings.FilePath = ExpandPath(
  • "./app_data.xml"
  • ) />
  •  
  • <!---
  • We don't want to hassle ourselves... I mean we
  • want her to feel loved, but come on! Let's only
  • remind our selves on a random time that is not
  • too short. THis value will be the time at which
  • we can next send a message. For default, we
  • will use Now() (a new message can be sent ASAP).
  • --->
  • <cfset APPLICATION.Settings.NextMessage = Now() />
  •  
  • <!---
  • This will be the an array of the last three IDs
  • used. In our hectic, ColdFusion loving days,
  • how can we be expected to remember which text
  • messages have been sent.
  • --->
  • <cfset APPLICATION.Settings.PrevMessages = ArrayNew( 1 ) />
  •  
  •  
  • <!--- <br>
  • Check to see if our app settings file exists.
  • If it does, then we are going to want to pickup
  • where we left off.
  • --->
  • <cfif FileExists( APPLICATION.Settings.FilePath )>
  •  
  • <!--- Read in the XML data file. --->
  • <cffile
  • action="READ"
  • file="#APPLICATION.Settings.FilePath#"
  • variable="LOCAL.SettingsData"
  • />
  •  
  •  
  • <!---
  • Convert the XML data into the Application
  • settings structure. Do not store this
  • directly into the application as we don't
  • want to lose our file path. Plus, you never
  • know if the structure has changed for what
  • ever reason.
  • --->
  • <cfwddx
  • action="WDDX2CFML"
  • input="#LOCAL.SettingsData#"
  • output="LOCAL.Settings"
  • />
  •  
  •  
  • <!---
  • Check to see if we have the next message
  • data point and that it is a valid date.
  • --->
  • <cfif (
  • StructKeyExists( LOCAL.Settings, "NextMessage" ) AND
  • IsNumericDate( LOCAL.Settings.NextMessage )
  • )>
  •  
  • <!--- Store the setting value. --->
  • <cfset APPLICATION.Settings.NextMessage = LOCAL.Settings.NextMessage />
  •  
  • </cfif>
  •  
  •  
  • <!---
  • Check to see if we have the previous
  • messages data point and that it is a valid
  • data array..
  • --->
  • <cfif (
  • StructKeyExists( LOCAL.Settings, "PrevMessages" ) AND
  • IsArray( LOCAL.Settings.PrevMessages )
  • )>
  •  
  • <!--- Store the setting value. --->
  • <cfset APPLICATION.Settings.PrevMessages = LOCAL.Settings.PrevMessages />
  •  
  • </cfif>
  •  
  • </cfif>
  •  
  • </cflock>
  •  
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnRequestStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="Fires prior to page processing.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • />
  •  
  •  
  • <!---
  • Check to see if we are manually resetting the
  • application. We will know to do this if the
  • query param "reset" exists in the URL.
  • --->
  • <cfif StructKeyExists( URL, "reset" )>
  •  
  • <!---
  • Manually call the OnApplicationStart()
  • event method. Let the App method take care
  • of locking. We will not care at this point.
  • --->
  • <cfset THIS.OnApplicationStart() />
  •  
  • </cfif>
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnRequest"
  • access="public"
  • returntype="void"
  • output="true"
  • hint="Fires after pre-page processing is complete. Defines which template will actually be run for the request.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • />
  •  
  • <!--- Include the requested page. --->
  • <cfinclude template="#ARGUMENTS.TargetPage#" />
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  • </cfcomponent>

As you can see, we are converting the SMS message data into a ColdFusion query object. We are doing this because based on the XML attributes, our message selection needs to have dynamic criteria. Nothing is better suited to this than a ColdFusion query of queries (man those QoQs really rock hard core!).

The NextMessage time stamp is there to limit the number of SMS text message prompts that we receive each day. This application is going to be launched via a scheduled task (which can be set to fire as often as you like). In order for "affection" to seem more natural, the frequency of the SMS text messages needs to seem more random. The NextMessage date/time value will allow the scheduled task to be run repeatedly without launching so many message prompts.

The PrevMessages array is a way for the system to not prompt you for the same message too often. That would sound far to mechanical. This helps take the burden off of you, the ColdFusion programming enthusiast, from having to keep all the outgoing SMS text messages straight in your head.

Now that we have the application defined, we are going to employ a two part process for sending out the text messages. We cannot just blindly send them out - what happens if we left our phones at home? What happens if we are at lunch with our targeted loved one? Getting a text message at those times would obviously be bad and ruin the party. Therefore, the system will email you with a confirmation prompt. Here is the code that selects the message (notice the dynamic criteria ColdFusion query of queries):

  • <!--- Get the current time. --->
  • <cfset dtNow = Now() />
  •  
  • <!---
  • Check to see if this is a weekday. We only care about
  • doing this during the week when we are more than likely
  • NOT with our special someones. Additionally, we only want
  • this to be for work hours - 9AM - 6PM.
  •  
  • Additionally, we only want to send a message if we are
  • at or after the time of the next message slot.
  • --->
  • <cfif (
  • (DayOfWeek( dtNow ) GTE 2) AND
  • (DayOfWeek( dtNow ) LTE 6) AND
  • (Hour( dtNow ) GTE 9) AND
  • (Hour( dtNow ) LTE 18) AND
  • (Now() GTE APPLICATION.Settings.NextMessage)
  • )>
  •  
  •  
  • <!---
  • Based on the current time, create a time-only
  • data value. This will be used in our min/max
  • query criteria.
  • --->
  • <cfset dtTime = CreateTime(
  • Hour( dtNow ),
  • Minute( dtNow ),
  • Second( dtNow )
  • ) />
  •  
  •  
  • <!---
  • Query for valid messages based on the date
  • and time criteria.
  • --->
  • <cfquery name="qMessage" dbtype="query">
  • SELECT
  • id,
  • message
  • FROM
  • APPLICATION.Messages
  • WHERE
  • (
  • min_time IS NULL
  • OR
  • min_time <= <cfqueryparam value="#dtTime#" cfsqltype="CF_SQL_FLOAT" />
  • )
  • AND
  • (
  • max_time IS NULL
  • OR
  • max_time >= <cfqueryparam value="#dtTime#" cfsqltype="CF_SQL_FLOAT" />
  • )
  • AND
  • (
  • days IS NULL
  • OR
  • days LIKE <cfqueryparam value="%#LCase( DateFormat( dtNow, 'ddd' ) )#%" cfsqltype="CF_SQL_VARCHAR" />
  • )
  •  
  • <!---
  • Check to make sure we are not selecting a
  • recently used message.
  • --->
  • AND
  • id NOT IN (
  • <cfqueryparam value="#ArrayToList( APPLICATION.Settings.PrevMessages )#,0" cfsqltype="CF_SQL_INTEGER" list="yes" />
  • )
  •  
  • ORDER BY
  • id ASC
  • </cfquery>
  •  
  •  
  • <!---
  • Check to make sure that we have at least
  • one message to choose from.
  • --->
  • <cfif qMessage.RecordCount>
  •  
  •  
  • <!--- Select a random row for the query. --->
  • <cfset intMessage = RandRange(
  • 1,
  • qMessage.RecordCount
  • ) />
  •  
  •  
  • <!---
  • Send email for confirmation. We don't want to just
  • fire off these text messages without confirmation
  • or we might text our ladies at highly inappropriate
  • times (such as when we are currently with them).
  • --->
  • <cfmail
  • to="xyz@xxxxxxxxxx.com"
  • from="xyz@xxxxxxxxxx.com"
  • subject="Romantic SMS Text Message Confirmation"
  • type="HTML">
  •  
  • <div style="font-size: 18px ; line-height: 27px ;">
  •  
  • <p>
  • Hey Romeo, do you want to send out the
  • following text message:
  • </p>
  •  
  • <blockquote style="font-style: italic ;">
  • #qMessage[ "message" ][ intMessage ]#
  • </blockquote>
  •  
  • <p>
  • <br />
  • <br />
  • </p>
  •  
  • <p>
  • <a
  • href="http://#CGI.server_name##GetDirectoryFromPath( CGI.script_name )#confirm_message.cfm?id=#qMessage[ "id" ][ intMessage ]#"
  • >SEND TEXT MESSAGE</a>
  • </p>
  •  
  • </div>
  •  
  • </cfmail>
  •  
  • </cfif>
  •  
  • </cfif>

Notice that the bulk of the select message ColdFusion template is only run during the week and between the hours of 9am to 6pm and only if the current time is greater than or equal to the time of NextMessage. This is how we prevent too many text message email prompts from going out. Running that ColdFusion template will result in an email like this:

Hey Romeo, do you want to send out the following text message:

Wish I was at home with you.

SEND TEXT MESSAGE

If you read the text message and want to send it out, you simply click on the link "Send Text Message" and the text is sent out. The ColdFusion template responsible for sending out the SMS text message is confirm_message.cfm:

  • <!--- Param the URL variables. --->
  • <cftry>
  •  
  • <cfparam
  • name="URL.id"
  • type="numeric"
  • default="0"
  • />
  •  
  • <cfcatch>
  • <cfset URL.id = 0 />
  • </cfcatch>
  • </cftry>
  •  
  •  
  • <!--- Query for the given ID. --->
  • <cfquery name="qMessage" dbtype="query">
  • SELECT
  • message
  • FROM
  • APPLICATION.Messages
  • WHERE
  • id = <cfqueryparam value="#URL.id#" cfsqltype="CF_SQL_INTEGER" />
  • </cfquery>
  •  
  •  
  • <!---
  • Check to see if the passed ID matches a message
  • that we have defined in our application.
  • --->
  • <cfif qMessage.RecordCount>
  •  
  •  
  • <!---
  • Use the ColdFusion CFMail tag to send the
  • text message using the celluar carrier's
  • mobile phone email address.
  • --->
  • <cfmail
  • to="0123456789@vtext.com"
  • from="9876543210@vtext.com"
  • subject="">
  •  
  • <!--- Send the text part. --->
  • <cfmailpart
  • type="text"
  • >#qMessage.message#</cfmailpart>
  •  
  • </cfmail>
  •  
  •  
  • <!---
  • Now that the message has been sent, we want to select
  • a random interval of time only after which we can then
  • send out another text message. We don't want to send
  • them out too often, or she will suspect something.
  • Let's add between 2 and 8 hours. We are going to create
  • the time span with minutes (not hours) to get a more
  • random distribution.
  • --->
  • <cfset APPLICATION.Settings.NextMessage = (
  • Now() +
  •  
  • <!--- Randomly pick time interval. --->
  • CreateTimeSpan(
  • 0,
  • 0,
  • RandRange( (2 * 60), (8 * 60) ),
  • 0
  • )
  • ) />
  •  
  •  
  • <!---
  • Add this message ID to the array of previous messages
  • so that we don't have to mentally keep track of which
  • messages have already been sent.
  • --->
  • <cfset ArrayAppend(
  • APPLICATION.Settings.PrevMessages,
  • URL.id
  • ) />
  •  
  • <!---
  • We only want to keep track of the last three
  • message. If we have more than that, we need to pop
  • one off the top.
  • --->
  • <cfif (APPLICATION.Settings.PrevMessages.Size() GT 3)>
  •  
  • <!--- Pop the first one off. --->
  • <cfset ArrayDeleteAt(
  • APPLICATION.Settings.PrevMessages,
  • 1
  • ) />
  •  
  • </cfif>
  •  
  •  
  • <!---
  • At this point, our application settings have
  • been updated. Now, we just need to update our
  • data file in case our application crashes or
  • has to be reinitialized. Convert the settings
  • to WDDX.
  • --->
  • <cfwddx
  • action="CFML2WDDX"
  • input="#APPLICATION.Settings#"
  • output="REQUEST.SettingsData"
  • />
  •  
  •  
  • <!--- Write the app settings to disk. --->
  • <cffile
  • action="WRITE"
  • file="#APPLICATION.Settings.FilePath#"
  • output="#REQUEST.SettingsData#"
  • />
  •  
  •  
  • </cfif>
  •  
  •  
  • <cfoutput>
  •  
  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>Text Message Confirmation</title>
  • </head>
  • <body>
  •  
  • <!--- Check to see if a message was found. --->
  • <cfif qMessage.RecordCount>
  •  
  • <p>
  • The following message has been sent:
  • </p>
  •  
  • <blockquote>
  • #qMessage.message#
  • </blockquote>
  •  
  • <cfelse>
  •  
  • <p>
  • <em>The given message could not be found</em>.
  • </p>
  •  
  • </cfif>
  •  
  • </body>
  • </html>
  •  
  •  
  • </cfoutput>

Notice that the SMS text message is sent using the Verizon Wireless cellular phone email account and a CFMail tag. This is the easiest way to accomplish this task. Once the message does get sent out, we update the system - the next available message time is updated and the current message ID is appended to the previous messages. We are storing the application setting data as XML via WDDX. WDDX, while I have some issues with it, provides a really easy and fast way for us to serialize and deserialize simple data for simple uses.

The To/From vtext numbers are hard coded, but these could easily be part of the application settings structure. Frankly, I just didn't think of it till the application demo was already done.

Please note that this post is just in good fun and I am NOT really that sad :)




Reader Comments

If I did that I would be bound to be found out. I would be off sick one day when the message "I wish I was at home with you" would pop up on her phone. Then she would think I really meant to send the message to someone else......

Maybe the plot for my next sitcom!

Reply to this Comment

@Boyan,

Yeah the color coding I implemented a while back killed the code download :( I am working on fixing that. Sorry.

Reply to this Comment

@Ben,

yeah, I saw that. Thanks! You are awsome! Thanks for the compliment but still - make a wishlist. I'm sure people will be happy to buy you a thing or two. I can't beleive you don't have one yet with all the help/code you provide to the CF community.

Just something I noticed on your front page - under "Recent Snippets", the last "recent" entry is from Sep-28-2006. Not sure if that's by design but thought I'd mention it.

Reply to this Comment

Yeah the Snippets have basically fallen from grace. When I first started the blog I had this vision that I would blog about concepts and then provide examples via the Snippets section... but, once I really started going, what I realized was that I put the concepts AND snippets directly into the blog content. I tried duplicating the examples into the snippets as well, but that just because too much effort with too little time.

What I am planning to do is create a "Projects" section in the coldfusion section ( http://www.bennadel.com/coldfusion/ ) under which I will put documentation and snippets for bigger things like the POIUtility and SkinSpider and what not.

I will keep the snippets section linkable, but will probably remove it from the primary nav and the homepage. We shall see... its all up in the air at this point.

Reply to this Comment

Great piece of writing, I really liked the way you highlighted so me really important and significant points on ending-Random-SMS-Text-Messages-With-ColdFusion-To-Make-Her-Feel-Loved. Thanks so much, I appreciate your work.

Reply to this Comment

SMS Reseller

So informative things are provided here, I really happy to read this post about Sending Random SMS Text Messages With ColdFusion To Make Her Feel Loved, I was just imagine about it and you provided me the correct information I really bookmark it, for further reading, So thanks for sharing the information.
http://www.experttexting.com/sms-reseller/

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.