Main Site Documentation

SMS Gateway Help


#1

Hi,
I’m trying to send a text message (SMS) with a CANxtra. I use the sms gateway provided by my telephone company: https://www.bibob.dk/SmsSender.asmx.
I am trying to modify this Powershell script: http://www.xipher.dk/WordPress/?p=616.
The only thing I have changed is that I have added the “deliveryReport”, as I thought it might be needed. See this link:
https://www.bibob.dk/SmsSender.asmx?op=SendMessage, I have also changed the server to https://www.bibob.dk/ instead of https://www.bibob.dk/SmsSender.asmx, as the host header is read only.

Here is my code (I have replaced my username and password with x’s):


using System;
using System.IO;
using System.Net;
using System.Text;

using Microsoft.SPOT;

namespace SMSSender
{
    class SMS
    {        
        public void SendSMS(int number, string message)
        {            
            if (number.ToString().Length != 8)
            {
                Debug.Print("Number has to be 8 digits");
                return;
            }            
            string username = "xxxxxxxx";//My phonenumber
            string password = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//Converted to MD5 Hash
            string server = "https://www.bibob.dk/";

            string XMLString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            XMLString += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
            XMLString += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"";
            XMLString += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
            XMLString += "<soap:Body><SendMessage xmlns=\"http://www.bibob.dk/\">";
            XMLString += "<cellphone>"+ username + "</cellphone>";
            XMLString += "<password>" + password + "</password>";
            XMLString += "<smsTo><string>" + number.ToString() +"</string></smsTo>";
            XMLString += "<smscontents>" + message + "</smscontents>";
            XMLString += "<fromNumber>" + username + "</fromNumber>";
            XMLString += "<deliveryReport>" + false + "</deliveryReport>";
            XMLString += "</SendMessage></soap:Body></soap:Envelope>";

            Byte[] bytesToSend = Encoding.UTF8.GetBytes(XMLString);
           
            HttpWebRequest myWebRequest = (HttpWebRequest)WebRequest.Create(server) as HttpWebRequest;
            myWebRequest.Method = "POST";            
                            
            myWebRequest.Headers.Add("Man", "POST /SmsSender.asmx HTTP/1.1");            
            myWebRequest.ContentType = "text/xml; charset=utf-8";                                   
            myWebRequest.ContentLength = bytesToSend.Length;            
            myWebRequest.Headers.Add("SOAPAction", "http://www.bibob.dk/SendMessage");

            using(Stream outputStream = myWebRequest.GetRequestStream())
                outputStream.Write(bytesToSend, 0, bytesToSend.Length);                       
        }                       
    }
}

Bassicly I got two questions:
At this link: https://www.bibob.dk/SmsSender.asmx?op=SendMessage under SOAP 1.1 it says that the first header must be:
POST /SmsSender.asmx HTTP/1.1

He does it this way in the Powershell script:
$objHTTP.setRequestHeader(‘Man’, ‘POST’ + ’ ’ + $SoapServer + ’ HTTP/1.1’)

Is it correct just to do in C#?
myWebRequest.Headers.Add(“Man”, “POST /SmsSender.asmx HTTP/1.1”);

Is it correct to use a HttpWebRequest? I though about using sockets, and then just send the data, but then I can not set the headers, needed for it to work.

Btw if I run the code, if throws an exception when trying to get the request stream:

using(Stream outputStream = myWebRequest.GetRequestStream())

.

This is the debug output:


 #### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (1) ####
    #### Message: 
    #### Microsoft.SPOT.Net.SocketNative::getaddrinfo [IP: 0000] ####
    #### System.Net.Dns::GetHostEntry [IP: 0008] ####
    #### System.Net.HttpWebRequest::EstablishConnection [IP: 00e1] ####
    #### System.Net.HttpWebRequest::SubmitRequest [IP: 0013] ####
    #### System.Net.HttpWebRequest::GetRequestStream [IP: 0008] ####
    #### SMSSender.SMS::SendSMS [IP: 0112] ####
    #### CANxtra_Webserver_LCD.Program::Main [IP: 006a] ####
    #### SocketException ErrorCode = -1
    #### SocketException ErrorCode = -1
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in Microsoft.SPOT.Net.dll
    #### SocketException ErrorCode = -1
    #### SocketException ErrorCode = -1
    #### Exception System.Net.WebException - 0x00000000 (1) ####
    #### Message: host not available
    #### System.Net.HttpWebRequest::EstablishConnection [IP: 00f1] ####
    #### System.Net.HttpWebRequest::SubmitRequest [IP: 0013] ####
    #### System.Net.HttpWebRequest::GetRequestStream [IP: 0008] ####
    #### SMSSender.SMS::SendSMS [IP: 0112] ####
    #### CANxtra_Webserver_LCD.Program::Main [IP: 006a] ####
A first chance exception of type 'System.Net.WebException' occurred in System.Http.dll
A first chance exception of type 'System.Net.WebException' occurred in System.Http.dll
An unhandled exception of type 'System.Net.WebException' occurred in System.Http.dll

Additional information: host not available

I do not have much experience with XML, so any help would be much appreciated :slight_smile:


#2

[quote]Is it correct just to do in C#?
myWebRequest.Headers.Add(“Man”, “POST /SmsSender.asmx HTTP/1.1”); [/quote]

Wrong. You don’t need to do that at all. HttpWebRequest object will do it for you based on Method property.


#3

Okay I tried to uncomment the part after:
myWebRequest.Method = “POST”;

But then throws an exception, that you have to set the contentlength. So I did, the same way as I did before:
myWebRequest.ContentLength = bytesToSend.Length;

But it still not working. I have tried changing server to https://www.bibob.dk/SmsSender.asmx as well, but that it still throws an exception the same place. Outputting: “Additional information: host not available” :frowning:


#4

Look at the link:

It shows what the post message should look like:


POST /SmsSender.asmx HTTP/1.1
Host: www.bibob.dk
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.bibob.dk/SendMessage"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <SendMessage xmlns="http://www.bibob.dk/">
      <cellphone>string</cellphone>
      <password>string</password>
      <smsTo>
        <string>string</string>
        <string>string</string>
      </smsTo>
      <smscontents>string</smscontents>
      <fromNumber>string</fromNumber>
      <deliveryReport>boolean</deliveryReport>
    </SendMessage>
  </soap:Body>
</soap:Envelope>


#5

Okay. I changed my code to this:


 public void SendSMS(int number, string message)
        {            
            if (number.ToString().Length != 8)
            {
                Debug.Print("Number has to be 8 digits");
                return;
            }            
            string username = "xxxxxxxx";
            string password = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//Converted to MD5 Hash
            string server = "https://www.bibob.dk/";
            //string server = "https://www.bibob.dk/SmsSender.asmx";

            string XMLString = "POST /SmsSender.asmx HTTP/1.1";
            XMLString += "Host: www.bibob.dk";
            XMLString += "Content-Type: text/xml; charset=utf-8";
            XMLString += "Content-Length: " + message.Length;
            XMLString += "SOAPAction: \"http://www.bibob.dk/SendMessage\"";
            XMLString += "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            XMLString += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
            XMLString += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"";
            XMLString += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
            XMLString += "<soap:Body><SendMessage xmlns=\"http://www.bibob.dk/\">";
            XMLString += "<cellphone>"+ username + "</cellphone>";
            XMLString += "<password>" + password + "</password>";
            XMLString += "<smsTo><string>" + number.ToString() +"</string></smsTo>";
            XMLString += "<smscontents>" + message + "</smscontents>";
            XMLString += "<fromNumber>" + username + "</fromNumber>";
            XMLString += "<deliveryReport>" + false + "</deliveryReport>";
            XMLString += "</SendMessage></soap:Body></soap:Envelope>";

            Byte[] bytesToSend = Encoding.UTF8.GetBytes(XMLString);
           
            HttpWebRequest myWebRequest = (HttpWebRequest)WebRequest.Create(server) as HttpWebRequest;
            myWebRequest.Method = "POST";
            myWebRequest.ContentLength = bytesToSend.Length;

            Debug.Print("Send SMS");
            using(Stream outputStream = myWebRequest.GetRequestStream())
                outputStream.Write(bytesToSend, 0, bytesToSend.Length);
            Debug.Print("Message has been sent");          
        }           

But it still not working…


#6

This is your content:


<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <SendMessage xmlns="http://www.bibob.dk/">
      <cellphone>string</cellphone>
      <password>string</password>
      <smsTo>
        <string>string</string>
        <string>string</string>
      </smsTo>
      <smscontents>string</smscontents>
      <fromNumber>string</fromNumber>
      <deliveryReport>boolean</deliveryReport>
    </SendMessage>
  </soap:Body>
</soap:Envelope>

Method ,Content type and content length you set through properties:


myWebRequest.Method = "POST";
myWebRequest.ContentType = "text/xml; charset=utf-8";                                   
myWebRequest.ContentLength = bytesToSend.Length;

Host and SOAPAction you add to the Headers dictionary:


myWebRequest.Headers.Add("SOAPAction", "http://www.bibob.dk/SendMessage");
myWebRequest.Headers.Add("Host", "www.bibob.dk");


#7

I have tried that, and it does not work.
And you can not set the host header, as it will print this exception:
“Additional information: Cannot update restricted header: Host”

See this page for more information: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.host.aspx .


#8

Ok I guess host is automatic then. Leave it out and try.


#9

Already done that, and it’s not working :frowning:


#10

Set your server variable to:

If it doesn’t work then use


#11

I have also done that. I was actually hoping I was doing something totally wrong, because I have tried to adjust so many of the variables :frowning:


#12

Ok, can you post your final version here


#13

Of couse. I have left all as it was, so you can see all the things i tried:


using System;
using System.IO;
using System.Net;
using System.Text;

using Microsoft.SPOT;

namespace SMSSender
{
    class SMS
    {        
        public void SendSMS(int number, string message)
        {            
            if (number.ToString().Length != 8)
            {
                Debug.Print("Number has to be 8 digits");
                return;
            }            
            string username = "xxxxxxxx";
            string password = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//Converted to MD5 Hash
            //string server = "https://www.bibob.dk/";
            string server = "https://www.bibob.dk/SmsSender.asmx";
            //string server = "https://www.bibob.dk/SmsSender.asmx/SendMessage";

            /*string XMLString = "POST /SmsSender.asmx HTTP/1.1";
            XMLString += "Host: www.bibob.dk";
            XMLString += "Content-Type: text/xml; charset=utf-8";
            XMLString += "Content-Length: " + message.Length;
            XMLString += "SOAPAction: \"http://www.bibob.dk/SendMessage\"";*/
            string XMLString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            XMLString += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
            XMLString += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"";
            XMLString += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
            XMLString += "<soap:Body><SendMessage xmlns=\"http://www.bibob.dk/\">";
            XMLString += "<cellphone>"+ username + "</cellphone>";
            XMLString += "<password>" + password + "</password>";
            XMLString += "<smsTo><string>" + number.ToString() +"</string></smsTo>";
            XMLString += "<smscontents>" + message + "</smscontents>";
            XMLString += "<fromNumber>" + username + "</fromNumber>";
            XMLString += "<deliveryReport>" + false + "</deliveryReport>";
            XMLString += "</SendMessage></soap:Body></soap:Envelope>";

            Byte[] bytesToSend = Encoding.UTF8.GetBytes(XMLString);
           
            HttpWebRequest myWebRequest = (HttpWebRequest)WebRequest.Create(server) as HttpWebRequest;
            myWebRequest.Method = "POST";

            myWebRequest.ContentType = "text/xml; charset=utf-8";
            myWebRequest.ContentLength = bytesToSend.Length;

            myWebRequest.Headers.Add("SOAPAction", "http://www.bibob.dk/SendMessage");
            //myWebRequest.Headers.Add("Host", "www.bibob.dk");

            /*
            myWebRequest.ContentLength = bytesToSend.Length;                            
            myWebRequest.Headers.Add("Man", "POST /SmsSender.asmx HTTP/1.1");            
            myWebRequest.ContentType = "text/xml; charset=utf-8";                                   
            myWebRequest.ContentLength = bytesToSend.Length;            
            myWebRequest.Headers.Add("SOAPAction", "http://www.bibob.dk/SendMessage");
            */

            Debug.Print("Send SMS");
            using(Stream outputStream = myWebRequest.GetRequestStream())//THis is where it throws an exception
                outputStream.Write(bytesToSend, 0, bytesToSend.Length);
            Debug.Print("Message has been sent");          
        }                       
    }
}


#14

Ok, final suggestion. Try to make it work in regular .Net app on your PC first. Also get the response and see what error is returned there if anything.


#15

Okay, I will try that and then post my progress :slight_smile:
Thank you for your help so far!!!


#16

I found this page (http://translate.google.com/translate?sl=da&tl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fphpgeek.dk%2Fblog%2F2008%2F03%2F01%2Fen-billig-sms-gateway-l%25C3%25B8sning-ja-det-er-muligt%2F&act=url - translated to english) by a user who made a php-script.
I only had to modify it a bit to get it working (it was a bit outdated). This is the final code:


<?php
/**
 * BiBoB SMS Gateway Class
 * 
 * Class using the BiBoB Webservice to send out SMS messages.
 * Furthermore there is a few of utilities functions that can be used too.
 * 
 * If you have any questions - feel free to contact me.
 * 
 * Developed by:
 * Johan Holst Nielsen
 * johan@ phpgeek.dk
 * www.phpgeek.dk
 * 
 * Use it as you want - and distribute is as you want - but please leve this message.
 *
 * Read more about BiBoB at www.bibob.dk
 * 
 * EXAMPLES
 * 
 * Send out an SMS:
 * <?php
 * $sms = new BiBoB_SMS('YourBiBoBNumber','YourBiBoBPassword');
 * if($sms->Login()===true) {
 *   $result = $sms->SendMessage('YourFriendsNumber','A nice and friendly message');
 *      if($result === true) {
 *         echo 'Message is sent';
 *      }
 * }
 * ?>
 * 
 * Get your account Balance:
 * <?php
 * $sms = new BiBoB_SMS('YourBiBoBNumber','YourBiBoBPassword');
 * if($sms->Login()===true) {
 *   $balance = $sms->GetBalance();
 *   echo 'I got '.sprintf('%.2f',$balance).' DKK left on my account';
 * }
 * ?>
 * 
 * Please read the comments in the source for more information.
 * 
 */

class BiBoB_SMS {
    
    /**
     * Defines where the SOAP Client can find the BiBoB SMS WSDL
     *
     * @ var string
     */
    private $wsdl = 'https://www.bibob.dk/SmsSender.asmx?WSDL';
    
    /**
     * Variable for the cellphone number. If you set your cellphone number here - you
     * do not need to add it when initialize the class.
     *
     * @ var string
     */
    protected $cellphone = '';
    
    /**
     * Varibale for the password in plain text. If you set your password here - you
     * do not need to add it when initialize the class.
     *
     * @ var string
     */
    protected $password = '';
    
    
    /**
     * Contructs the class - and adds cellphone number and password
     * 
     * Set the cellphone number and password. 
     *
     * @ param string $cellphone
     * @ param string $password
     */
    public function __construct($cellphone='',$password='') {
        if(!empty($cellphone)) { $this->cellphone = $cellphone; }
        if(!empty($password)) {  $this->password = md5($password); }
    }
    
    
    /**
     * Performs a login
     * 
     * Function is not needed to do anything. But use it to be sure you
     * got the right username and password when using other functions.
     * Returns true on successfull login - returns the error message on false.
     *
     * @ return boolean/string    Returns the error message on failure - otherwise boolean true.
     */
    public function Login() {
        $param = array();
        $param['cellphone'] = $this->cellphone;
        $param['password'] = $this->password;
        $result = $this->doSOAPCall('Login',$param);
        if($result->LoginResult === '') {
            return true;
        }
        return $result->LoginResult;
    }
    
    
    /**
     * Get your balanace
     * 
     * Get your current balance from BiBoB. The amount is returned as a float
     * in Danish Kroner.
     *
     * @ return float    The amount on your account balance.
     */
    public function GetBalance() {
        $param = array();
        $param['cellphone'] = $this->cellphone;
        $param['password'] = $this->password;
        $result = $this->doSOAPCall('GetBalance',$param);
        if($result->GetBalanceResult===NULL) {
            return false;
        }
        return $result->GetBalanceResult;
    }
    
    /**
    * Get your contact list
    * 
    * Get the contact list from your WebSMS at bibob.dk
    * Returns an array with the contacts. Each got the keys 
    * 'firstname', 'lastname' and 'cellphone'
    * Set parameter utf8decode to true if you want the text
    * to be encoded in ISO-8859-1
    * Returns false on failure.                                
    *
    * @ param    boolean    $utf8decode    Default set to true
    * @ return    array
    */
    
    public function GetContacts($utf8decode=false) {
        $param = array();
        $param['cellphone'] = $this->cellphone;
        $param['password'] = $this->password;
        $result = $this->doSOAPCall('GetContacts',$param);
        if($result->GetContactsResult===NULL) {
            return false;
        }
        $contacts = array();
        foreach($result->GetContactsResult->string as $r) {
            if($utf8decode) { $r = utf8_decode($r); }
            $rx = explode(':',$r);
            $contacts[] = array('firstname'=>$rx[0],'lastname'=>$rx[1],'cellphone'=>$rx[2]);
        }
        return $contacts;
    }
    
    /**
     * Send a SMS message
     * 
     * Send one - or more SMS messages through the WSDL. Content needs to be string
     * the string will automatic be UTF-8 encoded. Just leave date empty - otherwise
     * you want to send a scheduled message.
     * The to parameter can be a string of one cellphone numer - or can be an
     * array of 2 or more numbers. If it is an array and identical message will be
     * sent to all numbers.
     * Returns true on success and false on failure.            
     *
     * @ param    string/array    $to
     * @ param    string            $content
     * @ param    dateTime        $date    
     * @ return    boolean            True on success, False on failure
     */
    
    public function SendMessage($to,$content='',$date='') {
        if(trim($content) == '') { return false; } //We need some content in the SMS
        $param = array();
        if(is_array($to)) {
            foreach($to as $number) {
                $param['smsTo']['string'][] = $number;
            }
        }
        else {
            $param['smsTo'] = array('string'=>$to);
        }
        $param['cellphone'] = $this->cellphone;
        $param['password'] = $this->password;
        $param['smscontents'] = $content;
   		$param['deliveryReport'] = false;
        $result = $this->doSOAPCall('SendMessage',$param);
        if($result===NULL) {
            return false;
        }
        return true;
    }
    
    
    /**
     * Do a SOAP call
     * 
     * Do a SOAP call to the the given WSDL. Returns the result.
     *
     * @ param    string    $method    The method that have to be called
     * @ param    array    $param    Parameters given as a array
     * @ return    array    Array of the result
     * @ access    private
     */ 
    private function doSOAPCall($method,$param=array()) {
        $soapClient = new soapClient($this->wsdl);
        $result = $soapClient->__soapCall($method,array('parameters'=>$param));
        return $result;
    }
}
?>

I will try to base my code on that instead :slight_smile:

I only need to do something like you did:
http://wiki.tinyclr.com/index.php?title=Cdyne_SMS_Web_Service

And change “requestUrlString” to “https://www.bibob.dk/SmsSender.asmx?WSDL” and add the different parameters.


#17

Note that we found the HttpWebRequest very slow… using a direct socket to port 80 and writing a string worked much better.

Of course if you’re not doing many, then the simplicity of the HttpWebRequest is much better.


#18

Okay. Thank you.
I might try it out in the future :slight_smile: