February 18, 2016

How to send and receive SMS in asterisk using XMPP and SIP

Asterisk v11 or higher supports MessageSend() function that can be used with SIP or XMPP support. This provides the flexibility of using sms with a carrier that supports either SIP messaging or XMPP. 
In this tutorial, we are using a carrier that supports SMS over XMPP. We will use that to integrate it with SIP sofphones. 
Here is a brief overview of the setup: 
1) DID service provider sends SMS over XMPP to asterisk server.
2) Asterisk server relays the message to SIP softphone over SIP.
3) SIP sofphone replies back (SMS) to asterisk server over SIP.
4) Asterisk server relays the SMS to DID service provider over XMPP.
In short, SMS between carrier and asterisk is using XMPP whereas SMS between asterisk and SIP softphone is using SIP Message support.
You can read more on SIP Message and asterisk support here; 
SIP Message RFC
Asterisk v13 MessageSend()

Tools used:

  • asterisk (We used Asterisk 13.7.2 in this tutorial, however, you should be able to use asetrisk 11 or higher that supports MessageSend() function with XMPP)
  • Freepbx (This is not required at all, however, we have our environment already running freepbx in this case.)
  • Inbound carrier that supports SMS over SIP or XMPP. In our case, our carrier supports SIP over XMPP.
  • Make sure res_xmpp module is loaded and running in asterisk.
  • Sofphone that supports SIP messaging, you can use this one CSipSimple

Summary of Steps

  • Configure XMPP in asterisk and connect it with your carrier
  • Configure dialplan to relay SMS received from carrier (over XMPP) to SIP extension (over SIP).
  • Configure dialplan to to relay SMS received from SIP extension (over SIP) to carrier (over XMPP).
  • Configure softphone and test it out by sending/receiving SMS.

Step by Step

  1. You need to have XMPP credentials from your carrier to access SMS. These should look like "user@domain" and a password. In our case we had something like DID@domain. To configure asterisk as xmpp client with your carrier, please edit "/etc/asterisk/xmpp.conf" and add the following.
    username=<YOUR USERNAME HERE>

  2. sendtodialplan must be set to yes or asterisk will not execute dialplan on receiving SMS from XMPP. Also, the context “from_DID1234567890” means to execute this dialplan, which we will define later.
  3. On asterisk CLI, reload res_xmpp module
    asteriskCLI> module reload res_xmpp.so

  4. Verify that asterisk is now successfully connected to XMPP server
    asteriskCLI> xmpp show connections

    Jabber Users and their status:
           [DID1234567890] username@host
         - Connected
       Number of clients: 1

  5. The next step is to configure two options in asterisk sip.conf file. If you are using freepbx, then you can add them through GUI advanced settings.

    accept_outofcall_message = yes
    outofcall_message_context = messages

    accept_outofcall_message ensures that asterisk will accept message requests outside of a call i.e. as you would expect receiving SMS on your mobile without someone having to call your first. The purpose of outofcall_message_context here means to direct SIP-SIP and/or SIP-XMPP messages through [messages] context.
  6. The next step is to define contexts [from_DID1234567890] and [messages] and write dialplans. We will use asterisk’s function MessageSend(to,[from]) to deliver SMS. The function has two parameters to and from, both accepting sip or xmpp.
    In extensions.conf or extensions_custom.conf (if you using freepbx), add the following;
    exten => _.,1,Set(ACTUALFROM=${CUT(MESSAGE(to),:,2)})
    exten => _.,n,Set(ACTUALFROM2=${CUT(ACTUALFROM,@,1)})
    exten => _.,n,MessageSend(xmpp:${ACTUALFROM2}@CARRIER_DOMAIN,xmpp:DID123456789)
    exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
    exten => _.,n,Hangup()

    exten => _.,1,Set(ACTUALFROM=${CUT(MESSAGE(from),:,2)})
    exten => _.,n,Set(ACTUALFROM2=${CUT(ACTUALFROM,@,1)})
    exten => _.,n,MessageSend(sip:EXTENSION,<sip:${ACTUALFROM2}@ASTERISK_SERVER_IP>)

    Replace the holders with their corresponding values i.e.
    • CARRIER_DOMAIN  => This is your carrier’s domain (defined in xmpp.conf earlier e.g. example     
    • sip:EXTENSION => Your sip extension                                             
    • ASTERISK_SERVER_IP => Your asterisk server IP (if your server is using NAT, then make sure this is the Live IP)

    [from_DID123456789] => This context will be executed as soon SMS is received on XMPP connection. From here you can send the SMS to right SIP extension. It is very
    important to properly format from SIP address or else sms from softphone will not work. That is why we have ACTUALFROM and ACTUALFROM2 lines to extract from SIP address. Here is how the dialplan should look with sample placeholder values;

    exten => _.,n,Set(ACTUALFROM=${CUT(MESSAGE(to),:,2)})
    exten => _.,n,Set(ACTUALFROM2=${CUT(ACTUALFROM,@,1)})
    exten => _.,n,MessageSend(xmpp:${ACTUALFROM2}@examplesms,xmpp:DID123456789)
    exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
    exten => _.,n,Hangup()

    exten => _.,1,NoOp(SMS receiving from XMPP dialplan invoked)
    exten => _.,n,Set(ACTUALFROM=${CUT(MESSAGE(from),:,2)})
    exten => _.,n,Set(ACTUALFROM2=${CUT(ACTUALFROM,@,1)})
    exten => _.,n,MessageSend(sip:2000,<sip:${ACTUALFROM2}@>)

  7. Now reload asterisk and configure register your extension on your softphone.     
  8. Send SMS to your DID from your mobile phone using telco sms. You should be able to receive it on your softphone. Similarly, you should be able to send SMS from your softphone to any number.   

This setup is a proof-of-concept and does not ensure delivery if the device (sip sofphone) is offline and also does not retain messages. However, this can be used to build a more reliable SMS delivery solution using AGI, more on this later!