SMS/MMS in VitXiWebRTC and Mobile apps

SMS/MMS in VitXiWebRTC and Mobile apps
Specifically with Callback URL for use with Skyetel
Copy all of the features that textable.app had

1 Like

Thank you for your suggestion, it will be taken into account with the development team.

1 Like

SMS with Vitxi all in one dashboard

1 Like

Another feature that was promised nearly two years ago with a bogus “sample” shown at a trade show… the ability to SMS in and out of VitXi Chat using your declared API (Twilio, Telnyx, Teli, whatever).

1 Like

Hello Sir,

We have postponed the implementation of sending and receiving SMS to give priority to the call center features that we recently published in the latest version.

We will resume the implementation of SMS because we are aware that it is something important and that we have been requested on multiple occasions.

You can be aware of each of our channels to receive news of our next updates.

Best Regards!

3 Likes

Hi Daniel,

I merged your post with the existing ones, as you can see above, this is in the works by the VitalPBX team. We a hope that they will provide an update really soon.

1 Like

Any updates on the horizon?

2 Likes

I am sure many people would love to know if there is a timeline or any progress made on this feature.

2 Likes

Without a timeline, we are forced to look for an alternative solution. Can you please advise? This question has been around for a LONG time (old forums too).

2 Likes

We also receive requests for external texting capabilities quite often.
It’s one thing that keeps some of our staff members away from using the Vital/Vitxi platform; choosing instead to continue using their own cell phones to communicate externally.
These days, texting is as important as calling for timely communication.

2 Likes

While I totally understand the frustration to get this officially supported, you can get it working on your own if you want.

You’ll need use the dialplan to receive and send the message between the PBX and your carrier.

1 Like

If there is an easy way to implement this, why haven’t they rolled out the feature?
Do you have a link to a guide or something for reference?
Thanks!

4 Likes

PitzKey… Can you give us more (preferably documented) information on that process?

2 Likes

Hi @fnlauria and @mrizkowsky,

Here’s the idea in a nutshell:

  • Build a webhook that supports receiving SMS from your SMS provider.
  • In the webhook parse and deliver the data to an Asterisk dialplan, either via AMI or callfiles.
  • In the dialplan, send the data to the VitXi endpoint.
  • Modify the outgoing messages context to construct the data properly and call your provider’s CURL command to send the SMS

This is the entire idea in short. I will see if I have time to write proper documentation.

5 Likes

Hello,
Did you find any time to look into this?
I unfortunately do not have any programming skills, but would love to try to implement this.
Will this dump the text function into the chat section on vitxi?
What about sending it to the desk phone?

1 Like

Does your provider offer SMS via SIP Message? if yes it should be pretty simple to implement.

SMS does come in in the chat section in vitxi,

You should be able to send it to the desk phone if the phone supports SMS

Skyetel apparently only supports callback url.
https://support.skyetel.com/hc/en-us/articles/360056299914-SMS-MMS-API

Hello, @mrizkowsky

In that case you’ll need a webhook to accept the SMS, and a dialplan to process the incoming and outgoing SMS
Below you’ll find a node.js express server which you can use to accept and parse the incoming SMS and add it to a call file which will take it to the dialplan for processing,

For this to work you’ll need the below,

  1. Create a temp directory in the same directory the script is in, it’s used to create the call file before being moved to the asterisk spooler
  2. Install all packages required by the script
  3. Run the application in the background, you can create a service or start it with pm2
  4. Open port 8888 in your direwall, you can limit it to skyetel SMS IP (52.14.37.123)
  5. Get a SID and Secret from your skyetel account, used to authenticate when sending outbound messages.
  6. Create a file with the custom dialplans (i.e. /etc/asterisk/vitalpbx/extensions__90-custom.conf)

Webhook for inbound

#!/usr/bin/env node

const fs = require('fs')
const {exec} = require('child_process')
const express = require('express')
const cors = require("cors")
const bodyParse = require('body-parser')
const app = express()
const port = 8888;

app.use(cors())
app.use(bodyParse.json({limit:'1mb',}))

app.post('/', (req, res) => {
  const {from, to, text} =req.body
  if(!from || !to||!text)return res.status(422).send('An unexpected error occured')

  const sanitzisedText = text.replace(/[^\w ]/g,'')

  const fileName = `temp/${new Date().toISOString().match(/^[^\.]+/)[0]}.call`

 fs.writeFileSync(fileName,
`Channel: Local/s@dummy-answer
Callerid: "SMS" <${from}>
Context: skyetel-sms
Extension: s
Priority: 1
Setvar: from=${from}
Setvar: to=${to}
Setvar: body=${sanitzisedText}`)

fs.renameSync(fileName, fileName.replace('temp','/var/spool/asterisk/outgoing/'))


res.send('Success!')
})

app.listen(port, () => {
  try {
    fs.readdirSync('temp')
  } catch (error) {
    fs.mkdirSync('temp')
  }

  console.log(`SMS app listening at http://localhost:${port}`)
})

Inbound Dialplan

[dummy-answer]
exten => s,1,Answer()
 same => n,Wait(5)
 same => n,Hangup()

[skyetel-sms]
exten => s,1,Answer()
 same => n,Set(SMS_FROM=${FILTER(0-9,${from})})
 same => n,Set(SMS_TO=${FILTER(0-9,${to})})
 same => n,Set(MESSAGE(body)=${body})
 same => n,Noop(From: ${SMS_FROM})
 same => n,Noop(TO: ${SMS_TO})
 same => n,Noop(Body: ${MESSAGE(body)})
 same => n,Set(SMS_TO=${SMS_TO:-4}) ;The last 4 digits of our DIDs match the extension number, I couldn't figure out any other way to route to an extension based on the DID so you might have to hard code it ( i.e. Set(SMS_TO=${IF($["${SMS_TO}"="1234567890"]?101:102)}) )
 same => n,Set(TENANT=) ;Enter your tenant path
 same => n,Set(DIAL_STRING=${DB(${TENANT}/extensions/${SMS_TO}/dial)})
 same => n,GotoIf($["${DIAL_STRING}"=""]?sendfailedmsg)
 same => n,Set(COUNTER=1)
 same => n,Set(CURRENT_DEVICE=${CUT(DIAL_STRING,&,${COUNTER})})
 same => n,While($[${EXISTS(${CURRENT_DEVICE})}])
 same => n,Set(TECHNOLOGY=${CUT(CURRENT_DEVICE,/,1)})
 same => n,Set(USER=${CUT(CURRENT_DEVICE,/,2)})
 same => n,GotoIf($[$["${TECHNOLOGY}"="IAX2"]|$["${TECHNOLOGY}"="DAHDI"]]?next)
 same => n,MessageSend(${TOLOWER(${TECHNOLOGY})}:${USER},${SMS_FROM})
 same => n,NoOp(SMS Status to ${CURRENT_DEVICE}: ${MESSAGE_SEND_STATUS})
 same => n(next),Set(COUNTER=$[${COUNTER} + 1])
 same => n,Set(CURRENT_DEVICE=${CUT(DIAL_STRING,&,${COUNTER})})
 same => n,EndWhile()
 same => n,Goto(h,1)
 same => n(sendfailedmsg),Noop(The message to extension ${SMS_TO} has failed. Status: ${MESSAGE_SEND_STATUS})
 same => n(failed),Hangup()

Outbound Dialplan

[messages]
exten => _ZXXXXXX!,1,Noop(SMS Sending) ;Accepts 7 or more digits with the first digit being [1-9]
 same => n,GotoIf($["x${CUT(MESSAGE(to),<,2)}x"="xx"]?noname)
 same => n,Set(SMS_NUM=${CUT(MESSAGE(to),<,2)})
 same => n,Set(SMS_NUM=${CUT(SMS_NUM,>,1)})
 same => n,Set(SMS_TECH=${CUT(SMS_NUM,:,1)})
 same => n,Set(SMS_REAL_TECH=${CUT(MESSAGE(to),:,1)})
 same => n,GotoIf($["${SMS_TECH}"="${SMS_REAL_TECH}"]?noname)
 same => n,Set(MESSAGE(to)=${STRREPLACE(SMS_NUM,${SMS_TECH},${SMS_REAL_TECH})})
 same => n(noname),Set(SMS_TO=${FILTER(0-9,${CUT(MESSAGE(to),@,1)})})
 same => n,GotoIf($[${LEN(${SMS_TO})} < 10]?messages-internal,${EXTEN},1)
 same => n,ExecIf($["${LEN(${SMS_TO})}"="10"]?Set(SMS_TO=1${SMS_TO}))
 same => n,ExecIf($[${LEN(${SMS_TO})} > 11]?Hangup())
 same => n,Set(FROM=${CUT(MESSAGE(from),<,2)})
 same => n,Set(ACTUALFROM=${CUT(FROM,@,1)})
 same => n,ExecIf($["${ACTUALFROM}"=~"_"]?Set(ACTUALFROM=${CUT(ACTUALFROM,_,1)}))
 same => n,Set(SMS_FROM=${FILTER(0-9,${CUT(ACTUALFROM,:,2)})})
 same => n,Set(SMS_CID=1234567${SMS_FROM}) ;Again if the last 4 of your DID matches the extension number. Note: this must be an 11 digit number and it must have SMS enabled in Skyetel
 same => n,Noop(To: ${SMS_TO})
 same => n,Noop(From: ${SMS_FROM})
 same => n,Answer()
 same => n,Set(SendSMS=${SHELL(curl -X POST -v -H "Content-type: application/json" --user <SID>:<SECRET> --data "{ \"to\": \"${SMS_TO}\", \"text\": \"${MESSAGE(body)}\" }" https://sms.skyetel.com/v1/out?from=${SMS_CID})}) ;You'll have to get the SID and SECRET from your Skytel account
 same => n,Hangup()

P.S. I am not to familiar with JavaScript, but I tested this setup with Skyetel and it worked.

Hope that helps…

2 Likes

This looks like amazing work.
So the webhook is the script?
How do I know what packages it needs?
Do I assume it already has what is needed?
I can do some googling to figure out how to follow steps 2 and 3 but if you are feeling generous to provide some more tips to accomplish those I would be appreciative.

Regarding the dialplans pulling the number - is there a way to grab it from the inbound route from the extension configuration?
Also would I append the dialplan stuff to the existing dialplan?
Or is asterisk smart enough to use multiple dial plan files?
Thanks for working on this!

1 Like

Yes

Running this command in the same directory the script is in should install the packages needed npm install fs child_process express cors body-parser

I couldn’t find one unfortunately

All files that in the /etc/asterisk/vitalpbx directory that start with extensions__ and end with .conf are included in the dial plan, so you can create a custom file (i.e. extensions__90-custom.conf) and it will be included.

1 Like