A composition story: using IBM Cloud Functions to relay SMS to email
I often receive alerts on my mobile phone via SMS but I do not always carry it with me. So I wanted to write an application which will accept SMS messages, and for each message, email the content to me and maybe others in case of an emergency alert. While I may not have my phone, I am usually still somewhere with email notifications. That increases my chances of getting the alert promptly, at least that’s the goal.
My first thought was surely there’s an IFTTT (if-this-then-that) way of doing this, where the SMS is an event trigger and send email is the action to take in response. Surprisingly, there isn’t a way to do this with IFTTT. While there is an SMS event provider, it does not permit arbitrary incoming SMS messages (i.e., they must originate from a specific phone number). That’s quite limiting.
So then I considered Twilio since it offers “programmable SMS”. It works like this: you buy a phone number which generates events via a webhook callback. You can separately provide a handler to process the text message. Sounds promising. But notice that to do this, I need to run my handler somewhere… somewhere that’s (nearly) always on and able to accept a request. The problem now is that I have to provision a web server to provide a webhook API. Twilio even offers blueprints for doing this:
- Adapt the template code they provide to fill in the
- “Publish this file to a publicly accessible URL on your web server.”
- Copy the URL into the Twilio console, configuring the SMS webhook.
So to run roughly 10 lines of code, now I need to develop and manage a web server. And pay for it to handle a low amount of traffic. That’s just wrong. This is a space where serverless computing with functions-as-a-service excels: upload your function to the cloud, and it runs almost instantly when it’s triggered by an event. You pay for what you use, and idle time is free.
So with serverless computing, I can write my function, eschew deploying a web server, and shift the burden of managing a virtual machine or container (to run the code) to the service provider.
Twilio does offer their own version of functions, which I tried first but found it too limiting in its current form. I get to write my own action, but I cannot upload dependencies and they don’t offer the Sendgrid package I want to use for the email generation. Sendgrid is a cloud-based email service provider (admittedly, it’s overkill for this application, but I use it for other reasons and already have an account, so it suits my use case). I could use the Sendgrid REST API directly, but why when there’s a
npm module for that? It’s more code that I have to write without their SDK. I could have smashed the
npm library into my own function, but now I’m doing even more work, obfuscating my code, and have to write tooling to create a webpack bundle.
It took me 5-10 minutes to get my application fully running on IBM Cloud Functions. I used the new functions shell (
fsh) to program my solution. The Twilio webhook attaches a JSON payload, from which I needed to extract two fields:
From. The former becomes the
content of the email and the latter will populate the
subject field. Finally to conform to the Twilio API, the webhook should respond with an XML formatted message. The overall solution is a sequence of three steps — project fields, send email, generate XML response — which I programmed using composer.
Saving this composition to a file called
twilio.js, I deploy it as a serverless application from a terminal using the shell CLI
$ fsh app create twilio twilio.js. It is sometimes helpful to validate the control flow before deploying the application, and the shell offers a way to do this with
$ fsh app preview twilio.js locally or
$ fsh app get twilio once deployed. The source code is available on GitHub.
The last bit is to point the Twilio webhook at the serverless application. Using
$ fsh webbify twilio I made the app accessible via a web action and configured the Twilio dashboard webhook settings accordingly.
Serverless computing offers the intriguing reality of executing individual functions in the “cloud” in response to specific events. The platform takes on the burden of provisioning resources to execute the function, and reclaiming the resources when the function returns. As a programmer, this is an attractive proposition because it means I can develop my code and deploy it to the cloud. I don’t have to reserve a container or virtual machine, create a web server, or deploy and operate my infrastructure.
With the shell for IBM Cloud Functions I incrementally developed my application, first discovering the Twilio API, independently testing the send mail action, and lastly composing the functions together. The composer saved me from having to creating small functions to align schema or produce the final response because I could inline the functions right into the composition. Together, the composer and the shell make programming for the serverless cloud pleasant, and fast.