using System; using System.IO; using System.Net; using Interop.Clickatell; namespace Neo.Afx.WinService.Messages { /// /// A wrapper class for sending SMS's using the Clickatell (Vodazone) API. /// public class SmsVodazone : ISmsSender { private string ApiID { get; set; } private string UserName { get; set; } private string Password { get; set; } #region Initialization /// /// Initializes a new instance of the class /// by using the given values. /// /// The API ID to be queried. /// The user name to be queried. /// The password to be queried. public SmsVodazone(string apiID, string userName, string password) { try { ApiID = apiID; UserName = userName; Password = password; var reply = Authenticate(); string replyText; if (!ReplyOk(reply, "OK: ", out replyText)) { throw new Exception(replyText); } } catch (Exception ex) { throw new Exception(GetInnermostMessage(ex)); } } #endregion #region Credits /// /// Gets the number of credits left. /// public int Credits { get { var balance = QueryBalance(); string credits; if(ReplyOk(balance, "Credit: ", out credits)) { if (credits.Contains(".")) { credits = credits.Substring(0, credits.IndexOf(".")); } return (int)float.Parse(credits); } return 0; } } #endregion #region Send /// /// Sends the given message to the given cell number. /// /// The message to be sent. /// The cell number to which the message is sent. /// When this method returns, contains the error message if /// the SMS was not sent successfully; otherwise contains a null references. /// /// true if successful; false otherwise. /// public bool Send(string message, string cellNumber, out string error) { var successful = true; try { string replyText; var reply = SendMsg(message, cellNumber); if(ReplyOk(reply, "ID: ", out replyText)) { #region Check if successful reply = QueryMsg(replyText); if(ReplyOk(reply, "Status: ", out replyText)) { var messageStatus = (eSMSMsgStatus)Int32.Parse(replyText); error = messageStatus.ToString(); #region Set successful based on message status switch(messageStatus) { case eSMSMsgStatus.SMS_MSG_CANCELLED: successful = false; break; case eSMSMsgStatus.SMS_MSG_DELIVERED: break; case eSMSMsgStatus.SMS_MSG_ERR_DELIVERING_MSG: successful = false; break; case eSMSMsgStatus.SMS_MSG_ERR_WITH_MSG: successful = false; break; case eSMSMsgStatus.SMS_MSG_EXPIRED: successful = false; break; case eSMSMsgStatus.SMS_MSG_OK: break; case eSMSMsgStatus.SMS_MSG_QUEUED: break; case eSMSMsgStatus.SMS_MSG_QUEUED_LATER_DELIV: break; case eSMSMsgStatus.SMS_MSG_RECEIVED: break; case eSMSMsgStatus.SMS_MSG_ROUTING_ERROR: successful = false; break; case eSMSMsgStatus.SMS_MSG_UNKNOWN: break; } #endregion } else { error = replyText; successful = false; } #endregion } else { error = replyText; successful = false; } } catch(Exception ex) { error = GetInnermostMessage(ex); successful = false; } return successful; } #endregion #region ReplyOk static bool ReplyOk(string reply, string tag, out string message) { const string Marker = "ERR: "; message = null; if(!String.IsNullOrEmpty(reply)) { var p1 = reply.IndexOf(Marker); if(p1 == -1) { p1 = reply.IndexOf(tag); message = p1 == -1 ? reply : reply.Substring(p1 + tag.Length); return true; } // An error occurred so get error message message = reply.Substring(p1 + Marker.Length); } return false; } #endregion #region GetInnermostMessage public string GetInnermostMessage(Exception ex) { if (ex.InnerException == null) { return ex.Message; } else { return GetInnermostMessage(ex.InnerException); } } #endregion #region Helper Methods private string Authenticate() { return RequestGET("auth",""); } private string QueryBalance() { return RequestGET("getbalance", ""); } private string SendMsg(string message, string cellNumber) { return RequestGET("sendmsg", "to=" + cellNumber + "&text=" + message); } private string QueryMsg(string replyText) { return RequestGET("querymsg", "apimsgid=" + replyText); } public string RequestGET(string action, string queryString) { try { var baseUri = String.Format("https://api.clickatell.com/http/{0}?user={1}&password={2}&api_id={3}", action ,UserName, Password, ApiID); baseUri += "&" + queryString; HttpWebRequest request = (HttpWebRequest) WebRequest.Create(baseUri); request.KeepAlive = false; request.ProtocolVersion = HttpVersion.Version10; request.Method = "GET"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string result = ""; using (StreamReader rdr = new StreamReader(response.GetResponseStream())) { result = rdr.ReadToEnd(); } return result; } catch (Exception ex) { return "ERROR: " + GetInnermostMessage(ex); } } #endregion } }