Last week I attended the NEBytes technology user group for the first time. Despite the fact I didn't actually say more than two words (speaking to a real live human is only marginally easier than flying without wings) I did enjoy the two talks that were given.

The first of these was for Twilio, a platform for text messaging and Voice over IP (VoIP). This platform provides you with the ability to send and receive SMS messages, or even create convoluted telephone call services where you can prompt the user with options, capture input, record messages, redirect to other phones... and all fairly painlessly. I can see all sorts of interesting uses for the services they offer. Oh, and the prices seem reasonable as well.

All of this is achieved using a simple REST API which is pretty impressive.

My immediate use case for this is for alert notifications as, like any technology, sometimes emails fail or are not accessible. I also added two factor authentication to in under 5 minutes which I thought was neat (although in fairness, with the Identity Framework all I had to do was fill in the blanks for the Smsservice and uncomment some boilerplate code).

In this article, I'll show you just how incredibly easy it is to send text messages.

Getting an account

The first thing you need is a Twilio account - so go sign up. You don't need to shell out any money at this stage, the example program I will present below will work perfectly well with their trial account and not cost a penny.

Once you've signed up you'll need to validate a real phone number of your own for security purposes, and then you'll need to buy a phone number that you will use for your SMS services.

You get one phone number for free with your trial account. When you are ready to upgrade to a unrestricted account, each phone number you buy costs $1 a month (yes, that's one dollar), then $0.0075 to receive a SMS message or $0.04 to send one. (Prices correct at time of writing). For high volume businesses, short codes are also available, but these are very expensive.

You'll need to get your API credentials too - this is slightly hidden, but if you go to your Twilio account portal and look in the upper right section of the page there is a link titled Show API Credentials - click this to get your Account SID and Auth Token.

Creating a simple application

Twilio offers client libraries for a raft of languages, and support for .NET is no exception by using the twilio-csharp client, which of course has a NuGet package. Lots of packages actually, but we just need the core.

Install-Package Twilio

Now you're set!

To send a message, you create an instance of the TwilioRestClient using your Account SID and Auth Token and call SendSmsMessage with your Twilio phone number, the number of the phone to send the message to, and of course the message itself. And that's pretty much it.

static void Main(string[] args)
  SendSms("077xxxxxxxx", "Sending messages couldn't be simpler!");

private static void SendSms(string to, string message)
  TwilioRestClient client;
  string accountSid;
  string authToken;
  string fromNumber;

  accountSid = "DF8A228F5D66403E973E714324D5816D"; // no, these are not real
  authToken = "942CA384E3CC4107A10BA58177ACF88B";
  fromNumber = "+44191xxxxxxx";

  client = new TwilioRestClient(accountSid, authToken);

  client.SendSmsMessage(fromNumber, to, message);

The SendSmsMessage method returns a SMSMessage object which has various attributes relating to the sent message - such as the cost of sending it.

Apologies for the less-than-perfect photo, but the image below shows my Lumia 630 with the received message.

Not the best photo in the world, but here is a sample message
Not the best photo in the world, but here is a sample message

Sharp eyes will note that the message is prefixed with Sent from your Twilio trial account - this prefix is only for trial accounts, and there will be no adjustment of your messages once you've upgraded.

Simple API's aren't so simple

There's one fairly awkward caveat with this library however - exception handling. I did a test using invalid credentials, and to my surprise nothing happened when I ran the sample program. I didn't receive a SMS message of course, but neither did the sample program crash.

This is because for whatever reason, the client doesn't raise an exception if the call fails. Instead, it is essentially returned as a result code. I mentioned above that the SendSmsMessage return a SMSMessage object. This object has a property named RestException. If the value of this property is null, everything is fine, if not, then your request wasn't successful.

I really don't like this behaviour, as it means now I'm responsible for checking the response every time I send a message, instead of the client throwing an exception and forcing me to deal with issues.

The other thing that irks me with this library is that the RestException class has Status and Code properties, which are the HTTP status code and Twilio status code respectively. But for some curious reason, these numeric properties are defined as strings, and so if you want to process them you'll have to both convert them to integers and make sure that the underlying value is a number in the first place.

private static void SendSms(string to, string message)
  ... <snip> ...
  SMSMessage result;

  ... <snip> ...

  result = client.SendSmsMessage(fromNumber, to, message);

  if (result.RestException != null)
    throw new ApplicationException(result.RestException.Message);

Although I don't recommend you use ApplicationException! Something like this may be more appropriate:

if (result.RestException != null)
  int httpStatus;

  if (!int.TryParse(result.RestException.Status, out httpStatus))
    httpStatus = 500;

  throw new HttpException(httpStatus, result.RestException.Message);

There's also a Status property on the underlying SMSMessage class which can be failed. Hopefully the RestException property is always set for failed statuses otherwise that's something else you'd have to remember to check.

However you choose to do it, you probably should ensure that you do check for a failed / exception response, especially if the messages are important (for example two-factor authentication codes).

Long Codes vs Short Codes

By default, Twilio uses long codes (also known as "normal" phone numbers). According to their docs, these are rate limited to 1 message per second. I did a sample test where I spammed 10 messages one after another. I received the first 5 right away, and the next five about a minute later. So if you have a high volume service, it's possible that your messages may be slightly delayed. One the plus side, it does seem to be fire and forget, you don't need to manually queue messages yourself and they don't get lost.

Twilio also supports short codes (e.g. send STOP to 123456 to opt out of this list you never opted into in the first place), which are suitable for high traffic - 30 messages a second apparently. However, these are very expensive and have to be leased from the mobile operators, a process which takes several weeks.

Advanced Scenarios

As I mentioned in my intro, there's a lot more to Twilio than just sending SMS messages, although for me personally that's going to be a big part of it. But you can also read and process messages, in other words when someone sends a SMS to your Twilio phone number, it will call a custom HTTP endpoint in your application code, where you can then read the message and process it. This too is something I will find value in, and I'll cover that in another post.

And then there's some pretty impressive options for working with real phone calls (along with the worst robot sounding voice in history). Not entirely sure I will cover this as it's not immediately something I'd make use of.

Take a look at their documentation to see how to use their API's to build SMS/VoIP functionality into your services.

Update History

  • 2015-07-24 - First published
  • 2020-11-21 - Updated formatting

Like what you're reading? Perhaps you like to buy us a coffee?

Donate via Buy Me a Coffee

Donate via PayPal


# jigesh

it is very help full.