How to send SMS using NodeJS and Azure Functions

April 16, 2024
Written by
Reviewed by

How to send SMS using NodeJS and Azure Functions

Want to add SMS capabilities to your web application without managing servers? In this blog post, I will show you how to easily send SMS messages using Node.js and Azure Functions. Functions as a Service (FaaS), like Azure Functions, offer a serverless approach to development. This means you don't need to worry about maintaining complex infrastructure – just write your code and let the platform handle the rest. Serverless solutions offer advantages like scalability, cost-effectiveness, and ease of deployment.

Let's dive into building the Azure Function project using the CLI and learn how to send SMS messages in a snap!

Prerequisites

Before we can move forward, make sure you have the following.

Developing Azure Function locally

Today, we will create our own SMS sending service using Azure Functions and Twilio. Azure Functions is a serverless offering that allows us to deploy our code to the cloud without worrying about the underlying infrastructure.

Let’s start with creating the Azure Function project locally on our machine. You will need the Azure Functions Core tools installed. Once you have it installed, run the following command in your terminal.

func init MyTwilioProject --worker-runtime javascript --model V3

This command creates a JavaScript project that uses the desired programming model version.

Now, let's create a function. To add a function to our project, run the func new command using the --template option to select your trigger template. The following example creates an HTTP trigger named SMSTrigger:

cd MyTwilioProject
func new --template "Http Trigger" --name SMSTrigger

Now you should see a new directory within your MyTwilioProject directory, called SMSTrigger. This directory has two files that were generated: index.js and function.json.

Directory tree in the root of the project "MyTwilioProject"

Writing the Azure Function

In order to use Twilio within our function, we will need to install the npm package:

npm install twilio

Now let’s edit the index.js in our SMSTrigger directory so that it can use Twilio library to send an SMS.

cd SMSTrigger
const twilio = require("twilio");

module.exports = async function (context, req) {
  context.log("JavaScript HTTP trigger function processed a request.");

  const number = req.query.number || (req.body && req.body.number);
  const message = req.query.message || (req.body && req.body.message);
  
  if (number && message) {
    const accountSid = process.env["TWILIO_ACCOUNT_SID"];
    const authToken = process.env["TWILIO_AUTH_TOKEN"];
    const client = new twilio(accountSid, authToken);
    client.messages
      .create({
        body: message,
        from: process.env["TWILIO_PHONE_NUMBER"],
        to: number,
      })
      .then((message) => console.log(message.sid));
      
      context.res = {
        // status: 200, /* Defaults to 200 */
        body: "Message sent"
    };
  } else {
    context.res = {
        status: 400,
        body: "Please pass a number and message on the query string or in the request body"
    };
  }
};

Also, for the purposes of this demo, let’s set the Azure Function authentication level to anonymous so that we can trigger the function via HTTP with no key (Authorization).

Edit the function.json in the SMSTrigger directory, set the "authLevel": "anonymous".

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

With our JavaScript code in place, we are left with setting up the credentials for our Twilio library. We will be using Account SID and AUTH token from our Twilio account.

Configuring your Twilio Account

Once you are logged in to the Twilio Console, scroll down to find your Account SID and Auth Token. Copy these values, as we will save these as Environment Variables within our Azure Function.

Twilio Console home screen with Account SID and Auth token highlighted

To send a message, you will need to buy a phone number—ideally from the region you are based in—to avoid roaming charges. To accomplish this, go to the Twilio Console and search for a number you’d like to buy.

Buy a number screen in Twilio Console, with numbers from Canada

Now that we have the Account SID, Auth token and a Twilio phone number. Let’s update the local.settings.json inside the MyTwilioProject folder:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": "",
    "TWILIO_ACCOUNT_SID": "<your-account-sid>",
    "TWILIO_AUTH_TOKEN": "<your-auth-token>",
    "TWILIO_PHONE_NUMBER": "<your-twilio-phone-number>"
  }
}

Testing the Azure Function locally

To run the Azure Function locally, (yes it is possible, thanks to Azure Functions core tools) in the root directory of our project MyTwilioProject, run the following command:

func start

And your function is now running locally.

Azure Functions CLI command "func start" output

Now we can test our function by sending a POST request to the SMSTrigger URL - http://localhost:7071/api/SMSTrigger with the following query parameters:

  • message
  • number

You can use a tool like Postman or curl.

Here is how the request would look like in Postman.

Postman application with GET request to the local azure function with message and number parameters.

After you hit send, you will get a response “Message Sent”

Postman application with GET request to the local azure function get a 200 OK Body response with "Message Sent"

If you want to use curl:

curl -m 70 -X GET http://localhost:7071/api/SMSTrigger/ \
-H "Content-Type: application/json" \
-d '{
  "message": "Ahoy from Azure Functions",
  "number": "<YOUR_PHONE_NUMBER>"
}'

And you will also see the output in terminal, where you have your Azure Function running locally. Similar to this one:

[2024-04-11T19:34:04.647Z] JavaScript HTTP trigger function processed a request.
[2024-04-11T19:34:04.648Z] Executed 'Functions.SMSTrigger' (Succeeded, Id=0cb9726b-d1a1-4ca9-b51e-bf810b42e144, Duration=12ms)
[2024-04-11T19:34:05.121Z] SMb8453db8aa2a7a08646bb93f216d14aa

If you check your phone, you should have received a text message “Ahoy from Azure Functions”.

iPhone Messages application with SMS received "Ahoy from Azure Functions."

Deploying Azure Function to Azure

We have our Azure Function working locally, now it’s time to deploy it to the cloud. There are two ways you can do this, either via the Azure Portal or using the Azure CLI (either installed locally or accessed via Cloud Shell ).

I am going to show you how to deploy the Azure Function using the Azure CLI within Cloud Shell. Login into your Azure account and open the Cloud Shell, just select Try it from the upper right corner of a code block. You can also launch Cloud Shell in a separate browser tab by going to https://shell.azure.com.

Azure Portal with Cloud Shell icon on top right highlighted.

 

After the Cloud Shell is launched, create a new script twilio-azure-function.sh and add the following code.

touch twilio-azure-function.sh
nano twilio-azure-function.sh
# Function app and storage account names must be unique.

# Variable block
let "randomIdentifier=$RANDOM*$RANDOM"
location="eastus"
resourceGroup="twilio-azure-functions-rg-$randomIdentifier"
tag="create-function-app-consumption"
storage="twiliofunc$randomIdentifier"
functionApp="twilio-azure-function-$randomIdentifier"
skuStorage="Standard_LRS"
functionsVersion="4"

# Create a resource group
echo "Creating $resourceGroup in "$location"..."
az group create --name $resourceGroup --location "$location" --tags $tag

# Create an Azure storage account in the resource group.
echo "Creating $storage"
az storage account create --name $storage --location "$location" --resource-group $resourceGroup --sku $skuStorage

# Create a serverless function app in the resource group.
echo "Creating $functionApp"
az functionapp create --name $functionApp --storage-account $storage --consumption-plan-location "$location" --runtime node --resource-group $resourceGroup --functions-version $functionsVersion

Let’s give our script the right permissions so that we can execute it.

chmod +x twilio-azure-function.sh

Now, let’s run the script.

./twilio-azure-function.sh

You will see that the resources will be created one by one.

Optionally you can install the Azure CLI locally and run the same script from your own machine.

If we check our Azure account now and look for the Resource Group, you will find all the resources that we just created.

Azure Portal with twilio-azure resource group open with all resources we created.

Now head over to your terminal where you have the local Azure Function running. Make sure you are in the MyTwilioProject directory. If your local Azure Function is still running, you can stop it by CTRL + C key combination. To deploy our local Azure Function, we will run the functionapp publish command.

func azure functionapp publish <FunctionAppName> --publish-local-settings

We are using the --publish-local-settings option to automatically create app settings in your function app based on values in the local.settings.json file.

You can find your Function App Name from the Azure Portal.

Azure Portal with twilio-azure resource group open, highlighting Azure Function App.

After you run the command, you might get a prompt if the local settings are different from the Azure Function settings. Type yes.

Azure Functions CLI functionapp publish command output.

Voila! We have deployed our Azure Function to the cloud. The Invoke url is our Azure Function HTTP Trigger, which now we can use to send SMS.

curl -m 70 -X GET https://twilio-azure-function-8181600.azurewebsites.net/api/smstrigger \
-H "Content-Type: application/json" \
-d '{
  "message": "Ahoy from Azure Functions in Cloud.",
  "number": "<YOUR_PHONE_NUMBER>"
}'

TING TING! We just received a text message from our Azure Function!

Messages application on iPhone received SMS "Ahoy from Azure Functions in Cloud."

If you would like to clean-up the resources that we just created with this project, you can delete the resource group within Azure Portal, that was just created. This would delete all the infrastructure that was created to avoid any charges.

Conclusion

In conclusion, integrating Azure Functions with Twilio to send SMS messages using NodeJS offers a powerful, scalable, and cost-effective solution. This combination leverages the serverless cloud infrastructure of Azure and the seamless communication capabilities of Twilio, providing a reliable and efficient way to send SMS. With the simplicity of NodeJS and serverless architecture, developers can easily implement and maintain this solution without the need for extensive infrastructure management. This integration not only streamlines the process of sending SMS messages but also opens up possibilities for other innovative applications. I can't wait to see what you build!

Rishab Kumar is a Developer Evangelist at Twilio and a cloud enthusiast. Get in touch with Rishab on Twitter @rishabincloud and follow his personal blog on cloud, DevOps, and DevRel adventures at youtube.com/@rishabincloud.