How to Send SMS Text Messages with AWS Lambda and Python 3.6

May 04, 2017
Written by
Matt Makai
Twilion

GmRICmhwjC02v09YluVqfcQoHzr4641UIgNkcJW4pit2b6YFeD0e5W9GOdKIEgCmPjoeELWq0MU22kVx-BK_H92JSUG84XO5ZVpAvG79J81hYXlVH2KT6XS-vEneNNDLp706hswu

Amazon Web Services (AWS) Lambda is a usage-based service that can run arbitrary Python 3.6 code in response to developer-defined events. For example, if a new JPEG file is uploaded to AWS S3 then AWS Lambda can execute Python code to respond to resize the image on S3.

Let’s learn how to use AWS Lambda with a manual test event trigger to send outbound text messages via a Python Lambda function that calls the Twilio SMS REST API.

Getting Started with AWS Lambda

Sign up for a new Amazon Web Services account, which provides a free tier for new users, or sign into your existing AWS account.

After you sign up go to the main Console page that looks like the following screen.

Search for lambda in the dashboard text box.

As shown in the screenshot, use the search box with the text “lambda” to find Lambda on the list of services. Click on Lambda to get to the main AWS Lambda page.
Click the “Create a Lambda function” button. The “Select Blueprint” page will appear.
The Select Blueprint Lambda screen.

Click on the “Blank Function” option to advanced to the “Configure triggers” page. A trigger fires and runs the Lambda function when a developer-defined event happens. I found it confusing at first that the trigger is optional and you don’t actually need to configure a trigger to move to the next step. In our case we’ll test the Lambda function manually after we’ve set it up so click the “Next” button to move on.
Configure Lambda trigger screen.

The “Configure function” screen appears next where we can write some code.
The Lambda configuration screen.

Preparing the Lambda Function

Enter a “sendsms” as the name of the Lambda function and “Send an SMS text message to a phone.” for the description field. In the Runtime drop-down, select Python 3.6 for the programming language.

python-3-6.jpg

Below the Runtime drop-down there is a large text box for code, pre-populated with a stub lambda_handler function. The “Code entry type” drop-down can be changed to upload a ZIP file but for our short function we will stick to the “Edit code inline” option. Replace the default function in the text box and paste in the following code.

import base64
import json
import os
import urllib
from urllib import request, parse


TWILIO_SMS_URL = "https://api.twilio.com/2010-04-01/Accounts/{}/Messages.json"
TWILIO_ACCOUNT_SID = os.environ.get("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.environ.get("TWILIO_AUTH_TOKEN")


def lambda_handler(event, context):
    to_number = event['To']
    from_number = event['From']
    body = event['Body']

    if not TWILIO_ACCOUNT_SID:
        return "Unable to access Twilio Account SID."
    elif not TWILIO_AUTH_TOKEN:
        return "Unable to access Twilio Auth Token."
    elif not to_number:
        return "The function needs a 'To' number in the format +12023351493"
    elif not from_number:
        return "The function needs a 'From' number in the format +19732644156"
    elif not body:
        return "The function needs a 'Body' message to send."

    # insert Twilio Account SID into the REST API URL
    populated_url = TWILIO_SMS_URL.format(TWILIO_ACCOUNT_SID)
    post_params = {"To": to_number, "From": from_number, "Body": body}

    # encode the parameters for Python's urllib
    data = parse.urlencode(post_params).encode()
    req = request.Request(populated_url)

    # add authentication header to request based on Account SID + Auth Token
    authentication = "{}:{}".format(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
    base64string = base64.b64encode(authentication.encode('utf-8'))
    req.add_header("Authorization", "Basic %s" % base64string.decode('ascii'))

    try:
        # perform HTTP POST request
        with request.urlopen(req, data) as f:
            print("Twilio returned {}".format(str(f.read().decode('utf-8'))))
    except Exception as e:
        # something went wrong!
        return e

    return "SMS sent successfully!"

The above code defines the lambda_handler function, which AWS invokes to execute your code. The Python code expects two environment variables that are read by the os module with the os.environ.get function.

Within the lambda_handler function we check that all values have been set properly, otherwise we exit with a readable error message. If the appropriate values are in place we populate the URL with the user’s Twilio Account SID as specified in the API reference documentation. We then use Python 3’s urllib standard library functions to perform an API request to Twilio. If Twilio returns the expected HTTP 201 response there will not be an exception so we return from the function with the “SMS sent successfully!” value.

Below the code input area there is a section to set environment variable key-value pairs. Enter two environment variable keys named TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN.

env_vars.jpg

Head to the Try Twilio page and sign up for a free Twilio account so that we can grab Twilio credentials for populating the environment variable values.
try-twilio.jpg

After signing up, you’ll get to the main Twilio Console where you can grab your Account SID and Auth Token. Copy the values and paste them into the environment variable values on the AWS Lambda configuration page.

console-values.png
 

The Python 3.6 code and the environment variables are now in place. We just need to handle a few more AWS-specific settings before we can test the Lambda function. Scroll past the environment variables to the “Lambda function handler and role” section, which contains a few more required function configuration items.

Keep the default handler set to lambda_function.lambda_handler. Select “Create a new Role from template(s)” from the drop-down then for the “Role name” field enter “dynamodb_access”. Under “Policy templates” select the “Simple Microservice permissions”.
The “Simple Microservice permissions” allows our Lambda to access AWS DynamoDB. We will not use DynamoDB in this tutorial but the service is commonly used either as permanent or temporary storage for Lambda functions.

For the final configuration, keep the default handler, create a new role from a template for Simple Microservice permissions and save it with a unique name.

Our code and configuration is in place so click the “Next” button at the bottom right corner of the page.

Testing the Lambda Function

The next screen is to review the settings you just configured. Glance through the name, environment variables and other fields to make sure you didn’t typo anything.

review-screen.png

Scroll down press “Create function”.
review-function.png

A success message will appear on the next page below the “Test” button.
function-created.png

Click the “Test” button to execute the Lambda. Lambda will prompt us for some data to simulate an event that would kick off our function. Select the “Hello World” sample event template, which contains some default key that we will replace. Modify the template so you have the following input test event keys:
  • "To": "recipient phone number" – the number in the format “+12023351493” that you want to send a text message to. If you have a trial Twilio account this should be your verified phone number. If your Twilio account is upgraded then this can be any phone number.
  • "From": "twilio phone number" – the number in the format “+19732644156” that you own on Twilio, which will be used to send the outbound SMS
  • "Body": "Hello from AWS Lambda and Twilio!" – the message you want to send from the Twilio number to the recipient phone number

input-test-event.jpg

After entering your test event values, click the “Save and test” button at the bottom of the modal. Scroll down to the “Execution result” section where we can see our output.
sent-successfully.jpg

We can see the return value of the Lambda function and in just a moment our phone should light up with the received message like this:

success-python-3-6-aws-lambda.jpg

Awesome, our AWS Lambda function is working and we can modify it for whatever alert SMS notifications we need to send.

Next Steps

You just configured and ran some serverless infrastructure to call the Twilio API via the serverless AWS Lambda platform. There is a lot more you can do with Python and AWS Lambda. Check out the following tutorials for more code projects:

Questions? Drop a comment down below or contact me via