/* We use the HttpUtility class from the System.Web namespace * * If you see of the error "'HttpUtility' is not declared", you are probably * using a newer version of Visual Studio. You need to navigate to * Project | Properties | Application, * and select e.g. ".NET Framework 4" instead of ".NET Framework 4 Client Profile" as your 'Target framework'. * * Next, visit Project | Add reference, and select "System.Web" (specifically * System.Web - not System.Web.). */ using System.Net; using System; using System.Web; using System.Text; using System.IO; using System.Collections; namespace SMS { public class SendSMS { static void Main( ) { /* * Simply substitute your own username, password and phone number * below, and run the test code: */ string username = "username"; string password = "password"; /* * Your phone number, including country code, i.e. +44123123123 in this case: */ string msisdn = "447123123123"; string url = "{{ page.eapi_url_placeholder }}/submission/send_sms/2/2.0"; /* * A 7-bit GSM SMS message can contain up to 160 characters (longer messages can be * achieved using concatenation). * * All non-alphanumeric 7-bit GSM characters are included in this example. Note that Greek characters, * and extended GSM characters (e.g. the caret "^"), may not be supported * to all networks. Please let us know if you require support for any characters that * do not appear to work to your network. */ string seven_bit_msg = "Test message: all non-alphanumeric GSM characters: $@!#%&\",;:<>¡£¤¥§¿ÄÅÆÇÉÑÖØÜßàèéùìòå¿äöñüà\nGreek: ΩΘΔΦΓΛΩΠΨΣΘΞ"; /* * A Unicode SMS can contain only 70 characters. Any Unicode character can be sent, * including those GSM and accented ISO-8859 European characters that are not * catered for by the GSM character set, but note that mobile phones are only able * to display certain Unicode characters, based on their geographic market. * Nonetheless, every mobile phone should be able to display at least the text * "Unicode test message:" from the test message below. Your browser may be able to * display more of the characters than your phone. The text of the message below is: */ string unicode_msg = "Unicode test message: ☺ \nArabic: شصض\nChinese: 本网"; /* * There's a number of 8 bit messages that one can send to a handset, the most popular of the lot is Service Indication(Wap Push). * Some other popular ones are vCards and vCalendars, headers may vary depending on which of message one opts to send. * The User Data Header(UDH) is solely responsible for determining which * type of messages will be sent to ones' handset. * In a nutshell, SI(service indication) messages will have, in the final message body, both the UDH * and WSP(Wireless Session Protocol) appended to each other forming a prefix of the ASCII string of the Hex value * of the actual content. For example, suppose our intended Wap message body is as follows: * * Visit BulkSMS.com homepage * * Our headers will be -- UDH + WSP = FINAL_HEADER * '0605040B8423F0' + 'DC0601AE' = '0605040B8423F0DC0601AE' * * The UDH contains a destination port(0B84) and the origin port(23F0) * the WSP is broken down into the following: * * DC - Transaction ID (used to associate PDUs) * 06 - PDU type (push PDU) * 01 - HeadersLen (total of content-type and headers, i.e. zero headers) * AE - Content Type: application/vnd.wap.sic * * For this example our 8 bit message(what becomes our Wap Push) will look like this: * $msg = '0605040B8423F0DC0601AE02056a0045c60d0362756c6b736d732e636f6d00010356697369742042756c6b534d532e636f6d20686f6d6570616765000101'; * * You will only get UDH for both vCard and vCalendar type of 8 bit messages and no WSP, which will look something to this effect: * '06050423F4000' * * Now moving on and considering the example above, we will need to determine the type of message and get the header(s) * there of. * * string msg_type = "wap_push"; * string msg_body = "Visit BulkSMS.com homepage"; * string eight_bit_msg = get_headers( msg_type ) + xml_to_wbxml( msg_body ); */ string eight_bit_msg = "0605040B8423F0DC0601AE02056a0045c60d0362756c6b736d732e636f6d00010356697369742042756c6b534d532e636f6d20686f6d6570616765000101"; Hashtable result; /* * Upon a transient (retryable) error, sleep this many seconds: */ int sleep_time = 3; /* * The time it takes to retry transient errors will increase with * each retry attempt: */ int retry_growth_factor = 8; int num_retries = 5; string data = seven_bit_message( username, password, msisdn, seven_bit_msg ); for ( int x = 0; x < num_retries; x++ ) { result = send_sms( data, url ); if ((int)result["success"] == 1 ) { Console.WriteLine( formatted_server_response( result ) ); break; } else { Console.WriteLine( formatted_server_response( result ) ); } System.Threading.Thread.Sleep(sleep_time); sleep_time *= retry_growth_factor; } sleep_time = 3; data = eight_bit_message( username, password, msisdn, eight_bit_msg ); for ( int x = 0; x < num_retries; x++ ) { result = send_sms( data, url ); if ((int)result["success"] == 1 ) { Console.WriteLine( formatted_server_response( result ) ); break; } else { Console.WriteLine( formatted_server_response( result ) ); } System.Threading.Thread.Sleep(sleep_time); sleep_time *= retry_growth_factor; } sleep_time = 3; data = unicode_message( username, password, msisdn, unicode_msg ); for ( int x = 0; x < num_retries; x++ ) { result = send_sms( data, url ); if ((int)result["success"] == 1 ) { Console.WriteLine( formatted_server_response( result ) ); break; } else { Console.WriteLine( formatted_server_response( result ) ); } System.Threading.Thread.Sleep(sleep_time); sleep_time *= retry_growth_factor; } } public static string formatted_server_response( Hashtable result ) { string ret_string = ""; if( (int)result["success"] == 1 ) { ret_string += "Success: batch ID " + (string)result["api_batch_id"] + "API message: " + (string)result["api_message"] + "\nFull details " + (string)result["details"]; } else { ret_string += "Fatal error: HTTP status " + (string)result["http_status_code"] + " API status " + (string)result["api_status_code"] + " API message " + (string)result["api_message"] + "\nFull details " + (string)result["details"]; } return ret_string; } public static Hashtable send_sms( string data, string url ) { string sms_result = Post(url, data); Hashtable result_hash = new Hashtable(); string tmp = ""; tmp += "Response from server: " + sms_result + "\n"; string[] parts = sms_result.Split('|'); string statusCode = parts[0]; string statusString = parts[1]; result_hash.Add("api_status_code", statusCode); result_hash.Add("api_message", statusString); if(parts.Length != 3) { tmp += "Error: could not parse valid return data from server.\n"; } else { if ( statusCode.Equals("0") ) { result_hash.Add("success", 1); result_hash.Add("api_batch_id", parts[2]); tmp += "Message sent - batch ID " + parts[2] + "\n"; } else if (statusCode.Equals("1")) { // Success: scheduled for later sending. result_hash.Add("success", 1); result_hash.Add("api_batch_id", parts[2]); } else { result_hash.Add("success", 0); tmp += "Error sending: status code " + parts[0] + " description: " + parts[1] + "\n"; } } result_hash.Add("details", tmp); return result_hash; } public static string Post(string url, string data) { string result = null; try { byte[] buffer = Encoding.Default.GetBytes(data); HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(url); WebReq.Method = "POST"; WebReq.ContentType = "application/x-www-form-urlencoded"; WebReq.ContentLength = buffer.Length; Stream PostData = WebReq.GetRequestStream(); PostData.Write(buffer, 0, buffer.Length); PostData.Close(); HttpWebResponse WebResp = (HttpWebResponse)WebReq.GetResponse(); Console.WriteLine(WebResp.StatusCode); Stream Response = WebResp.GetResponseStream(); StreamReader _Response = new StreamReader(Response); result = _Response.ReadToEnd(); } catch (Exception ex) { Console.WriteLine(ex.Message); } return result.Trim()+"\n"; } public static string character_resolve(string body) { Hashtable chrs = new Hashtable(); chrs.Add('Ω', "Û"); chrs.Add('Θ', "Ô"); chrs.Add('Δ', "Ð"); chrs.Add('Φ', "Þ"); chrs.Add('Γ', "¬"); chrs.Add('Λ', "Â"); chrs.Add('Π', "º"); chrs.Add('Ψ', "Ý"); chrs.Add('Σ', "Ê"); chrs.Add('Ξ', "±"); string ret_str = ""; foreach ( char c in body ) { if( chrs.ContainsKey( c ) ) { ret_str += chrs[ c ]; } else { ret_str += c; } } return ret_str; } public static string seven_bit_message( string username, string password, string msisdn, string message ) { /******************************************************************** * Construct data * *********************************************************************/ /* * Note the suggested encoding for the some parameters, notably * the username, password and especially the message. ISO-8859-1 * is essentially the character set that we use for message bodies, * with a few exceptions for e.g. Greek characters. For a full list, * see: https://www.bulksms.com/developer/eapi/submission/character-encoding/ */ string data = ""; data += "username=" + HttpUtility.UrlEncode(username, System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&password=" + HttpUtility.UrlEncode(password, System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&message=" + HttpUtility.UrlEncode(character_resolve(message), System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&msisdn=" + msisdn; data += "&want_report=1"; return data; } public static string unicode_message( string username, string password, string msisdn, string message ) { /******************************************************************** * Construct data * *********************************************************************/ /* * Note the suggested encoding for the some parameters, notably * the username, password and especially the message. ISO-8859-1 * is essentially the character set that we use for message bodies, * with a few exceptions for e.g. Greek characters. For a full list, * see: https://www.bulksms.com/developer/eapi/submission/character-encoding/ */ string data = ""; data += "username=" + HttpUtility.UrlEncode(username, System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&password=" + HttpUtility.UrlEncode(password, System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&message=" + stringToHex( message ); data += "&msisdn=" + msisdn; data += "&dca=16bit"; data += "&want_report=1"; return data; } public static string eight_bit_message( string username, string password, string msisdn, string message ) { /******************************************************************** * Construct data * *********************************************************************/ /* * Note the suggested encoding for the some parameters, notably * the username, password and especially the message. ISO-8859-1 * is essentially the character set that we use for message bodies, * with a few exceptions for e.g. Greek characters. For a full list, * see: https://www.bulksms.com/developer/eapi/submission/character-encoding/ */ /* * In the following $udh string, 0B84 is a destination port and 23F0 is the origin port. */ string udh = "0605040B8423F0"; /* * $wsp_header is broken down into the following: * * DC - Transaction ID (used to associate PDUs) * 06 - PDU type (push PDU) * 01 - HeadersLen (total of content-type and headers, i.e. zero headers) * AE - Content Type: application/vnd.wap.sic */ string wsp_header = "DC0601AE"; string wap_push_message = udh + wsp_header + message; string data = ""; data += "username=" + HttpUtility.UrlEncode(username, System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&password=" + HttpUtility.UrlEncode(password, System.Text.Encoding.GetEncoding("ISO-8859-1")); data += "&message=" + wap_push_message; data += "&msisdn=" + msisdn; data += "&dca=8bit"; data += "&want_report=1"; return data; } public static string get_headers( string msg_type ) { string headers = ""; if( msg_type == "wap_push" ) { string udh = "0605040B8423F0"; string wsp = "DC0601AE"; headers += udh + wsp; } else if( msg_type == "vCard" || msg_type == "vCalendar" ) { headers += "06050423F40000"; } return headers; } public static string xml_to_string( string msg_body ) { //TODO /* * Code to convert 'msg_body' will go in here. */ return "conversion"; } public static string stringToHex(string s){ string hex = ""; foreach (char c in s) { int tmp = c; hex += String.Format("{0:x4}", (uint)System.Convert.ToUInt32(tmp.ToString())); } return hex; } } }