Thursday, December 15, 2011

C# Text Messages by Email Queues


Summary
This tutorial shows how to simply send a text message (SMS) by Email and .

Description
There are two goals  The first is simple and described in the beginning, send a text message by email.  The second is to send text messages of unlimited length via email as text messages have a character length limit.  As an addition, we are using a queue data structure to get the job done.  The format of this article explains the concept of a code chunk then shows the entire code.

Before we begin
For the tutorial, take a look at the following:

Send Email C# - Example Only - Find the clsSmtpClient class in this post.

Send Text Messages
     Want to send a text message by email? It's easy, and free.  Compose a new email and send it to "your 10 digit number@smsgateway.com".  For example, my pretend Verizon phone number is (555)123-0987.  If someone wanted to send a text message to me, they would send an email to "5551230987@vtext.com".  This is free.  
     "number@vtext.com" will get the message to Verizon customers.  In order for this to work you will need to use the correct SMS gateway.  Thankfully, you can find a list of them here.
     Lastly, all text messages have a character limit of 160 characters.  I can only send 140 characters per email sent to "@vtext.com".  This means that if I write a 1000 character email and want to send it as a text message to someone, only the first 140 will be sent as a text message.  This could be different for each SMS gateway as I have only worked with the Verizon SMS gateway.


Queue the Queue
     Data structures class was one of my favorite classes.  To me, data structures bring organization to the processing of data in a way that just makes sense.   I like to use them whenever relevant/needed not only for what they do but also to practice using them.  In short, the queue is a collection of objects that processes objects in a first-in/first-out manner.
     As an example (analogy), the queue is like standing in line at the grocery store.  In this example, the people waiting in line are our objects in the queue.  The idea of getting into line is called, Enqueue.  The idea of calling the next person in the line to check-out is called, Dequeue.   People (objects) get into the single-file line (Enqueue) and are processed at the check-out (Dequeue) in the order which they got into the line (the queue).
     As a programming example, we have three strings we want to put into a queue:  Customer1, Customer2, and Customer3.  Let's pretend we already have a queue called "checkOutLine" for our string objects.  We get them into the queue (our grocery store check-out line) by saying:

checkOutLine.Enqueue(Customer1);
checkOutLine.Enqueue(Customer2);
checkOutLine.Enqueue(Customer3);

     You, the programmer, are at the counter waiting to check these Customers (and their strings) out.  We  call the next Customer in line up to the counter. While the Customer is at the counter, we take a look at what they have and then the Customer leaves the queue (Dequeue).

// For example

// This string represents the string of the customer we call to the counter to check-out...
string nextCustomer = "";

// Call the next customer in line to the counter
nextCustomer = checkOutLine.Dequeue();

// Do something with the nextCustomer string

     We can also iterate through all of the customers in line using a foreach loop:

foreach (string str in checkOutLine)
{
     // Do something with each customer until there are none in the queue
}

Send Text Messages, No Length Limit
     Well, technically this isn't true.  Due to the limitations of the Short Message Service (again SMS), we are limited to 160 characters.  For those interested in why, an SMS message can only contain 1120 bits  (Reference here).  The commonly used GSM 7-bit alphabet gives us 160 characters.  While it's possible to send a long SMS using a  User Data Header (reference here), we aren't going to cover it.
      Instead we are going to take the original message (of any length), chop the whole message into 140 character or less separate messages, place each message in a queue, and send each message as a separate email.

The clsMessageQueue Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SmsDemo
{
    public class clsMessageQueue
    {
        Queue<string> _messageQueue = new Queue<string>();
        string _wholeMessage;
        int _max_length;
        int _totalMessages;
        int _messageLength;

        public clsMessageQueue(String SmsMessage, int length)
        {
            // Pass the entire message in
            WholeMessage = SmsMessage;
         
            // Pass the desired max length of the SMS message
            Max_Length = length;
         
            // Set the message length based on the entire message
            MessageLength = WholeMessage.Length;

            // Start processing the message and ready it in the queue
            Setup();
        }


        public Queue<string> MessageQueue
        {
            get { return _messageQueue; }
        }

        public string getMessage()
        {
            return _messageQueue.Dequeue();
        }

        public void setMessage(string str)
        {
            _messageQueue.Enqueue(str);
        }

        public string WholeMessage
        { get { return _wholeMessage; } set { _wholeMessage = value; } }

        public int Max_Length
        { get { return _max_length; } set { _max_length = value; } }

        public int TotalMessages
        { get { return _totalMessages; } set { _totalMessages = value; } }

        public int MessageLength
        { get { return _messageLength; } set { _messageLength = value; } }


        private void Setup()
        {

            // Find the amount of messages we need to make
            // based on the length of the total message


            // If there is any remaining characters (remainder)
            // there will be an extra message with less than
            // 140 characters
            if (MessageLength % Max_Length > 0)
            {
                // divide the messageLength by the Max_Length
                // in order to get the amount of messages and
                // add one for the extra message
                TotalMessages = (MessageLength / Max_Length) + 1;
            }
            // Otherwise - there is no remainder
            else
                TotalMessages = (MessageLength / Max_Length);

            // The total times we loop is equal to the amount of message
            // we need to make (see the above if statement)
            for (int i = 0; i <= (TotalMessages - 1); i++)
            {

                // if the length of the message is less than the Max_length
                if (MessageLength <= Max_Length)
                {
                    // all we need to do is put the message in the queue
                    setMessage(WholeMessage);
                }

                // if the length of the message is more than the Max_length
                else if (MessageLength > Max_Length)
                {
                    // take the first 140 chars (Max_Length)
                    // and put this into the queue
                    setMessage(WholeMessage.Substring(0, Max_Length));
                 
                    // cut the first 140 chars (Max_length) out
                    WholeMessage = WholeMessage.Substring(Max_Length, (WholeMessage.Length - Max_Length));
                 
                    // reset the length of the message
                    MessageLength = WholeMessage.Length;
                }
            }
        }

    }
}



How do we use it?
     Now that we have a queue full of 140 character or less messages, we need to send them in the order that we put them in (first in, first out).  For this demo we simple text boxes to get user input, a button named "btnSend", the clsMessageQueue (above) to process the messages, and the clsSmtpClient class to send each message.



namespace SmsDemo
{
    public partial class SendSMS : System.Web.UI.Page
    {
        int MAX_LENGTH = 140;

        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnSend_Click(object sender, EventArgs e)
        {

             // Get the email of who this text is from
            string fromEmail = Server.HtmlEncode(txtSmsFrom.Text);
         
            // I'm assuming the phone number is for a Verizon subscriber
            string toEmail = Server.HtmlEncode(txtSmsTo.Text) + "@vtext.com";
            // Get the message we want to send from the user
            string messageBody = Server.HtmlEncode(txtMessageBody.Text);


            clsMessageQueue messageQueue = new clsMessageQueue(messageBody, MAX_LENGTH);

            /*
             * Logic tier - clsSmtpClient
             *      Mail logic is put in another class
             *      and implemented here concisely.
            */

            // Smtp Client - other settings in web.config for safeness.
            clsSmtpClient mySmtpClient = new clsSmtpClient(fromEmail,
                                                           "Sean");
            // set the to email address
            mySmtpClient.setToAddress(toEmail);


            // This is where we send all the messages.
            // For every 140 char or less message, we send an email
            // and because we're using a queue, they are being sent int
            // the order that we cut them up.
            foreach (string str in messageQueue.MessageQueue)
            {
                // set the message content
                mySmtpClient.setMessageBody(str);

                // Send the email!! - Hiz-zah's are in order.
                mySmtpClient.SendEmail();

                // Need to wait a couple seconds
                // Otherwise the messages may get out of
                // order when they hit the SMS gateway.
                System.Threading.Thread.Sleep(2000);

            }

            if (mySmtpClient.Complete)
            {
                // When sending the messages, everything went fine
            }

            else if (!mySmtpClient.Complete)
            {
                // Something happened when sending the messages

            }
        }


Done!!!

No comments:

Post a Comment