Sending & Receiving SMS on Linux

A little while ago I worked on a mixed media theatre production called If There Was A Colour Darker Than Black I’d Wear It. As part of this production I needed to build a system that could send and receive SMS messages from audience members. Today we’re looking at the technical aspects of how to do that using SMS Server Tools.

There are actually a couple of ways to obtain incoming text messages:

  • Using an SMS gateway and software API
  • Using a GSM modem plugged into the computer, and a prepaid SIM

The API route is the easiest way to go from a programming aspect. It costs money, but most gateways provide a nice API to interface with, and you’ll be able to send larger volumes of messages.

BLACK had a few specific requirements that made the gateway unsuitable.

  1. We were projecting out of a van in regional South Australia. We had terrible phone reception, and mobile data was really flakey.
  2. We were going to be sending text messages to audience members later, and needed to have the same phone number.

So, we got hold of a USB GSM modem and used a prepaid phone SIM. This allowed us to receive unlimited messages for free. However, we couldn’t send messages as quickly as we would have liked.

Modem Selection

There are quite a few GSM modems to choose from. You are looking for one with a USB interface and a removable SIM. GSM modems that use wifi to connect to computers won’t work. You need to be able to remove the SIM because most mobile data SIMs won’t allow you to send or receive SMS messages. The other big requirement is Linux drivers, and Google is really your friend here. The main thing to watch out for is manufacturers changing the chipsets in minor product revisions.

We ended up going with an old Vodafone modem using a Huawei chipset. The exact model I used is HUAWEi Mobile Connect Model E169 It shows up in Linux like this:

ID 12d1:1001 Huawei Technologies Co., Ltd. E169/E620/E800 HSDPA Modem

SMS Tools

SMS Tools is an open source software package for interfacing with GSM modems on Linux. It includes a daemon, SMSD, which receives messages. SMSD is configured to run your own scripts when messages are received, allowing you to do pretty much anything you want with them.

Installation is straight forward on Ubuntu et al:

sudo apt-get install smstools

Next you’ll need to configure the software for your modem and scripts.

Configuration File

The configuration file is a bit unwieldy, but thankfully it comes with some sane default settings. Edit the file in your favourite text editor:

sudo vim /etc/smsd.conf

Modem Configuration

First up you will need to configure your modem. The modem configuration is at the end of the config file, and the exact parameters will vary depending on what modem you have. Let’s have a look at what I needed:

device = /dev/ttyUSB0
init = AT^CURC=0
incoming = yes
baudrate = 115200

device is where you specify the file descriptor for your modem. If you’re using a USB modem, this will almost allways be /dev/ttyUSB0.

init specifies AT commands needed for your modem. Some modems require initialisation commands before they start doing anything. There are two strategies here, either find the manual for your modem, or take advantage of the SMSTools Forums to find a working configuration from someone else.

incoming is there to tell SMSTools you want to use this device to receive messages.

baudrate is, well, the baud rate needed for talking to the device.

Like I said, there are many options to pick from, but this is the bare minimum I needed. Check the SMSTools website and forum for help!

Event Handler

The other big important part of the config file is the event handler. Here you can specify a script/program that is run every time a message is sent or received. From this script you can do any processing you need, and could even reply to incoming messages.

eventhandler = /home/michael/smstools/sql_insert

My script is some simple Bash which inserts a message into a database, but more on that in a moment.

Sending Messages

Sending SMS messages is super easy. Smsd looks in a folder, specified in the config file, for outgoing messages. Any files that appear in this folder get sent automatically. By default this folder is /var/spool/sms/outgoing.

An SMS file contains a phone number to send to (including country code, but with out the +) and the body of the message. For example:

To: 61412345678

This is a text message sent by smstools. Awesome!

Easy! Just put files that look like this into the folder and you’re sending messages.

Receiving Messages

Let’s have a better look at the event handler. Remember, this script is called every time a message is sent or received. The information about the message is given to your program as command line arguments:

  1. The event type. This will be either SENT, RECEIVED, FAILED, REPORT, or CALL. We’re only interested in RECEIVED here.
  2. The path to the SMS file. You read this file to do whatever you need with the message

You can use any programming language to work with the message. However, it is very easy to use formail and Bash. For example:


#run this script only when a message was received.
if [ "$1" != "RECEIVED" ]; then exit; fi;

#Extract data from the SMS file
SENDER=`formail -zx From: < $2`
TEXT=`formail -I "" <$2 | sed -e"1d"`

From there you can do whatever you want. I put the message into a MySQL database.


That’s all you need to write programs that can send and receive SMS messages on Linux. Once you have smsd actually talking to your modem it’s pretty easy. However, in practice it’s also fragile.

The smsd log file is incredibly useful here. It lives in /var/log/smstools/smsd.log

Here are some of the errors I encountered and what to do about them:

Modem Not Registered

You’ll see an error that looks like this:


This means the modem has lost reception, and is trying to re-establish a connection. Unfortunately there is nothing you can do here but wait or, using a USB extension cable, trying to find a spot with better reception.

Write To Modem Error

An error like this:

GSM1: write_to_modem: error 5: Input/output error

means the software can no longer communicate with the modem. This is usually caused by the modem being accidentally unplugged, the modem being plugged in after the system has powered up, or by an intermittent glitch in the USB driver. To fix this, do the following:

  1. Stop smsd (sudo service smstools stop)
  2. Unplug the modem
  3. Wait 10 seconds or so
  4. Plug the modem back in
  5. Start smsd (sudo service smstools start)

Cannot Open Serial Port

You may see this error:

Couldn’t open serial port /dev/ttyUSB0, error: No such file or directory

This occurs if you started the computer (and therefore smsd) before plugging in the modem. Follow the steps above to fix it.


So there you have it. Follow these steps and you can send and receive SMS messages on Linux, using a cheap prepaid SIM and GSM modem.

In the next post we’ll be looking at exactly what I used this setup for.

Published by

Michael Marner

My name is Michael, and this is my website. I am currently working as a Research Fellow at the University of South Australia's Wearable Computer Lab. I am also the chair of the board and an announcer at Adelaide based community radio station Three D Radio 93.7FM.

19 thoughts on “Sending & Receiving SMS on Linux”

  1. “In the next post we’ll be looking at exactly what I used this setup for.”

    Hi Michael, I’m interested in the above. Can you show me this setup? Thanks.

  2. Hi Michael !
    thanks you for that goods article.
    I’m tring to make a SMS Gateway, i’ve a RaspberryPi 2, the same huawei modem as you, and i use gammu to handle Incoming SMSs, so i’m facing a problem: my gateway receive SMS for about 20 minutes before hanging,i mean modem always receive message but did not notify gammu.
    I want to switch to smstools,and i want to know if you have the same problem with SMSTools3?
    (p.s: excuse my english if i make some fault, i’m not an english speaking)

  3. Please help me to troubleshppt… here is log file
    [root@mrtg sms]# smssend 8801712045854 ‘test sms from Nagios’
    [root@mrtg sms]# cat /var/log/smsd.log

    2016-04-27 01:54:51,3, GSM1: Modem is not clear to send
    2016-04-27 01:54:52,6, smsd: Moved file /var/spool/sms/outgoing/send_CC5134 to /var/spool/sms/checked
    2016-04-27 01:55:05,3, GSM1: Modem is not clear to send
    2016-04-27 01:55:18,3, GSM1: Modem is not clear to send
    2016-04-27 01:55:30,2, smsd: Smsd main program received termination signal.
    2016-04-27 01:55:30,2, smsd: Smsd main program is awaiting the termination of all modem handlers.
    2016-04-27 01:55:30,2, GSM1: Modem handler 0 has received termination signal, will terminate after current task has been finished.
    2016-04-27 01:55:31,3, GSM1: Modem is not clear to send
    2016-04-27 01:55:31,2, GSM1: Modem handler 0 terminated.
    2016-04-27 01:55:31,2, smsd: Smsd main program terminated.
    2016-04-27 01:55:39,2, smsd: Smsd v3.0.10 started.
    2016-04-27 01:55:39,2, smsd: Running as root:root.
    2016-04-27 01:55:39,6, smsd: File mode creation mask: 022 (0644, rw-r–r–).
    2016-04-27 01:55:39,6, smsd: outgoing file checker has started.
    2016-04-27 01:55:39,6, GSM1: Modem handler 0 has started.
    2016-04-27 01:55:40,6, GSM1: I have to send 1 short message for /var/spool/sms/checked/send_X28231
    2016-04-27 01:55:40,6, GSM1: Sending SMS from to 8801833104095
    2016-04-27 01:55:40,6, GSM1: Checking if modem is ready
    2016-04-27 01:55:43,3, GSM1: Modem is not clear to send

  4. i succeed to get sms once but now
    i get the following:
    2017-02-19 12:05:58,2, smsd: Smsd v3.1.14 started.
    2017-02-19 12:05:58,2, smsd: Running as smsd:dialout.
    2017-02-19 12:05:58,4, smsd: File mode creation mask: 022 (0644, rw-r–r–).
    2017-02-19 12:06:04,2, GSM1: Modem handler 0 terminated. PID: 13888, was started 17-02-19 12:02:18.

  5. Hi 20papercups! I’m wondering if you got any data on what kind of volume this setup is capable of receiving?

    I’m wondering if for example this will receive 100 SMS, send in a relatively short window of time (say 5min).

    Thanks, have a nice day

  6. It’s really variable, as on a technical level SMS uses “leftover” bandwidth. It sends at about the same speed as a mobile phone, so one message every couple of seconds.

    If quick bulk sending is necessary then you’re better off going with a paid SMS gateway.

  7. Sometimes I got the troubles to send or receive the SMS in a dongle.

    I have a simple bash script (cront) to check the error from smstools log and restart the service and reset the modem


    THERE_ERROR=$(tail /var/log/smsd.log | grep "put_command expected (OK)|(ERROR)")

    if [ ! -z "${THERE_ERROR}" ]; then
    echo "[$(date)] There error. Will restart service and dongle"
    /etc/init.d/sms3 stop
    echo "[$(date)] stop service sms3"
    /usr/sbin/usb_modeswitch -R -v 12d1 -p 1506
    echo "[$(date)] reset modem"
    sleep 10
    /etc/init.d/sms3 start
    echo "[$(date)] start service sms3"
    echo "[$(date)] no error"

Leave a Reply

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