Drupal 6 SMS Framework: Esendex PHP5 SOAP Gateway

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 (
form_set_error('', '');


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($sendxml, XSD_ANYXML, NULL, NULL, NULL);
$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($headerxml, XSD_ANYXML, NULL, NULL, NULL);
$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

esendex-0.1.1.tar.gz2.7 KB