Sending Text Messages (SMS) With ColdFusion And CFMail
I have never played around with sending text message with ColdFusion (or anything non-cell-phone related), so I thought this morning would be a fun time to try it out. My initial thought was to try and use CFHttp to submit the text message forms provided on the individual carrier sites. I know that there are different ways to do it, but I figured I would give this a go first. Here is the CFHttp and CFHttpParam code that I used to mimic the form being submitted on Verizon's mobile site:
<cfhttp url="https://www.vtext.com/customer_site/jsp/disclaimer.jsp" method="POST" useragent="Mozilla / Firefox" result="objHTTP"> <!--- Set referrer. ---> <cfhttpparam type="CGI" name="referer" value="https://www.vtext.com/customer_site/jsp/messaging_lo.jsp" encoded="false" /> <!--- Include the original hidden form fields. ---> <cfhttpparam type="FORMFIELD" name="trackResponses" value="No" /> <cfhttpparam type="FORMFIELD" name="Send.x" value="Yes" /> <cfhttpparam type="FORMFIELD" name="translatorButton" value="" /> <cfhttpparam type="FORMFIELD" name="showgroup" value="n" /> <cfhttpparam type="FORMFIELD" name="DOMAIN_NAME" value="@vtext.com" /> <!--- Visible form fields. ---> <!--- To (number). ---> <cfhttpparam type="FORMFIELD" name="min" value="XXXXXXXXXX" /> <!--- Text message Content. ---> <cfhttpparam type="FORMFIELD" name="text" value="This is a test ColdFusion submission." /> <!--- Not sure what this is??? ---> <cfhttpparam type="FORMFIELD" name="message" value="" /> <!--- From (name or number). ---> <cfhttpparam type="FORMFIELD" name="subject" value="Ben Nadel" /> <!--- Reply-to number. ---> <cfhttpparam type="FORMFIELD" name="sender" value="XXXXXXXXXX" /> <!--- Call back number. ---> <cfhttpparam type="FORMFIELD" name="callback" value="" /> <!--- Message priority. ---> <cfhttpparam type="FORMFIELD" name="type" value="0" /> <!--- Count field (available characters). Your Message, Reply To Address and Callback Number fields all count toward the 160-character message length. ---> <cfhttpparam type="FORMFIELD" name="count" value="#(160 - 37)#" /> <!--- Form buttons. ---> <cfhttpparam type="FORMFIELD" name="Send" value="Send" /> <cfhttpparam type="FORMFIELD" name="Reset" value="Clear" /> <cfhttpparam type="FORMFIELD" name="disclaimer_submit" value="disclaimer_submit" /> </cfhttp>
That is HUGE and was a bit of a pain to create (Verizon has a confirmation page before you actually send it through). And that's just for one site! Imagine having to do that for each carrier? No thanks.
The other option is to use the mobile email addressed that most carriers provide. With these numbers, we can use ColdFusion and CFMail to send a text message to a mobile device. The first trick was to round up all the email addresses that the carriers use. With the use of Google, this was a fairly easy task. The next step was just setting up a simple web form:
<!--- Kill extra output. ---> <cfsilent> <!--- Param the form variable. ---> <cfparam name="FORM.from" type="string" default="" /> <cfparam name="FORM.to" type="string" default="" /> <cfparam name="FORM.provider" type="string" default="" /> <cfparam name="FORM.subject" type="string" default="" /> <cfparam name="FORM.message" type="string" default="" /> <cftry> <cfparam name="FORM.submitted" type="numeric" default="0" /> <cfcatch> <cfset FORM.submitted = 0 /> </cfcatch> </cftry> <!--- This is the data validation error array. We will use this to keep track of any data errors. ---> <cfset arrErrors = ArrayNew( 1 ) /> <!--- Let's build up a list of providers. Each provider will have a differen domain name for the mail usage. ---> <cfset objProviders = StructNew() /> <cfset objProviders[ "Verizon" ] = "vtext.com" /> <cfset objProviders[ "Sprint PCS" ] = "messaging.sprintpcs.com" /> <cfset objProviders[ "T-Mobile" ] = "tmomail.net" /> <cfset objProviders[ "Cingular" ] = "cingularME.com" /> <cfset objProviders[ "NexTel" ] = "messaging.nextel.com" /> <cfset objProviders[ "Virgin Mobile" ] = "vmobl.com " /> <!--- Check to see if the form has been submitted. ---> <cfif FORM.submitted> <!--- Strip out non-numeric data from To field. For now, we are only goint to allow phone numbers. ---> <cfset FORM.to = FORM.to.ReplaceAll( "[^\d]+", "" ) /> <!--- Validate form fields. ---> <cfif NOT Len( FORM.from )> <cfset ArrayAppend( arrErrors, "Please enter your FROM number" ) /> </cfif> <cfif NOT Len( FORM.to )> <cfset ArrayAppend( arrErrors, "Please enter your TO number" ) /> </cfif> <cfif NOT Len( FORM.message )> <cfset ArrayAppend( arrErrors, "Please enter your text message" ) /> </cfif> <!--- Check to see if we have any form validation errors. If we do not, then we can process the form. ---> <cfif NOT ArrayLen( arrErrors )> <!--- Check to see which provider was selected. If no provider was selected then we are just gonna try to loop over all of them. ---> <cfif NOT StructKeyExists( objProviders, FORM.provider )> <!--- Set the provider value to all keys in the provider struct. That will allow us to loop over them. ---> <cfset FORM.provider = StructKeyList( objProviders ) /> </cfif> <!--- Loop over the provider values to send the SMS text message. ---> <cfloop index="strProvider" list="#FORM.provider#" delimiters=","> <!--- When sending out the CFMail, be sure to put the full email address in the TO including the provider-specific domain. ---> <cfmail to="#FORM.to#@#objProviders[ strProvider ]#" from="#FORM.from#" subject="New Message" type="text"> <!--- Set the text part of the message. This allows us to sent a text message without destroying our beloved tabbing. ---> <cfmailpart type="text/plain" >#FORM.message#</cfmailpart> </cfmail> </cfloop> <!--- Send the user back to the same page with a new form (mostly so that they do not re-submit the form twice). I like to put in a RandRange() sometimes, just to make sure there is no strange caching taking place. ---> <cflocation url="#CGI.script_name#?#RandRange( 1, 100 )#" addtoken="false" /> </cfif> </cfif> </cfsilent> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title> Sending Text Messages (SMS) With ColdFusion And CFMail </title> </head> <body> <cfoutput> <!--- Check to see if we have any form validation errors to display. ---> <cfif ArrayLen( arrErrors )> <p> Please review the following issues: </p> <ul> <cfloop index="intError" from="1" to="#ArrayLen( arrErrors )#" step="1"> <li> #arrErrors[ intError ]# </li> </cfloop> </ul> </cfif> <form action="#CGI.script_name#" method="post"> <!--- This is our hidden value to flag that the form has been submitted (and is NOT loading for the first time). ---> <input type="hidden" name="submitted" value="1" /> <label for="from"> From: <input type="text" name="from" id="from" value="#FORM.from#" /> </label> <br /> <label for="to"> To: <input type="text" name="to" id="to" value="#FORM.to#" /> </label> <select name="provider"> <option value="">-- Not Sure --</option> <!--- Loop over providers. ---> <cfloop index="strName" list="#StructKeyList( objProviders )#" delimiters=","> <option value="#strName#" <cfif (FORM.provider EQ strName)> selected="true" </cfif> >#strName#</option> </cfloop> </select> <br /> <label for="message"> Message: <input type="text" name="message" id="message" value="#FORM.message#" maxlength="160" /> </label> <br /> <input type="submit" value="Send SMS Text Message" /> </form> </cfoutput> </body> </html>
The idea here is that you put in the To/From information and select the provider. Since each provider has it's own email address format, this will help us figure out which address format to use. If you are not sure which provider the recipient is using, the processing will loop over all the providers and send a CFMail message. If that works, why let them select a provider at all? Well, because sending potentially bad emails to multiple providers just feels wrong, doesn't it?
So, I know that this has all been done before (probably years ago), but I thought I would give it a go, see how it works. This is an easy way to send SMS text messages through ColdFusion if you do not have access to ColdFusion's event gateways (which I do not) and if I ever need to do this for some application, at least I have the code that will do it.
Want to use code from this post? Check out the license.
>> So, I know that this has all been done before (probably years ago)
Yep. I messed with it a few years ago using http. I had it integrated with a calendar I set up to remind me of meetings and such. Now I use Yahoo as they have text messaging built in. They have a better calendar too.
Now I just use it to find my cell phone. ;)
When you say you just use Yahoo, are you talking about an API for sending text messages? Or do you just mean as part of their calendar system?
Ooooh... they have an API? I *love* API's. There goes this weekend. ;)
But yeah, just the calendar app. I moved all my stuff to Google (gmail, docs, etc) but I haven't messed with their calendaring system yet.
Nice code. While using event gateways certainly seems like the "right" way to send SMS messages even a company like Southwest uses the email method you detail.
Great article, Ben. One thing that is important to note is that the various carriers place limits on the number of characters that could be in the text message. For example, Verizon Wireless restricts the length of the message to144 characters. To make matters more confusing, the different carriers have different upper limits to boot :(
At a minimum, make sure your app checks for the number of characters for the given provider, or always checks that it's fewer than the carrier with the lowest maximum message length.
Excellent point! And to even complicate things more, I believe that the Subject of the outgoing email is also included as part of the character limit (as it becomes part of the final text message).
As a lame-ass fix, I put a MaxLength of the Message field, but it is 160. Clearly this would break if maxed out since it doesn't take the Subject into account or the differences in carrier.
I guess the next step would be to figure out the limit for the different carriers, or to pick a lowest common value, such as 100 characters, that should satisfy them all.
Take a look at http://www.livejournal.com/tools/textmessage.bml?mode=details
It lists *all* of the SMS carriers and their message restrictions. Basically, most carriers specify an upper limit for the entire message and a sub-limit on the "from" field.
So, for the example of Verizon Wireless, it says that the message can only be 140 characters but of that 140, the from field can occupy no more than 34 characters.
I'd say that for a US-based audience, you need to keep the entire message to 120 characters but for an international audience, you probably want to be even more conservative and stay under 90.
Holy cow, that's like the most bad-ass text message resource link ever :)
Thanks a lot for bringing that to my attention. It is super useful.
Not a problem. I'm actually in the middle of building an SMS-sender application myself. Originally, we started with just an e-mail list but it just got to be too hard to keep the messages small enough. Now along comes you and you've written half the app for me so this was the least I could do :)
Team work is a beautiful thing :)
has anyone gotten into real SMS shortcodes?
Ive looked into this several times in the past, and it just never seemed like something I would be investing in 'for fun'.
Are there any new SMS shortcodes 'packages' out there that would allow the creation of a site/service around Text messaging without paying out the @ss for the shortcode and per-text fee's?
I haven't looked into any real SMS since I think they all require using the Enterprise-level gateways, which I do not have access to. I haven't even looked at prices since the above is prohibitive.
We use a shared short code service provided by an sms aggregator called Unwired Appeal. The cost is more reasonable if it is shared. However users do need to enter a specific 4 digit code at the beginning of each message to identify our account. I also use ColdFusion to send, receive, process and reroute messages. It works great.
I just took a look at the Unwired Appeal website. Looks like a nice site / set of services. Thanks for passing that along.
I have something similar working, but I have one question. I would like to allow messages longer than 120 characters. I have started a process that takes the message length and my goal is to have it send emails until the message is complete so it will email the entire message, just in chunks...however I am having problems.....any guess on how to accomodate this?
What problem are you running into? What aspect is not working?
thanks for the response. Well the only real problem is getting the remaining 120 characters each time. I know it is a combination of left, right and len statements but cna't seem to get the right combination. My thought was send the first 120 characters, set the remaining characters to a sting, send the next remaining 120 characters all within a loop until the entire grouping of emails was complete.
To be really basic, I think you are on the right track - grabbing 120 characters and then moving on. The only tricky part is when you want to make sure you don't cut a word in half.
This seems like an interesting little problem. Let me see if I can whip up a quick demo over lunch. I have an idea cooking.
I thought I would try and put something down on paper for you:
Let me know if that helps at all.
First of all, I would thanks very much for all the codes. It could take me months if I write my own.
I am developing a Register of Newsletter. The user will register their email address and cell phone to receive news via their email address and cell. All phones will have diff carriers.
And I wonder if your codes handle to send out a multi phone numbers with different carriers?
The worse thing I can do is to ask to them to select the carrier name along with their phone number (when they register) and store it in DB. Then when I send out the message, I will go thru the loop to send to each of them at a time. But I don't think it's good idea.
If you are going to be sending to a lot of people, I would maybe look into the shared SMS service rather than using the CFMail route. Apparently the cellular companies don't like people using mail to send SMS (they don't get money for it) and will ban your stuff if they catch on to it.
Yes we do have text message service.
So let go back to my earlier question is that how do I send an text message to multi cell?
Any advise please
My code does not handle multiple senders. However, does your SMS service require that? I would be surprised that they would need more than simply the number to text.
Well, My client has their own SMS service, I don't have to it any more.
U already finished two days of work. :)
This is the one i want to do
I'm am today officially embarking on engaging an SMS aggregator using coldfusion to send and receive sms short codes.
I got my dedicated IP setup today and was setting up the sms gateway.
Would you mind sharing with me some of the unseens that you've run into? Possibly some code snippets even?
I have not dealt with SMS gateways - I assume you are doing this in ColdFusion Enterprise Edition. You'll probably know more about this than myself :)
Do you know if there is a limit that an SMS gateway provider like AT&T or verizon imposes on the number of messages sent - either per day, per hour, or per month. I am wondering if there is a limit place on the message sender as to how many messages can actually be sent.
I would love to find out more information about setting up SMS gateways. We have been using a shared short code provider and they service has ben down for three weeks in the US so we are investigating more service providers and other options. I just stumbled upon the SMS gateway information for ColdFusion 9 and I'm trying to see how to leverage this.
Since we run a commercial SMS gateway, I can tell you straight off...its expensive in money AND time.
If your intention is for private business use, your better off with a shared short-code. Get another SC provider.
We still use an aggregator ourselves, albeit our own shortcode. and what does that get us? well for all intents and purposes, the only functional difference is that each text message has 1-less keyword parameter to type in. thats pretty much it.
Once we get to 1 million messages/month we'll attempt to directly contract with each of the US cellular businesses. (you will find it excruciatingly difficult to contract with any cellular directly unless you have demonstrated measurable (by their standards) usage requirements.
Several cellulars have gone to charging $500/contract. (the aggregator will pass that on to you in addition to their hefty monthly charges). keep that in mind.
Connor: what are your SMS intentions?
@matthew walsh, we are looking to send an SMS on every approved application that comes through and we were working with Clickatell, but there shared shortcodes were recently banned by US carriers due to some rogue users. They have worked to get it fixed, but we are looking at three weeks now and no change. We will be sending about 200-300 messages a day, so not much really. I am looking into other shared shortcode providers (CellTrust, Message-Media, and several more)
As a side note, what are the downsides to just using some code like Ben has here? Since we don't know the provider for each person, could we just send an email to every provider and the right one would go through? Doesn't seem ethical, but is there a way to find out the provider?
seems to me as part of your information collection process (application form), you could easily add a combobox to collect the users carrier.
the applicant is certainly motivated to provide the info so you'd be set.
outside of that email spamming would work too.
You dont hear alot about that method since most would be tight lipped about it.
me? i would not be surprised if those email portals monitor submittal IP's and eventually block very low matching recurring submittal IP addresses.
I've been using the cfmail option to send emails to user's cell phones for almost two years.
I usually send around 2,000 to 3,000 messages per day and have ran into lots of problems with the carriers blocking my messages after a certain number of connections in a certain time frame. They keep track of your IP address and label you as spam if you are sending too many messages. It's also important to have a valid DNS Pointer record to your sending server. I've gotten around the blocking by adding 4 more mail servers to send from and just cycle through the server connections at send time so the messages are evenly distributed over each server. I still reach the limits on heavy send days.
Another problem I've recently run into with the cfmail tag is when I specify the failto attribute the failto address shows up as the sent from address on the text message. What I am trying to do is show my user's email address as sent from (from) but have all rejected messages come back to me (failto). This would allow text message receivers to reply directly to the user that sent the message and allow me to manage bounced addresses... the problem is, it shows my email address instead of the sender's address when I use failto. If I remove failto, the sender's email address is shown as the sender but they also get all the bounced messages which isn't good.
Anyone have any thoughts on how I might be able to get around this little problem? Any ideas/thoughts how I might be able to make this process better would be greatly appreciated! I'd love to be able to use a SMS gateway service, but the cost is so high so I'm stuck with these hacks.
@Connor, @Matthew, @Matt,
I have heard a mixture of all of these problems from everyone who deals with SMS. I think the CFMail approach is good for very low-volume stuff. Above that, you probably gotta go with dedicated or shared short codes. Shared short codes, as you guys have already discussed are less expensive, but stlll pricey. The one shared short code that I played with was with TextMarks. They have a great API; but, they put ads (rather large ads) at the bottom of each SMS message. If you want to go ad-free, even with TextMarks, it costs like $1000/month for a significant amount of volume:
I've heard of people trying to get contracts going directly with the cellular carries and I'm told that's just a whole other nightmare that you don't want to deal with. I've actually heard that the cell carriers pretty much dismiss you until you can bring the a massive amount of volume.
I do wish there was an easier way in all of this.
# <cfset FORM.to = FORM.to.ReplaceAll(
# ) />
If I request a page containing this code:
<cfset tekst="de doodoodoo, de daa daa da">
I get the error
"The GetToken method was not found."
or am I overlooking something?
This is not a CF9 feature; it's actually a bit of a hack what I am doing there. Underlying *most* simple values in ColdFusion is a Java string (all of ColdFusion is built on top of some form a Java class or another). The Java string exposes the replaceAll() and replaceFirst() methods (among many others).
It's an undocumented / quasi excepted feature. If you are curious about it, take a look at this blog post:
Just talks about some of the underlying stuff.
In my implementation of this, the CFMailpart was causing my message body to display multipart MIME information. By simply removing the CFMailpart tags from my code, it works slick as ice.
Hmm, interesting. Glad you got it working without it.
Sir Ben, I was really having trouble of creating this SMS (computer to mobile phone) transactions. actually i was doing an on-line grading system where in the grades of the student are sent to their mobile phones.
Thank's for the information you shared. It really help mea lot.
I hope this works for me. I need to be able to send a text message to my dispatcher when we receive an emergency service request. Rather than make the user enter the texting info, I want to handle it through coldfusion and send it to the provider I know my dispatcher has on their phone so I should be able to simplify this.
Ben, this was a fabulous find. We have a low volume that needs to go out (like 5 to 10 a day) and this will work perfectly to prove the concept. Once again, amazing concept!
Does anyone know how to find out what domain a given phone number uses?
hi Ben Nadel.
i hv a confusion to use cfmail function to send sms
first of all mobileNo should be registered at service provide accroding to me understanding
i m putting in
message="this is nice help fron ben"
but no answer
have the no should register at messaging.nextel.com
or on other service provider by using their domain
any help will be greatly appreciated
can anyone tell me how to use Ben code
is number must be register first at service provider
e.g my number is 3456789675 and compay is telenor
at send to option i will write something like this
any help will be highly appreciated
I haven't read the article, yet, but I'm just glad to see it at the tippy top of Google's results. :D
Thanks for your code.
But I have checked the same in my local and live system, but it is not working.
Whether I have to change settings related things in CF Administrator for working the same.
I have tried the same like below,
>Hello huan, this is a test message</cfmailpart>
Can you please help where I fails?