Added use URL SMS provider so anyone can bridge to their own SMS solution (#4478)

Ylian Saint-Hilaire committed Sep 1, 2022 at 13:31 UTC dce036658e4d64db12da98e2dd3aa7fccd2f8173
3 files changed +37
meshcentral-config-schema.json
+8
@@ -1310,6 +1310,14 @@
1310 "from": { "type": "string" }
1311 },
1312 "required": [ "provider", "apikey", "from" ]
1313 + },
1314 + {
1315 + "type": "object",
1316 + "properties": {
1317 + "provider": { "type": "string", "enum": [ "url" ] },
1318 + "url": { "type": "string", "description": "A http or https URL with {{phone}} and {{message}} in the string. These will be replaced with the URL encoded target phone number and message." }
1319 + },
1320 + "required": [ "url" ]
1321 }
1322 ]
1323 }
meshsms.js
+25
@@ -78,6 +78,14 @@ module.exports.CreateMeshSMS = function (parent) {
78 obj.provider = require('telnyx')(parent.config.sms.apikey);
79 break;
80 }
81 + case 'url': {
82 + // Validate URL configuration values
83 + if (typeof parent.config.sms.url != 'string') { console.log('Invalid or missing SMS gateway URL value.'); return null; }
84 + if (!parent.config.sms.url.toLowerCase().startsWith('http://') && !parent.config.sms.url.toLowerCase().startsWith('https://')) { console.log('Invalid or missing SMS gateway, URL must start with http:// or https://.'); return null; }
85 + if (parent.config.sms.url.indexOf('{{message}}') == -1) { console.log('Invalid or missing SMS gateway, URL must include {{message}}.'); return null; }
86 + if (parent.config.sms.url.indexOf('{{phone}}') == -1) { console.log('Invalid or missing SMS gateway, URL must include {{phone}}.'); return null; }
87 + break;
88 + }
89 default: {
90 // Unknown SMS gateway provider
91 console.log('Unknown SMS gateway provider: ' + parent.config.sms.provider);
@@ -123,6 +131,23 @@ module.exports.CreateMeshSMS = function (parent) {
131 if (err != null) { parent.debug('email', 'SMS error: ' + err.type); } else { parent.debug('email', 'SMS result: ' + JSON.stringify(result)); }
132 if (func != null) { func((err == null), err ? err.type : null, result); }
133 });
134 + } else if (parent.config.sms.provider == 'url') { // URL
135 + var sms = parent.config.sms.url.split('{{phone}}').join(encodeURIComponent(to)).split('{{message}}').join(encodeURIComponent(msg));
136 + parent.debug('email', 'SMS URL: ' + sms);
137 + sms = require('url').parse(sms);
138 + if (sms.protocol == 'https:') {
139 + // HTTPS GET request
140 + const options = { hostname: sms.hostname, port: sms.port ? sms.port : 443, path: sms.path, method: 'GET', rejectUnauthorized: false };
141 + const request = require('https').request(options, function (res) { parent.debug('email', 'SMS result: ' + res.statusCode); func(res.statusCode == 200, (res.statusCode == 200) ? null : res.statusCode, null); res.on('data', function (d) { }); });
142 + request.on('error', function (err) { parent.debug('email', 'SMS error: ' + err); if (func != null) { func(false, err, null); } });
143 + request.end();
144 + } else {
145 + // HTTP GET request
146 + const options = { hostname: sms.hostname, port: sms.port ? sms.port : 80, path: sms.path, method: 'GET' };
147 + const request = require('http').request(options, function (res) { parent.debug('email', 'SMS result: ' + res.statusCode); func(res.statusCode == 200, (res.statusCode == 200) ? null : res.statusCode, null); res.on('data', function (d) { }); });
148 + request.on('error', function (err) { parent.debug('email', 'SMS error: ' + err); if (func != null) { func(false, err, null); } });
149 + request.end();
150 + }
151 }
152 }
153
sample-config-advanced.json
+4
@@ -601,5 +601,9 @@
601 "provider": "telnyx",
602 "apikey": "xxxxxxx",
603 "from": "1-555-555-5555"
604 + },
605 + "____sms": {
606 + "provider": "url",
607 + "url": "http://example.com/sms.ashx?phone={{phone}}&message={{message}}"
608 }
609 }