Send SMS from the Browser with Python-flask and html

Overview

This guide will use flask to create a simple web application that can send sms through the browser.

What do I need?

Find the full code on Github here
You will need the SignalWire Python SDK as well as Flask to handle the web framework.

Additionally you will need a signalwire account which you can create here. You will also need your SignalWire API credentials which you can find in the API tab of your SignalWire dashboard. For more information on navigating your SignalWire space check here.

How to run

Run Natively

Run app.py in your python environment of choice.
This app will be using Flask, which will use port 5000 on your localhost by default.

📘

This example should not be used in a live environment

Exposing this web app to a live endpoint means anybody with the url could send sms requests through your SignalWire space.

Code Walkthrough

This application has two components app.py which is our "server" component, and a templates folder which holds our sendsms.html, this is our client component.
Additionally there is an example.env file you can use to fill in with your SignalWire credentials and save as .env

Server-side code

Set-up

The server-side code for this is very simple, first we will import the required packages, load then set our environment variables, and create a client that will handle our sms requests.

from flask import Flask, request, render_template, redirect
import os
from dotenv import load_dotenv
from signalwire.rest import Client as signalwire_client
import re

load_dotenv()

SIGNALWIRE_PROJECT_KEY = os.environ['SIGNALWIRE_PROJECT_ID']
SIGNALWIRE_TOKEN = os.environ['SIGNALWIRE_API_TOKEN']
SIGNALWIRE_SPACE = os.environ['SIGNALWIRE_SPACE_URL']
SIGNALWIRE_NUMBER = os.environ['SIGNALWIRE_FROMNUMBER']

client = signalwire_client(SIGNALWIRE_PROJECT_KEY, SIGNALWIRE_TOKEN, signalwire_space_url=SIGNALWIRE_SPACE)

Index Route

Next we will create a route that returns our sendSMS.html form. When integrating this project, this may not be needed as you can simply embed the code from sendSMS.html into any html page your project is already using.

@app.route("/", methods=['GET', "POST"])
def smsmenu():
    return render_template('sendSMS.html')

Create Sms/Handler Route

Finally for our server-side we will create a route that actually handles the creation of our sms requests to the client.

First we will get the pnum and smsbody values from the client and call our phonevalidation() function, passing our pnum.
If phonevalidation() returns False we will let the client know that phone number wasn't valid. Otherwise we will create a request using pnumvalid as the "to" number and the body we retrieved from the client as our message body, and return "Message Sent." In this case there is no validation for if a message was delivered successfully, only that the request was created.

Alternatively if our conditions aren't met, we just assume something went wrong and return a message stating so to the client.

@app.route("/createsmshandler", methods=['GET', "POST"])
def createsms():
    pnum = request.args.get('pnum')
    body = request.args.get('smsbody')

    pnumvalid = phonevalidation(pnum)

    if pnumvalid == False:
        return "Invalid Phone Number"

    else:
        success = client.messages.create(to=pnumvalid, from_=SIGNALWIRE_NUMBER, body= body)
        return "Message sent."

Phone Number Validation

Validating phone numbers helps reduce improperly formatted requests to SignalWire, which in turn means your messages are delivered to the right target more appropriately! We can do this with some basic regex using python's default regex package re.

First we will define a new function and accept one pnum parameter. When we call this function in createsms() we will pass the phone number from our client as pnum.
Next we define our compiled regex as pattern. Our regex is simply looking for a string of 10 or 11 digits.
Then we will create a filterednum variable which will strip all non-digit characters from our phone number. The goal is to eliminate any white-space or special characters, for instance 1(123)-123-1234 would be stripped down to 11231231234.

Once we have our number filtered we can use the regex findall method to return a list of strings that match our criteria. We should only get 0 or 1 matches. If we get 0 matches, we return False which will return to our function.

If we do get a match, we will check the length of the match. If the length is 11 digits, and the leading digit is a "1" we can assume this user included the country-code and append a + to the string and return our e.164 formatted phone number to our function which will then use it as the to number in our text.
Similarly, if the length of our match is 10 digits we will assume the user did not include an area code and append +1 before returning our number to the function.

def phonevalidation(pnum):

    pattern = re.compile(r'\d{10,11}$')
    filterednum = re.sub("[^0-9]", "", pnum)
    matches = pattern.findall(filterednum)

    for match in matches:
        if len(match) == 11 and match[0] =="1":
            match = "+"+match
            return match
        if len(match) == 10:
            match = "+1"+match
            return match
    else:
        return False

📘

This Function is designed to Validate US country codes

If you would like to validate numbers from other countries you may have to adjust the code to match your desired country-code and phone number lengths.

Client-side Code

Our client-side code is just a simple html file SendSMS.html.
Most of this code is just the default/boilerplate HTML. The heart of our client really boils down to the <body>.

First we will create a new <form> with the action url being our /createsmshandler route. Once this is set we can create a <label> that will describe what our form does.
Now we can create our two text inputs pnum which is our target phone number, and smsbody which is the message the client would like to send. These will be passed as arguments to /createsmshandler.

Example: /createsmshandler?pnum=%2B11231231234&smsbody=Your+SMS+body+here

Finally, we have to create a <button> which will be used to submit our request and ensure we close our </form> tag.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Send A Message</title>
</head>
<body>
        <form action = "/createsmshandler">
        <label for="pnum">Send an SMS</label><br>
        <input type="text" id="pnum" name="pnum" value="+18001234567">Send SMS To</input></br></br>
        <input type="text" id="smsbody" name="smsbody" value="Your SMS body here">Sms Body</input></br></br>
        <button id="submitButton" class="float-left submit-button" >Send SMS</button>
        </form>
</body>
</html>

Wrap Up

This is a simple and flexible way to allow data to be passed from the client to your server which can then be validated before we create requests to the SignalWire API! While this guide focuses on SMS this same principle can be used to implement a wide variety of features into your web app!

Required Resources:

Github Repo
Python SignalWire SDK

Sign Up Here

If you would like to test this example out, you can create a SignalWire account and space here.

Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!


Did this page help you?