Friday, November 27, 2015

International Voice + SMS Forwarder: SMS Forwarding Part 2

Previously: SMS Forwarding Part 1

I've divided up the process of implementing SMS (text message) forwarding into three parts since there's a lot of "gotchas" in this part.  In the first part, I described the general process.  In this part, I'll provide the steps to implement an auto-responder, plus a walk-through video to demonstrate everything that needs to be done and to point out all the gotchas.  The third post will actually forward the SMS to an email.

There are two general steps in this post: setting up the AWS Lambda function and setting up an API Gateway to call that function.  All the instructions are written out below, followed by the video walkthrough.

A lot of this post is based on the Twilio blog post about creating your own IVR (interactive voice resonse) system with API Gateway and Lambda.

Setting up the Lamba function

  1. Log into Amazon Web Serivces and go to the Lambda console.
  2. Create a new function based on the 'hello-world-python' template.  (Hint: filter the templates by 'python')
  3. Name the function and give it a description.  Paste in the following code for the function:
    1
    2
    3
    4
    5
    6
    import json
    
    def lambda_handler(event, context):
        print(json.dumps(event, separators=(',',':')))
        return {'message': "Sorry, but I haven't set up text forwarding yet.  " +
                           "Please email xxxxxxxxxxxxx@gmail.com"}
    This will import the JSON library used for debugging (line 1), define an entry point for the Lambda function (line 3), print some debugging information (line 4, useful for the next post), and then return a simple dictionary with a response message asking to email you (lines 5-6).
  4. Create a new IAM role for the function, then save the role and the function.

Setting up the API Gateway

  1. Go to the API Gateway console.
  2. Create a new API. Under that, create a resource named 'SMS' and then within that resource, create a POST method.
  3. Set the POST method to use the Lambda function you created above
  4. Update the Integration Request with a mapping template to convert content formatted as application/x-www-form-urlencoded.  Use the following mapping template:
    {
      "reqbody":"$input.path('$')"
    }
    This template converts the POST request data to JSON for the Lambda function.
  5. Update the Integration Response to use a mapping template, too. Use this template:
    1
    2
    3
    4
    5
    #set($inputRoot = $input.path('$'))
    <?xml version="1.0" encoding="UTF-8"?>
    <Response>
        <Message>$inputRoot.message</Message>
    </Response>
    
    This mapping template will convert the JSON from the Lambda function to XML for Twilio.  You can read more about the template language on the Mapping Template Reference.
  6. Update the Method Response to send back an XML Content-Type header (application/xml) instead of JSON.
  7. Test it out in AWS.
  8. Deploy the API.  (It doesn't matter what you name the stage.)
  9. Test it for real with curl.  Replace the URL here with your URL, plus the path to the resource you created.  If you used 'SMS' in step 2, the path will be '/sms'.
    curl -X POST -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" -d"From=%2B2345678901&Body=TestSMS" "https://foobar.execute-api.us-east-1.amazonaws.com/your-api-name/sms"
  10. Update Twilio to point to the deployed URL (plus the path of the resource, e.g. https://foobar.execute-api.us-east-1.amazonaws.com/your-api-name/sms)
  11. Test it out by sending a text message to your Twilio number.
If you have any trouble, the CloudWatch logs from the API Gateway and from the Lambda function will guide you.

Here's a walkthrough to help you understand all the minutia. The API Gateway console has a lot of unintuitive clicks that you probably will waste time finding if you don't watch the quick walkthrough.








Previously: SMS Forwarding Part 1
Next Update: SMS Forwarding Part 3

Thursday, November 19, 2015

International Voice + SMS Forwarder: SMS Forwarding Part 1

Previously: International Call Forwarding

Now that I’ve got voice forwarding working, I’ve got to get SMS (text message) forwarding working.  I’ve decided to split this into multiple parts since there’s a lot to do.

The first part, this post, will cover the general idea of what I’m doing with Amazon Web Services (AWS).  The second part will be a narrated video showing each of the steps to implement an SMS auto-responder, along with the code.  The auto-responder will just send a generic reply asking to email me.  The third part will be the code to actually forward SMS messages to an email address. 

Twilio

Twilio is the service I used to set up the voice forwarding.  It allows you to build custom voice, SMS, and MMS applications.  The general idea is that you give Twilio a URL to load when it gets a call, text, or MMS.  Twilio follows the directions it gets when loading that URL.  I need to set up that URL.  The most basic (useful) direction I can give is to reply with another text message, so that’s what I’ll implement first.

In my previous post, I covered International Call Forwarding.  That was easy because Twilio built tools into their service for forwarding calls.  They don't have forwarding for SMS or MMS.  I’ll use Amazon for generating the response text message, and (in the third part) for forwarding the messages to my email.

The Cloud

For those of you not in the tech world, Amazon is more than just shopping. About 10 years ago Amazon decided to start opening up some of their web site infrastructure to the world.  They rent out web infrastructure, such as computers to do processing and serve webpages, amazingly fast internet connections, firewalls to protect against attackers, and a few other things.  Amazon was the first company to do this on a large scale and they're the most successful by far.  When someone talks about being "in the cloud," they are most likely really talking about "using computers rented from Amazon for a small premium in exchange for a fast internet connection, redundancy, labor, scalability, and solving a whole host of other problems."  Amazon’s offerings are collectively called Amazon Web Services or AWS.

I’m going to create an SMS auto-responder using AWS’s Lambda service and API Gateway service.  Then I'll build a forwarder with their Simple Email Service.

Building an Auto-Responder

Lambda lets you execute small bits of code in response to some trigger.  You don’t need to rent a server from Amazon to run that code and pay for all the idle time.  Generating a reply to a text message is simple, so it’s perfect for Lambda. 

API Gateway will give you a URL that someone can request and then pass that request on to a Lambda function.  There are some language differences to work out regarding the language that Twilio wants to use and the language Lambda wants to use.   I’ll cover that in the second part.

Building a Forwarder

Once I've got the autoresponder working, I can set up SMS forwarding to my email using Amazon Lambda and Amazon's Simple Email Service.

Cost

The cost of running the smallest server with Amazon is about $0.013 per hour, or $9.36 per month.  Since I'm using AWS Lambda, I don't need to run any servers with Amazon.  Generating a few hundred SMS replies via Lambda costs well under one cent per month.  (As an aside, AWS has a free tier of service, where if you use very little, it won’t cost you anything at all.  Some of the services I use will be free, some won’t be.  That $9.36 per month would fall into the free tier, but I’d still need to worry about the maintenance on the server).


There are some additional costs from other unrelated AWS services that I use.  Overall, my Amazon bill is less than $1.00 per month.  Twilio charges $1.00 per month per phone number and $0.0075 per SMS sent or received.  I expect the total cost of SMS forwarding to be under $3.00 per month.  Voice forwarding will cost about the same.
Next Update: SMS Forwarding Part 2