Drupal 6 SMS Framework: Esendex PHP5 SOAP Gateway

Submitted by nigel on Wednesday 30th December 2009

Drupal 6 SMS Framework enables the sending of SMS from a Drupal 6 website, through a suitable bureau service. The 'glue' between the SMS Framework module and the chosen SMS bureau is called a 'gateway'. Each bureau needs the development of a dedicated gateway, and currently there are few available. In reality, the only gateways for Drupal 6 are Clickatell and a generic email facility.

In the hope of encouraging others to have a go, I have developed another. My gateway connects to UK (amongst others) provider Esendex. Furthermore, I have opted to code in PHP5 and using the PHP5 built-in SOAP module. This means that should you be tempted to develop a SOAP gateway for another bureau, you can use my module as a starting point.

There are a couple of negatives. Firstly, the module only works with PHP5 and the built-in SOAP class. If you wish to extend this, there are plenty of tutorials on the Internet to guide you.

Currently, the module only allows a single send, although my intention is to develop my module further to allow for multi-recipient messages. In addition, there is no incoming message facility. This may toddle along in the fullness of time. Finally, it would be great to have a message status facility but this is a shortcoming of the Framework and as such I am reliant upon the Framework developers to include this.

Below is the code. If you have any comments, please register and add as appropriate.

// Copyright <a href="http://www.badzilla.co.uk
//" title="www.badzilla.co.uk
//</a> Licence GPL. This program may be distributed as per the terms of GPL and all credits
// must be retained
// If you find this script useful, please consider a donation to help me fund my web presence
// and encourage me to develop more products to be placed under the terms of GPL
// To donate, go to <a href="http://www.badzilla.co.uk" title="http://www.badzilla.co.uk">http://www.badzilla.co.uk</a> and click on the donation button
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of

* @file
* Adds support for sending SMS messages using the Esendex gateway.
* Authored by badzilla.co.uk
* November/December 2009

* Implementation of hook_gateway_info().
function sms_esendex_gateway_info() {
  return array(
'esendex' => array(
'name' => 'Esendex',
'configure form' => 'sms_esendex_admin_form',
'send' => 'sms_esendex_send',

* Callback for sending messages.
function sms_esendex_send($number$message$options) {
sms_esendex_command('sendmsg', array('number' => $number'message' => $message));

sms_esendex_admin_form($configuration) {

$form['sms_esendex_messagelimit'] = array(
'#type' => 'item',
'#title' => t('Message Limit'),
'#value' => sms_esendex_messagelimit(),
$form['sms_esendex_account'] = array(
'#type' => 'textfield',
'#title' => t('Account'),
'#description' => t('Esendex Account.'),
'#size' => 40,
'#maxlength' => 255,
'#default_value' => $configuration['sms_esendex_account'],

$form['sms_esendex_user'] = array(
'#type' => 'textfield',
'#title' => t('User'),
'#description' => t('The username of your Esendex account.'),
'#size' => 40,
'#maxlength' => 255,
'#default_value' => $configuration['sms_esendex_user'],

$form['sms_esendex_password'] = array(
'#type' => 'textfield',
'#title' => t('Password'),
'#description' => t('The current password on your Esendex account.'),
'#size' => 30,
'#maxlength' => 64,
'#default_value' => $configuration['sms_esendex_password'],

* Gets the current message limit
function sms_esendex_messagelimit() {
$ret sms_esendex_command('limit');
    return isset(
$ret['data']) ? $ret['data'] : t('N/A');

* Validates the submission of the configuration form.
function sms_esendex_admin_form_validate($form, &$form_state) {
$result sms_esendex_command('state', array(), $form_state['values']);
    if (


sms_esendex_command($command 'state'$data = array(), $config NULL) {

$gateway sms_gateways('gateway''esendex');

    if (
$config == NULL)
$config $gateway['configuration'];

$command) {
$endpoint 'https://www.esendex.com/secure/messenger/soap/AccountService.asmx?wsdl';
$soapaction 'com.esendex.ems.soapinterface/GetAccountState';
$args = array(new SoapParam('''com:GetAccountState'));
$fname 'GetAccountState';

$endpoint 'https://www.esendex.com/secure/messenger/soap/SendService.asmx?wsdl';
$soapaction 'com.esendex.ems.soapinterface/SendMessage';

$sendxml '<com:SendMessage>';
$sendxml .= '<com:recipient>' $data['number'] . '</com:recipient>';
$sendxml .= '<com:body>' $data['message'] . '</com:body>';
$sendxml .= '<com:type>Text</com:type>';
$sendxml .= '</com:SendMessage>';

$sendbody = new SoapVar($sendxmlXSD_ANYXMLNULLNULLNULL);
$args = array("ItemXml" => $sendbody);
$fname 'SendMessage';


// override the __doRequest to hack the ns1 namespace prefix which seems to stuff up the esendex server
    // for some reason their ASP.NET server demands a namespace prefix of 'com'
if (!class_exists(MSSoapClient)) {
MSSoapClient extends SoapClient {

__doRequest($request$location$action$version) {
$request str_replace('ns1''com'$request);

// parent call - note that a snapshot of $request is held in a buffer so
                // subsequent dump using __getLastRequest *WILL NOT* reflect the changes effected
                // here. This is a known feature. 
                // See PHP manual php.net/manual/en/soapclient.dorequest.php
return parent::__doRequest($request$location$action$version);


// PHP5 built-in SOAP client
$param = array('location' => $endpoint
'uri'      => 'com.esendex.ems.soapinterface'
'style'    => SOAP_DOCUMENT,
'use'      => SOAP_LITERAL
'trace'    => 1);

$soap = new MSSoapClient(NULL$param);

$options = array('location'   => $endpoint
'uri'        => 'com.esendex.ems.soapinterface'
'soapaction' => $soapaction);

$headerxml '<com:MessengerHeader>';
$headerxml .= '<com:Username>' $config['sms_esendex_user'] . '</com:Username>';
$headerxml .= '<com:Password>' $config['sms_esendex_password'] . '</com:Password>';
$headerxml .= '<com:Account>' $config['sms_esendex_account'] . '</com:Account>';
$headerxml .= '</com:MessengerHeader>';

$headerbody = new SoapVar($headerxmlXSD_ANYXMLNULLNULLNULL);
$header = new SOAPHeader('com.esendex.ems.soapinterface''MessengerHeader'$headerbody); 

// attempt the soap call; if error then log the messages and return
try {
$result $soap->__soapCall($fname$args$options$header);
    } catch (
SoapFault $soapFault) {
watchdog('sms''Esendex Request Headers: %s', array('%s' => $soap->__getLastRequestHeaders()));
watchdog('sms''Esendex Request: %s', array('%s' => $soap->__getLastRequest()));
watchdog('sms''Esendex Error Response: %s', array('%s' => $soapFault));
        if (!isset(
drupal_set_message(t('Esendex Error: Refer to System Report for Stack Trace'), 'error');
drupal_set_message(t('Esendex Error @errno: @errstr'
'@errno' => $soapFault->detail->ErrorCode
'@errstr' => $soapFault->detail->ErrorMessage)), 'error');

        return array(
'status' => true'data' => NULL);

// no error so everything ok. Extract the returning data we need
    // uncomment below for debugging
    // watchdog('sms', 'Esendex Result: @res', array('@res' => print_r($result, TRUE)));
switch($command) {
$retdata $result->MessageLimit;

// do nothing
$retdata '';

    return array(
'status' => false'data' => $retdata);
name = "Esendex"
description = "Allows the SMS Framework to use Esendex as a gateway."
package = SMS Framework
dependencies[] = sms
core = 6.x
blog terms
Drupal Drupal 6 PHP