メニュー

Rate this page:

Thanks for rating this page!

We are always striving to improve our documentation quality, and your feedback is valuable to us. How could this documentation serve you better?

PythonとAmazon Lambdaを使用して、SMSおよびMMSメッセージを受信、返信する

Today we're going to get to "Hello, World!" on a serverless Twilio application using Amazon API Gateway, Amazon Lambda, and Python. By the end of this guide, you'll have the roots of your next world-changing Twilio Application. By the end of this paragraph you'll have a promise - you won't need to spin up a single VPS.

Sound exciting? Indubitably. Let's get started!

受信SMSのダイアグラム

Oh, and if you haven't yet, please log into or create an AWS Account, and log into or create a Twilio Account. Don't worry, we'll be here when you're ready.

Webhookとは何か

Webhooks are user-defined HTTP callbacks. They are usually triggered by some event, such as receiving an SMS message or an incoming phone call. When that event occurs, Twilio makes an HTTP request (usually a POST or a GET) to the URL configured for the webhook.

To handle a webhook, you only need to build a small web application that can accept the HTTP requests. Almost all server-side programming languages offer some framework for you to do this. Examples across languages include ASP.NET MVC for C#, Servlets and Spark for Java, Express for Node.js, Django and Flask for Python, and Rails and Sinatra for Ruby. PHP has its own web app framework built in, although frameworks like Laravel, Symfony and Yii are also popular.

どのフレームワークや言語を選んだにせよ、WebhookはあらゆるTwilioアプリケーションに対して同様に機能します。 これらはTwilioに与えられたURIに対するリクエストを生成します。 アプリケーションはデータベースの読み書き、他のAPIとの統合、あるいは何らかの演算など、必要とされるあらゆる処理を実行し、それからTwilioに実行してほしい指示をTwiMLのレスポンスとしてTwilioに応答します。

TwilioおよびAmazon API GatewayでAmazon Lambdaを使用する

Although the piece that will eventually be exposed to the world will belong to API Gateway, it's conceptually easier to start with code on Lambda. Since this may feel backwards to you, be prepared for some forward references in this section. This will all become clear when we expose everything to the world from API Gateway.

To get started, from your choice of Amazon region, create a new Lambda function from your Lambda Console:

Lambdaファンクションを作成する

まだリージョン内にファンクションがない場合は、「Get Started Now」ボタンをクリックします。

今すぐLambdaをはじめよう

By paging or searching, choose the blueprint 'microservice-http-endpoint-python'. Next remove the 'API Gateway' trigger by hitting the red remove button. We will be adding our own trigger when we are done with the code.

'microservice-http-endpoint-python' gets us to a good starting position with lambda_function set up with the proper function signature to take input from API Gateway (eventually).

Lambdaのインラインエディターでコードを編集する

Our entire "Hello, World!" Application fits in 6 lines of code. Simply: we're going to import Python 3's print, print out all of the headers and HTTP parameters we've received, then return TwiML.

インラインエディターに下記のコード全体を入力します:

        
        
        
        
        6行のコードで、Python 2.7とAmazon Lambda上から「Hello, World!」と返信します。

        LambdaでSMSまたはMMSメッセージに返信する

        6行のコードで、Python 2.7とAmazon Lambda上から「Hello, World!」と返信します。

        リクエストヘッダーと本文のパラメーターへのアクセス

        All of the POSTted HTTP parameters and any Headers we choose to include will be inside the event dictionary. Although it appears to be magic at this point, there is a two step process in API Gateway to prepare event for our consumption. As API Gateway expects JSON input, we'll be using a Body Mapping and splitting on ampersand characters to prepare the dictionary for Python.

        print("Received event: " + str(event))
        

        There is some more magic in this line - print is redirected automatically to Amazon Cloudwatch. When our role and policies are properly setup, invocations of this function and any output will be found in CloudWatch.

        Generating TwiML Manually with Lambda and Python

        TwiML, Twilio's XML Markup Language, is incredibly powerful and lets you easily instruct Twilio on how to handle incoming actions. We're only using a tiny subset of TwiML today in order to respond to a message with a message of our own.

        return '<?xml version=\"1.0\" encoding=\"UTF-8\"?>'\
               '<Response><Message>Hello world! -Lambda</Message></Response>'
        

        With this string, we are first informing Twilio that we are responding with XML encoded in UTF-8. We then set up a Message tag nested inside a Response tag; the Message tag informs Twilio that we would like to reply with the contents of the tag (in this case by SMS).

        メディアを伴った返信を行う(MMSメッセージ - 日本未対応)

        Responding with an MMS is also very easy with the flexibility TwiML allows. Simply add a <Media> tag to the <Response> and you'll be peppering your message with pngs in no time (yes, other image formats work as well).

        Is your picture worth 1,000 words but you need 5,000? No problem - Twilio allows up to 10 media items per response.

        Creating a Role and Policy for Our Lambda Function

        Since we used the microservice-http-endpoint-python blueprint, Amazon makes it easy to set up a proper role and policy. Use the Policy Template 'Simple Microservice permissions' which should be pre-populated, and pick a name for your new role. We've chosen the name 'myTwilioRole':

        Lambdaのポリシーとロールの定義

        高度なLambdaの設定

        Under 'Advanced settings', feel free to set your Memory (MB) to the minimum of 128 MB. We've personally used a timeout of 10 seconds without issue.

        In production, you'll want to revisit these limits; note how Lambda's pricing changes based upon your selections.

        Lambdaファンクションを作成する

        We're now ready to create the function! Simply hit 'Next' to get to a review screen, and when satisfied create it.

        ここでは、上部の「Test」と書かれた青いボタンを使用して、ファンクションを自由にテストしてみましょう。 入力に関わらず、下記のような結果が表示されるはずです(ダブルクォートが含まれます):

        "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response><Message>Hello world! -Lambda</Message></Response>"

        Amazon API Gatewayをセットアップする

        Your lambda function now has resources allocated, policies and roles defined, and responds beautifully - our next step is to find a way to let the world speak with it. That's where API Gateway comes into play. We're going to use the Lambda/API Gateway integration to set up a path from Twilio to the Lambda function we just defined.

        API Gatewayのコンソールとお好きなリージョン(Lambdaファンクションのリージョンと一致している必要はありません)から、「Create API」を選択します。

        Amazon API GatewayでAPIを作成する

        先と同様、現在のリージョンでまだAPIがない場合、「Get Started」ボタンをクリックして開始します。

        API Gateway入門

        In the 'Create new API' screen, fill out an API name and Description. We're naming our API 'twilio_simple_responses' with a Description of 'Simply respond with Twilio.'.

        新規の名前と説明文を入力したら、「Actions」プルダウンで「Create Resource」を選択します。

        新規Resource API Gatewayの作成

        Name your resource something like 'Message Responder', and use a Resource Path of '/message'. Then 'Create Resource':

        API Gatewayでリソースを作成する

        Now select 'Create Method', select 'POST', and hit the check mark (✓). You'll then be taken to the setup screen. Here select 'Lambda Function' integration without Proxy integration, and select the region and name of your Lambda Function. Note that the 'Lambda Function' field will automatically search as you type - you likely only need to enter the first few characters to find your function:

        API GatewayでLambdaファンクションを設定する

        保存後に、権限許可のポップアップから「Okay」をクリックすると、Lambdaのインテグレーションは準備完了です!

        We're going to take the setup one step at a time to properly integrate our function with API Gateway. Note that the majority of changes we're going to make in the console are because API Gateway is designed for JSON input and output. We need to work around that in order for Twilio, which posts a form and expects XML, to understand our response.

        リクエストをLambdaファンクションに統合する

        Although our function is bare-bones now, most applications will eventually need some logic based upon incoming messages. We need to map a content type of application/x-www-form-urlencoded into JSON to work properly with API Gateway and Lambda. Click on 'Integration Request', then expand 'Body Mapping Techniques'.

        Next, click 'Add mapping template', inserting 'application/x-www-form-urlencoded' and hitting the check mark (✓). There will be a pop-up asking you to secure this mapping; confirm you would like to secure it. API Gateway will change your 'Request Body Passthrough' to 'When there are no templates defined (recommended)' (if it does not or you cancel the request move it now).

        We will use code first suggested by avilewin in the AWS Developer Forums to split our HTTP parameters into JSON key/value pairs. Enter this code into the editor which appears under the Content-Type box:

        #set($httpPost = $input.path('$').split("&"))
        {
        #foreach( $kvPair in $httpPost )
         #set($kvTokenised = $kvPair.split("="))
         #if( $kvTokenised.size() > 1 )
           "$kvTokenised[0]" : "$kvTokenised[1]"#if( $foreach.hasNext ),#end
         #else
           "$kvTokenised[0]" : ""#if( $foreach.hasNext ),#end
         #end
        #end
        }
        

        Next, go back to 'Method Execution' by following the link at the top of the frame. You may need to scroll up.

        LambdaレスポンスをAPI Gatewayと統合する

        Next, we need to do some plumbing from the output of our Lambda function. While in a traditional API you'd want to properly use HTTP status codes, you'll generally only want to respond with a 200 and sometimes a 401 to Twilio's request. Additionally, API Gateway is set up to respond with a 'Content-Type' of application/json, while Twilio expects application/xml. Let's fix that now for the 200 case.

        Click on the 'Integration Response' link. Expand the '200' Response, then expand the 'Body Mapping Templates'. If there is an 'application/json' entry, remove that now.

        Now click 'Add mapping template' and add application/xml. You'll want to enter this very simple mapping:

        #set($inputRoot = $input.path('$')) 
        $inputRoot
        

        Essentially, we are only echoing the return value of the Lambda function. This will also take care of the surrounding double quotes (") in the return string. 'Save' the mapping, and return to Method Execution with the link at the top of the screen.

        API Gatewayのレスポンス

        Click the 'Method Response' link. Under 'Response Body for 200', if application/json is defined, remove that now. Then simply add application/xml with an 'Empty' model and click the check mark (✓).

        Return to Method Execution with the link at the top of the screen.

        APIのデプロイとステージの選択

        あともう少しです - Actionsメニューから「Deploy API」を選択します:

        APIギャラリーにAPIを追加する

        You'll then be asked which stage to deploy to - if you don't yet have one created, you can create a new stage from the menu. Name your stage 'prod':

        API Gatewayで新規ステージを作成する

        Expand the 'prod' stage which appears (or surf to 'Stages' in the sidebar), and click on 'POST' under '/' and '/message'. At the top, you'll see an 'Invoke URL':

        API GatewayでURLを呼び出す

        Copy that URL... with a full clipboard we're 2/3 of the way to a serverless Twilio application! Let's push on.

        WebhookのURLを設定する

        From the Twilio Console, navigate to the Numbers Section in the sidebar (#). Next, select the number you'd like to route to our new Lambda function.

        Under 'Messaging' and in 'A Message Comes In', select 'Webhook' and paste the API Gateway URL into the text box (highlighted below). Ensure 'HTTP POST' is selected.

        SMS Webhook

        予備のWebhook URL

        You'll also notice the 'Primary Handler Fails' box. In production, you may want to have a secondary handler for incoming messages. Twilio will automatically fail-over to the secondary handler if it can't reach the primary handler in 15 seconds or if there is some other problem. See our Availability and Reliability guide for more details.

        Protect your webhooks

        Twilio supports HTTP Basic and Digest Authentication. Authentication allows you to password protect your TwiML URLs on your web server so that only you and Twilio can access them.

        Learn more about HTTP authentication and validating incoming requests here. You can also check out our full guide on securing your Python Amazon Lambda app.

        Twilio電話番号にメッセージを送信する

        And with that, all of the plumbing is complete! You now have Twilio watching for incoming messages, API Gateway listening for requests from Twilio, and Python logic in Lambda listening for API Gateway. Try texting your Twilio number to verify that the world still wants to say hello to you.

        What's Next? Making a Large Delta with Twilio and Lambda

        We highly suggest that you next visit our guide on validating incoming Twilio requests with Python on Lambda. In that article we'll explore some more advanced features of Lambda such as loading our Python Helper library and defining Environmental Variables, along with demonstrating some simple phone number checks and validating Twilio requests.

        If you're ready to press on, Add-Ons will often simplify your next steps. Add-ons make the Twilio platform even more powerful by allowing you to integrate some amazing tools and services from our partners into your application.

        Whatever you build, we're here to help - and to celebrate when you deploy. Let us know when you hit the deploy button by messaging us on Twitter!

        Paul Kamp Samuel Mendes David Prothero Kat King
        Rate this page:

        ヘルプが必要ですか?

        We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.