SMS
The gateway uses SMS Text messages for sending passwords to end-users. The SMS queue shows the SMS Text messages sent by the gateway which are not yet handled by the configured remote SMS transport. If an SMS Text message cannot be delivered, the “Last Error” column should provide information on why it cannot be delivered. An SMS transport must be configured before SMS Text messages can be sent.
The gateway sends passwords to end users via SMS text messages. These messages appear in the SMS Queue until they are processed by the configured SMS transport (the service or connection your system uses to deliver texts).
If a message cannot be delivered, the “Error Message column” explains why (for example, invalid phone number, carrier rejection, expired message, or network timeout). Use this information to correct the issue and resend if needed.
Before any SMS text messages can be sent, an SMS transport must be configured and active. If you do not see messages leaving the queue, verify that:
An SMS transport is configured and enabled.
Recipient phone numbers are in the correct international format (E.164, such as +15551234567).
Your SMS provider account has sufficient balance or quota.
Network connectivity and credentials for the SMS provider are valid.
Send SMS
A test SMS can be sent from the actions menu
SMS transports
An SMS transport is the connection between the gateway and an SMS provider. The following transports are built in:
Transport |
Description |
|---|---|
|
Sends the SMS Text message with the Clickatell Connect HTTP API |
|
Sends the SMS Text message with the eCall HTTP API |
|
Sends the SMS Text message with the Twilio REST API |
|
Sends the SMS Text message with an external script (see Scriptable SMS transport) |
The transports are configured on the settings page under . The settings of a transport are global settings: they cannot be set per domain or per user.
Only one transport is active at a time. The active transport is selected with the “SMS Active Transport” setting () or with the CLI:
ciphermail-cli property global set --name sms-active-transport --value twilio
The names of all registered transports can be listed with:
ciphermail-cli sms transports
Hint
The transport name is not case sensitive. A name which contains a space, like
Clickatell Connect/HTTP, must be quoted on the command line.
Note
Configuring a transport does not activate it. Only the transport selected with “SMS Active Transport” is used to send SMS Text messages.
Clickatell Connect/HTTP
This transport sends the SMS Text message with the Clickatell Connect HTTP API
(https://platform.clickatell.com/messages/http/send).
The API key is created in the Clickatell Platform portal for the HTTP API integration which should deliver the messages.
The following setting is available under :
- Clickatell Connect API Key
The authentication key which unlocks the Clickatell integration service (property
sms-transport-clickatell-connect-api-key).
Example configuration with the CLI:
ciphermail-cli property global set --name sms-transport-clickatell-connect-api-key --value "<api-key>"
ciphermail-cli property global set --name sms-active-transport --value "Clickatell Connect/HTTP"
eCall
This transport sends the SMS Text message with the eCall HTTP API
(https://url.ecall.ch/api/sms).
The following settings are available under :
- Ecall account name
The account name (user name) of the eCall gateway account (property
sms-transport-ecall-account-name).- Ecall account password
The password of the eCall gateway account (property
sms-transport-ecall-account-password).
Example configuration with the CLI:
ciphermail-cli property global set --name sms-transport-ecall-account-name --value "<account-name>"
ciphermail-cli property global set --name sms-transport-ecall-account-password --value "<password>"
ciphermail-cli property global set --name sms-active-transport --value ecall
Twilio
This transport sends the SMS Text message with the Twilio REST API
(https://api.twilio.com/2010-04-01/Accounts/<AccountSid>/Messages.json).
Twilio is the default transport.
The following settings are available under :
- From
The sender of the SMS Text message: a phone number in international format (E.164, such as
+15551234567) or an alphanumeric sender ID (propertysms-transport-twilio-from).- Messaging Service SID
The Messaging Service to send the message with, a unique 34-character identifier which starts with
MG(propertysms-transport-twilio-messaging-service-sid). Use a Messaging Service instead of a fixed sender number if you want Twilio to select the sender number from a pool.- Account SID
The identifier of the Twilio account (property
sms-transport-twilio-account-sid). The Account SID is always required because it is part of the API URL.- Auth Token
The authentication token of the Twilio account (property
sms-transport-twilio-auth-token).- API Key SID
The identifier of a Twilio API key (property
sms-transport-twilio-api-key-sid). API keys are revokable credentials which can be created on the Twilio dev tools page.- API Key Secret
The secret which belongs to the API Key SID (property
sms-transport-twilio-api-key-secret).
Important
“From” or “Messaging Service SID” (or both) must be set. If neither is set, the SMS Text message cannot be sent.
Important
There are two ways to authenticate with Twilio:
With an API key: set “API Key SID” and “API Key Secret”.
With the account credentials: set “Auth Token”.
If “API Key SID” is set, the API key is used and “API Key Secret” must be set as well. If “API Key SID” is not set, “Auth Token” must be set. Using an API key is advised because an API key can be revoked without changing the account credentials.
Example configuration with the CLI, using an API key and a fixed sender number:
ciphermail-cli property global set --name sms-transport-twilio-account-sid --value "<account-sid>"
ciphermail-cli property global set --name sms-transport-twilio-api-key-sid --value "<api-key-sid>"
ciphermail-cli property global set --name sms-transport-twilio-api-key-secret --value "<api-key-secret>"
ciphermail-cli property global set --name sms-transport-twilio-from --value "+15551234567"
ciphermail-cli property global set --name sms-active-transport --value twilio
Scriptable SMS transport
This transport sends the SMS Text message with an external script, which makes it possible to use an SMS provider for which there is no dedicated transport. The script receives the phone number and the message from the gateway and is responsible for handing the message over to the provider (for example with a REST API call).
Configuring the scriptable SMS transport requires three steps:
Create the script which sends the SMS Text message.
Enable the scriptable SMS transport with Ansible.
Make the scriptable transport the active SMS transport.
How the script is called
The gateway calls the configured command with the phone number as a command line option and the message on standard input:
/opt/ciphermail/scripts/send-sms.sh --phone-number "+15551234567"
The script must therefore meet the following requirements:
The script must be executable and the
ciphermail-backenduser must be allowed to execute it (the back end runs as theciphermail-backenduser).The message must be read from standard input.
The phone number is passed with the
--phone-numberoption. The gateway normalizes and validates the phone number before the script is called, so it is always in international format (E.164, such as+15551234567).The script must exit with exit code
0if the SMS Text message was sent, and with a non-zero exit code if it was not sent.
Note
If the script exits with a non-zero exit code, the SMS Text message stays in the SMS queue and is retried about once a minute. Anything the script writes to standard error is stored as the “Error message” of the queued message, so write a helpful error message to standard error. A message which cannot be sent within 24 hours is discarded.
Attention
By default the script must finish within 30 seconds. If it takes longer, the process is terminated and the SMS Text message is treated as not sent. Do not wait or retry in a loop inside the script; return a non-zero exit code and let the gateway retry.
Create the script
Create the script using the Cockpit Terminal (or use an SSH client) and make it executable:
sudo vi /opt/ciphermail/scripts/send-sms.sh
sudo chmod +x /opt/ciphermail/scripts/send-sms.sh
Hint
The directory /opt/ciphermail/scripts/ can be used for your own scripts.
The following example script sends the SMS Text message with the Twilio REST API. It handles the command line options, reads the message from standard input, logs to syslog and reports a failure with a non-zero exit code. Use it as a starting point for your own script. Click the title to expand the script.
Bash example script (send-sms.sh)
#!/bin/bash
set -e
set -o pipefail
# set a sane/secure path
PATH='/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin'
# it's almost certainly already marked for export, but make sure
export PATH
# remove all aliases (start with \ to prevent unalias from being aliased)
\unalias -a
# clean command hash
hash -r
# set a sane/secure IFS (note this is bash & ksh93 syntax only--not portable!)
IFS=$' \t\n'
SCRIPT_NAME=$(basename "$0")
# the error exit codes
GENERAL_EXIT_CODE=100
usage()
{
echo "Usage: $SCRIPT_NAME [option...]" >&2
echo "" >&2
echo " -h show usage" >&2
echo " --help show usage" >&2
echo " --phone-number phone number to send SMS to" >&2
exit 1
}
exit_with_error()
{
echo "$1" >&2
local exit_code="$2"
if [ -z "$exit_code" ]; then
exit_code=$GENERAL_EXIT_CODE;
fi
exit "$exit_code"
}
if [ "$#" -eq 0 ]; then usage; fi
GETOPT_TEMP=$(getopt -o h --long "help,phone-number:" \
-n "$SCRIPT_NAME" -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around $GETOPT_TEMP: they are essential!
eval set -- "$GETOPT_TEMP"
while true ; do
case "$1" in
-h|--help) usage ;;
--phone-number) phone_number=$2 ; shift 2 ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
if [[ -z $phone_number ]]; then
exit_with_error "phone_number not set"
fi
echo "sending SMS to $phone_number" | logger -t ciphermail-backend
# Read message body from stdin (also kept for logging/debugging below)
message="$(cat)"
TWILIO_ACCOUNT_SID=<replace>
TWILIO_AUTH_TOKEN=<replace>
TWILIO_FROM_NUMBER=<replace>
resp_file="$(mktemp)"
http_code="$(
curl -sS -X POST "https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}/Messages.json" \
-u "${TWILIO_ACCOUNT_SID}:${TWILIO_AUTH_TOKEN}" \
--data-urlencode "To=${phone_number}" \
--data-urlencode "From=${TWILIO_FROM_NUMBER}" \
--data-urlencode "Body=${message}" \
-o "${resp_file}" \
-w "%{http_code}"
)"
# Twilio returns 201 Created on success for Message creation
if [[ "${http_code}" != "201" ]]; then
{
echo ""
echo "Twilio SMS send failed (HTTP ${http_code}). Response body:"
cat "${resp_file}"
} | logger -t ciphermail-backend
rm -f "${resp_file}"
exit_with_error "SMS could not be sent (HTTP ${http_code})"
fi
rm -f "${resp_file}"
exit 0
Attention
The example script contains the credentials of the SMS provider. Make sure the script can only be read by the users who need it.
Enable the scriptable SMS transport
The scriptable SMS transport is only registered if the command to run is configured. Create an Ansible override file using the Cockpit File Browser (or use an SSH client):
sudo vi /etc/ciphermail/ansible/group_vars/all/override.yml
Paste the following content:
---
ciphermail_backend__scriptable_sms_transport_command: '/opt/ciphermail/scripts/send-sms.sh'
Then run the playbook:
sudo cm-run-playbook
Hint
The command may contain fixed command line options, for example
'/opt/ciphermail/scripts/send-sms.sh --provider example'. The
--phone-number option is always added by the gateway. Setting
ciphermail_backend__scriptable_sms_transport_command to false (the
default) disables the scriptable SMS transport.
Activate the scriptable SMS transport
After the back end has restarted, the transport is available under the name
Scriptable. To make it the active transport, set the “SMS Active Transport”
setting ()
or use the CLI:
ciphermail-cli property global set --name sms-active-transport --value scriptable
The available transports can be listed with:
ciphermail-cli sms transports
Test the scriptable SMS transport
Send a test SMS Text message:
ciphermail-cli sms send --message test --phone-number <phone-number>
Check the SMS queue:
ciphermail-cli sms get all
If the message was sent, it is removed from the queue. If the queue still
contains the message, the lastError of the message (the “Error message”
column on the SMS queue page) explains why it could not be sent. Additional
information can be found in the back-end log:
sudo journalctl -u ciphermail-backend -r