SMS Gateway using smstools in Debian 9

Plug in your GSM Modem and run dmesg to find your device details.

# dmesg 

[6136702.655264] usb 1-4: new high-speed USB device number 2 using xhci_hcd
[6136702.822144] usb 1-4: New USB device found, idVendor=2001, idProduct=ab00
[6136702.822171] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[6136702.822192] usb 1-4: Product: Mobile Connect [6136702.822206] usb 1-4: Manufacturer: Mobile Connect
[6136702.822220] usb 1-4: SerialNumber: d35260985787
[6136702.979291] usb-storage 1-4:1.0: USB Mass Storage device detected
[6136702.980220] scsi host9: usb-storage 1-4:1.0
[6136702.980449] usbcore: registered new interface driver usb-storage
[6136703.006228] usbcore: registered new interface driver uas
[6158459.424559] usbcore: registered new interface driver usbserial
[6158459.424615] usbcore: registered new interface driver usbserial_generic
[6158459.424659] usbserial: USB Serial support registered for generic
[6159146.077845] usbcore: registered new interface driver ftdi_sio
[6159146.077905] usbserial: USB Serial support registered for FTDI USB Serial Device
[6162088.836820] usbserial: USB Serial deregistering driver FTDI USB Serial Device

Some modems start of by mounting a storage device which holds the Windows drivers, since we dont need this we install a tool that allows us to skip this part:

# apt install usb-modeswitch usb-modeswitch-data

Unzip the data files and search for a file that matches idVendor and idProduct in you dmesg.

# cd /usr/share/usb_modeswitch/
# gunzip configPack.tar.gz

To flip the imaginary switch, just run:

# usb_modeswitch --default-vendor 2001 --default-product ab00 -c ./2001:ab00

After flipping the switch idProduct changes from ab00 to 7e35

Create a udev device

# vim /etc/udev/rules.d/50-usb.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="2001", ATTRS{idProduct}=="7e35", SYMLINK+="absms"

Reload udev rules

# udevadm control --reload-rules && udevadm trigger

Configure smsD

# vim /etc/smsd.conf
devices = GSM1

incoming = /var/spool/sms/incoming
outgoing = /var/spool/sms/outgoing
sent = /var/spool/sms/sent
checked = /var/spool/sms/checked
failed = /var/spool/sms/failed

logfile = /var/log/smstools/smsd.log
stats = /var/log/smstools/smsd_stats

infofile = /var/run/smstools/smsd.working
pidfile = /var/run/smstools/smsd.pid


receive_before_send = no
autosplit = 3

[GSM1]
device = /dev/absms
incoming = yes
baudrate = 19200
memory_start = 1
pin = 0000
init=AT+CPMS="SM","SM","SM"

Heres a bash-script to send sms:

#!/bin/bash

[ $# -ne 2 ] && echo "Missing or too many params.. Syntax: sms <number> \"message\"" && exit 1

NR="$1"
MESS="$2"

echo -e "To: ${NR}\n\n${MESS}" > /var/spool/sms/outgoing/$(date +%Y%m%d-%T.%N).txt

Setting up a Web API for sending and receiving SMS.

Mount and bind the sms spool queue to your web root:

# mount --bind /var/spool/sms /var/www/sms.your.domain/html/smsd
# nvim api.php
<?php
$license='
    AsbraSMS v1.0 is a frontend for smstools
    Copyright (C) 2019 Nimpen J. Nordström <j@asbra.nu>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
    ';

$phone   = $_REQUEST['phone'] ?? '';
$message = $_REQUEST['message'] ?? '';
$date    = date("ymd_His");

if ( ! empty ( $phone ) && ! empty ( $message ) )
{
	$content="To: $phone\n\n$message";
	echo "Sending...\n" . $content;
	file_put_contents("smsd/outgoing/$date.txt", $content);
}
else {
	echo "\nError: Missing parameters!\n\n";
	echo "Example: curl 'http://sms.your.domain/index.php?phone=%2B46720437607&message=test+from+terminal' > /dev/null\n";
	echo "Where %2B is UNICODE for the plus sign '+', use it to prefix the mobile number with a country code.\n\n";
	echo "$license\n\n";
}

With that code pasted you’ve got yourself a brand new API!
Go ahead and send your first SMS.

# curl "http://sms.your.domain/index.php?phone=%2B46720437607&message=test+from+terminal" > /dev/null

Or via POST:

# curl -X POST -F "phone=+46720437607" -F "message=testar lite" http://sms.asbra.lan/api.php

A simple php frontend

# nvim index.php
<?php /*

    AsbraSMS v1.0 is a frontend for smstools
    Copyright (C) 2019 Nimpen J. Nordström <j@asbra.nu>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

*/
$phone   = $_GET['phone'] ?? '';
$message = $_GET['message'] ?? '';
$date    = date("ymd_His");
?>
<!doctype html>
<html lang="en">
	<head>
		<!-- Required meta tags -->
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

		<!-- Bootstrap CSS -->
		<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

		<style>
			.bg-black { background-color:#000; }
			a { font-weight:bold; }
		</style>

		<title>AsbraSMS</title>
	</head>

	<nav class="navbar navbar-dark bg-dark mb-5">
		<div class='container'>
			<a class="navbar-brand" href="<?php echo $_SERVER['PHP_SELF']; ?>">Asbra<b class='text-primary'>SMS</b></a>
			<button class="navbar-toggler border-0" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
				<span class="navbar-toggler-icon"></span>
			</button>
			<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
				<div class="navbar-nav">
				  <a class="nav-item nav-link active" href="https://xn--1ca.se">Author</a>
				  <a class="nav-item nav-link active" href="<?php echo $_SERVER['PHP_SELF']; ?>">Home <span class="sr-only">(current)</span></a>
				</div>
			</div>
		</div>
	</nav>

	<body class='bg-black text-light'>

		<div class='container'>

			<div class='row mb-4'>
				<div class='col-lg-6 mb-3'>

					<div class='card card-body bg-dark text-light'>
						<h3 class='mb-3'>Compose your message</h3>
						<form method=get>
							<div class="form-group">
								<label for="inputPhone">Mobile Phone Number</label>
								<input name="phone" value="<?=$phone?>" type="text" class="form-control" id="inputPhone" aria-describedby="phoneHelp" placeholder="Phone number">
								<small id="phoneHelp" class="form-text text-muted">Dont forget country code (+46)</small>
							</div>
							<div class="form-group">
								<label for="inputSms">SMS Message</label>
								<input name="message" value="<?=$message?>" type="text" class="form-control" id="inputSms" placeholder="SMS Message">
							</div>
							<button type="submit" class="btn btn-primary">Submit</button>
						</form>
					</div>

				</div>
				<div class='col-lg-6 mb-3'>

					<?php if ( ! empty ( $phone ) && ! empty ( $message ) ) : ?>
							<div class='card card-body bg-warning text-light mb-4'>
							<h3>Sending...</h3>
								<?php $content="To: $phone\n\n$message"; ?>
								<pre><?=$content?></pre>
								<?php file_put_contents("smsd/outgoing/$date.txt", $content); ?>

							</div>
					<?php endif; ?>
				</div>
			</div> <!-- /row -->

			<div class='row'>

				<div class='col-lg-6 mb-3'>
					<div class='card card-body bg-dark text-light'>
					<h4>Sent</h4>
						<?php globber("smsd/sent/*"); ?>
					</div>
				</div>

				<div class='col-lg-6 mb-3'>
					<div class='card card-body bg-dark text-light'>
					<h4>incoming</h4>
						<?php globber("smsd/incoming/*"); ?>
					</div>
				</div>

<?php if ( ! empty ( glob ( "smsd/failed/*"	) ) ) : ?>
				<div class='col-lg-12 mb-3'>
					<div class='card card-body bg-danger text-light'>
					<h4>Failed</h4>
						<?php globber("smsd/failed/*"); ?>
					</div>
				</div>
<?php endif; ?>
			</div>
		</div>

		<!-- Optional JavaScript -->
		<!-- jQuery first, then Popper.js, then Bootstrap JS -->
		<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
		<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
	</body>
<footer class='text-center py-5'>
	<small>
		<strong>AsbraSMS Copyright © 2019 ASBRA AB, <j@asbra.nu></strong><br>
		<hr style="border-top:1px solid #fff; max-width:250px;">
		This is free software, and you are welcome to redistribute it
		under certain conditions.<br>
		See <a href='https://www.gnu.org/licenses/gpl-3.0.en.html'>GNU GPL v3</a> for more information.
	</small>
</footer>
</html>

<?php

function globber($path) {

	$files = glob($path);
	$dir = dirname($path);

	usort($files, create_function('$a,$b', 'return filemtime($b) - filemtime($a);'));

	echo "<table class='table table-striped table-dark table-sm'>";
	foreach ( $files as $file )
	{
		$filename = basename ( $file );
		echo "<tr><td><a href='$dir/$filename'>$filename</a></td><td><div class='float-right'>".date("Y-m-d H:i:s", filectime($file))."</div></td></tr>";
	}
	echo "</table>";

}

2 comments

  1. Hi,
    thank You for sharing. I have this error.
    2019/11/08 14:57:37 [error] 11202#0: *8 FastCGI sent in stderr: “PHP message: PHP Parse error: syntax error, unexpected ‘?’ in /usr/share/nginx/www/smsd/sms.php on line 19” while reading response header from upstream, client: 192.168.14.112, server: localhost, request: “GET /smsd/sms.php HTTP/1.1”, upstream: “fastcgi://unix:/var/run/php5-fpm.sock:”, host: “192.168.14.30”

    1. ‘??’ is a php-7 feature, you’re using php 5.
      Try ‘?:’ instead

Leave a comment

Your email address will not be published. Required fields are marked *