TIPS VoIP.ms SIP Messaging based SMS tutorial

Joined
Jul 6, 2013
Messages
85
Reaction score
31
Hello forum, I just got SMS via SIP working on my IncrediblePBX2020 and so I share my config with those of you who would like to use it. Oops: tuturial? how about tutorial =)

Overview: You are running IncrediblePBX2020 or similar and you recieve phone calls via VoIP.ms trunks for which you have SMS over SIP enabled. The phone calls you receive are routed to your various extensions and you run Zoiper-for-Android or some other endpoint which supports SIP Text Messaging. This script will allow multiple text enabled DIDs to forward text messages to multiple extensions concurrently. It will also allow different extensions to send SMS out on whichever outbound trunk you assign to that extension.

Reference material:
SMS Overview: https://wiki.voip.ms/article/SMS
SMS via command promp: http://nerdvittles.com/?p=24058#app18
SMS via your extensions: https://wiki.voip.ms/article/SIP/SMS_with_FreePBX

Instructions:
Read through the material above, then implement SMS via command prompt per the second link above so that you can test your setup, noting that the scripts are already pre-installed in IncrediblePBX2020 so you only need to configure them. Then follow the instructions in the 3rd link above but replace their sample code with the modified code below, and fill in the values per the in-line comments below. There is no magic here, all I've really done is performed the local-extension to DID-number mapping and outbound SMS number to DID mapping which the VoIP.ms article says you'll need to figure out for yourself. That's all!
Code:
[sms-in]
exten => _.,1,NoOp(Inbound SMS dialplan invoked)
exten => _.,n,NoOp(To ${MESSAGE(to)})
exten => _.,n,NoOp(From ${MESSAGE(from)})
exten => _.,n,NoOp(Body ${MESSAGE(body)})
exten => _.,n,Set(ACTUAL_FROM=${MESSAGE(from)})
exten => _.,n,Set(HOST_TO=${CUT(MESSAGE(to),@,2)})
exten => _.,n,Set(NUMBER_TO=${MESSAGE_DATA(X-SMS-To)})
exten => _.,n,Gosub(sms-in,T_${NUMBER_TO},1)
exten => _.,n,Hangup()
; Message for 6005550100 route to the the extensions listed below. Replace all instances of the SMS phone number below with yours.
exten => T_6005550100,1,MessageSend(pjsip:701@${HOST_TO},${ACTUAL_FROM}) ; Replace the extension number with yours.
exten => T_6005550100,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550100,n,MessageSend(pjsip:702@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550100,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550100,n,MessageSend(pjsip:703@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550100,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550100,n,MessageSend(pjsip:704@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550100,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550100,n,MessageSend(pjsip:705@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550100,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550100,n,Return()
; Messages for 6005550101 route to the the extensions listed below. Replace all instances of the SMS phone number below with yours.
exten => T_6005550101,1,MessageSend(pjsip:701@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550101,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550101,n,MessageSend(pjsip:703@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550101,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550101,n,Return()
; Messages for 6005550102 route to the the extensions listed below. Replace all instances of the SMS phone number below with yours.
exten => T_6005550102,1,MessageSend(pjsip:702@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550102,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550102,n,MessageSend(pjsip:704@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension number with yours.
exten => T_6005550102,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => T_6005550102,n,Return()
; If you have more text enabled phone numbers then add sections below as needed.

[sms-out]
exten => _.,1,NoOp(Outbound Message dialplan invoked)
exten => _.,n,NoOp(To ${MESSAGE(to)})
exten => _.,n,NoOp(From ${MESSAGE(from)})
exten => _.,n,NoOp(Body ${MESSAGE(body)})
exten => _.,n,Set(NUMBER_TO=${CUT(CUT(MESSAGE(to),@,1),:,2)})
exten => _.,n,Set(EXTENSION_FROM=${CUT(CUT(MESSAGE(from),@,1),:,2)})
; Here we map the sending EXTENSION_FROM to a corresponding sending NUMBER_FROM before sending it.
exten => _.,n,Set(CASE_701=6005550101) ; Messages from extension 701 are to originate from 6005550101
exten => _.,n,Set(CASE_702=6005550102) ; Messages from extension 702 are to originate from 6005550102
exten => _.,n,Set(CASE_703=6005550101) ; Messages from extension 703 are to originate from 6005550101
exten => _.,n,Set(CASE_704=6005550102) ; Messages from extension 704 are to originate from 6005550102
exten => _.,n,Set(CASE_705=6005550100) ; Messages from extension 705 are to originate from 6005550100
exten => _.,n,Set(NUMBER_FROM=${CASE_${EXTENSION_FROM}})
exten => _.,n,Gosub(sms-out,F_${NUMBER_FROM},1)
exten => _.,n,Hangup()
; Messages from 6005550100 are sent via their corresponding trunk below. Replace all instances of the trunk phone number below with yours.
exten => F_6005550100,1,Set(ACTUAL_FROM="${NUMBER_FROM}" <sip:VOIPMS_ACCOUNT@VOIPMS_SERVER_NAME>) ; Replace VOIPMS_ACCOUNT and VOIPMS_SERVER_NAME with their corresponding values
exten => F_6005550100,n,Set(ACTUAL_TO=pjsip:TRUNK_NAME/sip:${NUMBER_TO}@VOIPMS_SERVER_NAME) ; Replace TRUNK_NAME and VOIPMS_SERVER_NAME with their corresponding values
exten => F_6005550100,n,MessageSend(${ACTUAL_TO},${ACTUAL_FROM})
exten => F_6005550100,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => F_6005550100,n,Return()
; Messages from 6005550101 are sent via their corresponding trunk below. Replace all instances of the trunk phone number below with yours.
exten => F_6005550101,1,Set(ACTUAL_FROM="${NUMBER_FROM}" <sip:VOIPMS_ACCOUNT@VOIPMS_SERVER_NAME>) ; Replace VOIPMS_ACCOUNT and VOIPMS_SERVER_NAME with their corresponding values
exten => F_6005550101,n,Set(ACTUAL_TO=pjsip:TRUNK_NAME/sip:${NUMBER_TO}@VOIPMS_SERVER_NAME) ; Replace TRUNK_NAME and VOIPMS_SERVER_NAME with their corresponding values
exten => F_6005550101,n,MessageSend(${ACTUAL_TO},${ACTUAL_FROM})
exten => F_6005550101,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => F_6005550101,n,Return()
; Messages from 6005550102 are sent via the corresponding trunk below. Replace all instances of the trunk phone number below with yours.
exten => F_6005550102,1,Set(ACTUAL_FROM="${NUMBER_FROM}" <sip:VOIPMS_ACCOUNT@VOIPMS_SERVER_NAME>) ; Replace VOIPMS_ACCOUNT and VOIPMS_SERVER_NAME with their corresponding values
exten => F_6005550102,n,Set(ACTUAL_TO=pjsip:TRUNK_NAME/sip:${NUMBER_TO}@VOIPMS_SERVER_NAME) ; Replace TRUNK_NAME and VOIPMS_SERVER_NAME with their corresponding values
exten => F_6005550102,n,MessageSend(${ACTUAL_TO},${ACTUAL_FROM})
exten => F_6005550102,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => F_6005550102,n,Return()
; If you have more text enabled trunks then add sections below as needed.
Of course if you only have one SMS enabled phone number (trunk), then the above becomes much simpler like this. SMS messages will forward to 3 different extensions and all outbound messages go out on the same trunk:
Code:
[sms-in]
exten => _.,1,NoOp(Inbound SMS dialplan invoked)
exten => _.,n,NoOp(To ${MESSAGE(to)})
exten => _.,n,NoOp(From ${MESSAGE(from)})
exten => _.,n,NoOp(Body ${MESSAGE(body)})
exten => _.,n,Set(ACTUAL_FROM=${MESSAGE(from)})
exten => _.,n,Set(HOST_TO=${CUT(MESSAGE(to),@,2)})
exten => _.,n,Set(NUMBER_TO=${MESSAGE_DATA(X-SMS-To)})
exten => _.,n,MessageSend(pjsip:701@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension with yours.
exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => _.,n,MessageSend(pjsip:702@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension with yours.
exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => _.,n,MessageSend(pjsip:703@${HOST_TO},${ACTUAL_FROM}) ; Replace the example extension with yours.
exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => _.,n,Hangup()

[sms-out]
exten => _.,1,NoOp(Outbound Message dialplan invoked)
exten => _.,n,NoOp(To ${MESSAGE(to)})
exten => _.,n,NoOp(From ${MESSAGE(from)})
exten => _.,n,NoOp(Body ${MESSAGE(body)})
exten => _.,n,Set(NUMBER_TO=${CUT(CUT(MESSAGE(to),@,1),:,2)})
exten => _.,n,Set(EXTENSION_FROM=${CUT(CUT(MESSAGE(from),@,1),:,2)})
exten => _.,n,Set(ACTUAL_FROM="VOIPMS_PHONE_NUMBER" <sip:VOIPMS_ACCOUNT@VOIPMS_SERVER_NAME>) ; Replace VOIPMS_PHONE_NUMBER and VOIPMS_ACCOUNT and VOIPMS_SERVER_NAME with their corresponding values
exten => _.,n,Set(ACTUAL_TO=pjsip:TRUNK_NAME/sip:${NUMBER_TO}@VOIPMS_SERVER_NAME) ; Replace TRUNK_NAME and VOIPMS_SERVER_NAME with their corresponding values
exten => _.,n,MessageSend(${ACTUAL_TO},${ACTUAL_FROM})
exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => _.,n,Hangup()
And of course you have to enable your trunks for SMS, and also your extensions in pjsip.endpoint_custom_post.conf like this:
Code:
[701](+) ; Replace NNN with the corresponding PJSIP extension name
message_context=sms-out
[702](+) ; Replace NNN with the corresponding PJSIP extension name
message_context=sms-out
[703](+) ; Replace NNN with the corresponding PJSIP extension name
message_context=sms-out

Don't forget to restart asterisk when done and if you made a mistake then of course see here:
$ less /var/log/asterisk/full

Special thanks to Ward Mundy for making stuff like this possible for me through his publishings etc!
 
Last edited by a moderator:
Thanks for the TUT, and I see that Groundwire supports SIMPLE SIP, but I also see that PJSIP is required. Damn, that's going to be a rather large config change for me to make this work, but may just be worth it.
My 2020 is running so smoothly I'm not sure I wanna touch it. PJSIP is disabled as my older Mitel's don't like it. Looks like I may need to enable and punch some firewall holes. Would have made a good Xmas project.
 
So I got inbound working, but not outbound.
There is some confusing bits on the Voipms wiki, where they reference NNNNNNNNNN, does your actual extension number need to be 10 digits? I currently use a 3 digit extension, and the wiki is quite ambiguous here. Any idea's?
Each of these extensions is named after one of the SMS enabled DIDs from your VoIP.ms account .....
 
Well, one of my remote extensions doesn't like TLS with PJSIP, so time to revert the programming.
 
So I got inbound working, but not outbound.
There is some confusing bits on the Voipms wiki, where they reference NNNNNNNNNN, does your actual extension number need to be 10 digits? I currently use a 3 digit extension, and the wiki is quite ambiguous here. Any idea's?
No it does not. The VoIP.ms example code is for a different scenario where your phone connects directly to their POP as an extension, in which case the extension number must be the same as your VoIP.ms DID number since you are using their code. When passing through your own PBX the scenario is different, and this is exactly the issue which my modifed verson of their code takes care of for you. But you need to map your NXXNXXXXXX DID number to your extension and the reverse like this, in the code which I posted above:
Code:
; Here we replace the sending EXTENSION_FROM with the sending NUMBER_FROM so the PSTN can accept it.
exten => _.,n,Set(CASE_701=6005550100) ; Messages from extension 701 are to originate from 6005550100
exten => _.,n,Set(CASE_702=6005550101) ; Messages from extension 702 are to originate from 6005550101
exten => _.,n,Set(CASE_703=6005550102) ; Messages from extension 703 are to originate from 6005550102
; The above would be better as a per extension config in the database and configurable via GUI.
Where you'll replace the phone number with your VoIP.ms DID number and the extension number with your actual extension number. If you have several hundred DID's and extensions then you'll want to add more lines. Be sure to use the code I published above and it should just work. You have to do this because the "PSTN" network will reject your SMS message if it shows as as originating from an extension rather than your VoIP.ms DID number.

If all else fails then it should become obvious why by inspecting the tail end of $ less /var/log/asterisk/full
Note that SHIFT+F will take you to the end of the log and display your SMS progress in realtime.

Would have made a good Xmas project.
It did indeed make a GREAT Christmas project! ;o) I'm using PJSIP everywhere now except for my two FreePhoneLine trunks where it barfs.
 
Last edited:
I've revised the original post to present a complex and a simple option. Both are tested working here. There are a LOT of unnecessary lines in it for debug purposes. This stuff is begging for an AGI script and message queuing when an extension is down and so on.

I'm curious however why the names of subroutines I defined above within different contexts seem to collide. I had to prefix the subroutine names with F_ and T_ in my code above to prevent collision and this worries me greatly.
 
Last edited:
I did follow the original post to the T and outbound didn't work. I've reverted everything back to CHAN_SIP so maybe someone else will have better luck with the new code that's posted.
 
PJSIP trunks and endpoints have configuration fields in the GUI for this. (Extensions - advanced tab)

View attachment 2562
That's already covered by the VoIP.ms web page but you're right, I should have called it out specifically here too like this:

Connectivity / Trunks / VoIPms202 ; Edit(icon) / PJSIP Settings / Advanced:
Message Context: sms-in
 
maybe someone else will have better luck with the new code that's posted.
The new code does exactly the same thing in the same way, except for:
(1) It's more configurable, allowing the same SMS message to go out to multiple extensions.
(2) The old code might have failed to send out a message to some of the trunks IF you had more than one outbound trunk configured.

A nice easy to implement improvement might be to send out an email via the PBX if a message fails to forward to an extension after being received, but I've not done this because I already have VoIP.ms sending me emails.
 
That's already covered by the VoIP.ms web page but you're right, I should have called it out specifically here too like this:

Connectivity / Trunks / VoIPms202 ; Edit(icon) / PJSIP Settings / Advanced:
Message Context: sms-in

What I am saying is there is no need for the "message_context=sms-out" in the pjsip custom conf file for the extensions. The field is available in the GUI. (Assuming at least core module version 15.0.9.43)
 
Last edited:
no need for the "message_context=sms-out"
The trunk context is [sms-in] but the extension context is [sms-out] which are two very different things, the former called by the trunk and the latter called by the extensions. I have not tried without but in order to send SMS from an extension there needs to be somewhere to define which context that extension should call...
 
The trunk context is [sms-in] but the extension context is [sms-out] which are two very different things, the former called by the trunk and the latter called by the extensions. I have not tried without but in order to send SMS from an extension there needs to be somewhere to define which context that extension should call...

Applications -> Extensions -> edit a PJSIP extension -> Advanced tab -> scroll down or find text "Messages Context," and here enter your sms-out context where messages from the extension will be processed for outbound sending.

I'm not saying you're wrong about the contexts, I'm just saying you can define it in the GUI and not have to edit the custom file for that.
 
I see it now, thanks. It's called "Messages Context" and for some hard to explain reason I had been looking for "Text Message Context" so I wasn't finding it! Yes, nice alternative to banging in the file :)
 
Hello to all,

I have configured a voipms account on my asterisk 1.6.

I have already configured several providers, which work with the old SIP driver and I also have SMS via chansip between extensions.

Now I added VoipMs that works in pjsip and I was able to configure incoming and outgoing calls but, I can't configure SMS. I don't get anything even reading the debug you can't see anything about sms on pjsip.

Any help?

I used exactly the configuration published on voipms wiki but nothing to do.

I put the configurations for receiving and sending Voipms SMS in the file extension_custom.conf, but I have only the one in that file, is it correct?
 
thanks, I've read but now when I try to send a message from my software phone this is the debug's result:

== Endpoint XXXXXX is now Reachable


-- Executing [484XXXXXXX@mycontext:1] Set("Message/ast_msg_queue", "CALLERID(all)=<XXXXXXXXXX>") in new stack


-- Executing [484XXXXXXX@mycontext:2] Dial("Message/ast_msg_queue", "PJSIP/1484XXXXXXX@voipms") in new stack


-- Called PJSIP/1484XXXXXXX@voipms


[2020-11-20 23:13:09.095] ERROR[30868][C-00000001]: translate.c:1396 ast_translator_best_choice: Cannot determine best translation path since one capability supports no formats


[2020-11-20 23:13:09.095] WARNING[30868][C-00000001]: channel.c:6650 ast_channel_make_compatible_helper: No path to translate from PJSIP/voipms-00000000 to Message/ast_msg_queue


== Spawn extension (mycontext, 484XXXXXXX, 2) exited non-zero on 'Message/ast_msg_queue'

The mobile phone (484XXXXXXX) ring for a second but not receive a sms.


Receive SMS is different... nothing I can't see nothing in the console's debug.
 
Get 3CX - Absolutely Free!

Link up your team and customers Phone System Live Chat Video Conferencing

Hosted or Self-managed. Up to 10 users free forever. No credit card. Try risk free.

3CX
A 3CX Account with that email already exists. You will be redirected to the Customer Portal to sign in or reset your password if you've forgotten it.
Back
Top