Sending SMS Messages with Amazon SNS, AWS Lambda and Python

Did you know that you can send SMS messages easily with Amazon SNS without subscribing any phone numbers to a topic? Let’s say that you have verified phone numbers and you would like to send text messages to them assuming that they opted in for this. Besides, you would like to pay only when you send. You can use Amazon SNS SDK for Python and automate this process using AWS Lambda.

What is Amazon SNS?

Firstly, let’s talk about Amazon SNS briefly. Amazon Simple Notification Service or shortly SNS, is a managed AWS service to send messages to different endpoints and clients. In basic usage, you subscribe these endpoints such as emails or phone numbers to an Amazon SNS topic and these subscribers receive published messages after they verified the subscription.

To give an example, let’s say that you have an Autoscaling Group and you would like to be notified when a scaling event occurs. You can definitely create a topic, integrate it with your Autoscaling Group and subscribe to this topic to get these notifications.

Amazon SNS is also useful for decoupling your applications as you can subscribe an Amazon SQS queue to process the messages later or an HTTP/S endpoint to make an HTTP requests or even an AWS Lambda function to trigger when a message is published.

In all these cases, you need to subscribe the endpoint before publishing messages for them to be able to receive your messages.

What about sending SMS via Amazon SNS?

In nowadays, when you need to send messages programmatically, possibly the first thing comes to your mind would be using a cloud service such as Twillio and their API. That is definitely fine and you can continue with this approach if you are already happy with it.

However, there is an alternative using Amazon SNS and sending automated SMS messages does not require creating an SNS topic and subscribing any phone numbers beforehand. It is like using Amazon SNS API instead of that other service. You can also develop an all AWS solution using AWS Lambda and trigger this function via an API Gateway endpoint or CloudWatch Scheduled Event or any other trigger whichever suitable for your use case as long as AWS Lambda supports.

Of course, it does not have to be serverless, you can use this approach in your web applications you run on your servers. But, serverless is beautiful as you do not need to manage or pay for any servers and ensure that your service is running when needed, isn’t it?

How much does it cost?

Well, this is an important point. Like in other AWS services, you pay only for what you use. The pricing is per message, but there are two types of messages and their prices might differ in some countries.

  • Transactional Messages: These are messages that are optimized for high delivery success rate. These messages often use more expensive routes according to ensure that they are delivered. Therefore their prices can be more expensive. One time passwords/PINs are good examples to this type of messages.
  • Promotional Messages: These are messages that are optimized for cost savings and often use less expensive routes with a reasonable delivery rate. You should never mark promotional messages as transactional, because there might be legal implications of doing so in some countries and your account might be marked for abuse.

Therefore, there are two things to consider: Pricing and conforming to law. Actually, as of today, the pricing does not differ when messages are sent to Turkey as the screenshot below shows. However, even so, you should mark your promotional messages correctly to be inline with legal requirements.

Amazon SNS SMS pricing for Turkey - 2018/05

As you can see, different operators and their prices listed. Please check the latest pricing from Amazon SNS - SMS pricing page to get up-to-date information.

Example AWS Lambda function with Python

As we made our case, let’s see an example about how we can send an SMS message with Amazon SNS. We will not need an Amazon SNS topic for this. We will simply use AWS SDK for Python (Boto3) to send an SMS message with SNS.

The Python code for our AWS Lambda function looks like below:

import logging
import boto3

# Initialize logger and set log level
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# Initialize SNS client for Ireland region
session = boto3.Session(
    region_name="eu-west-1"
)
sns_client = session.client('sns')


def lambda_handler(event, context):

    # Send message
    response = sns_client.publish(
        PhoneNumber=event["phone_number"],
        Message='Hi there! This is a test message sent with Amazon SNS',
        MessageAttributes={
            'AWS.SNS.SMS.SenderID': {
                'DataType': 'String',
                'StringValue': 'SENDERID'
            },
            'AWS.SNS.SMS.SMSType': {
                'DataType': 'String',
                'StringValue': 'Promotional'
            }
        }
    )

    logger.info(response)
    return 'OK'

Here, we get the phone number from event object provided to AWS Lambda. According to your triggering method you should configure this accordingly. You can also read from a database such as Amazon DynamoDB or perform another logic.

Let’s talk about MessageAttributes key-value pairs:

  • AWS.SNS.SMS.SenderID is optional. I used here to show that you can define a 10 characters long sender ID that will be shown in the receiving phone if it is supported in their country. Unfortunately, it is not suported in my country and I see only NOTICE as sender.

  • You should use AWS.SNS.SMS.SMSType atribute to mark your message as promotional or transactional as we discussed earlier in this post.

IAM role for AWS Lambda

We need to grant permissions to our AWS Lambda function to be able to send SMS messages using Amazon SNS. As you do in other IAM roles for your AWS Lambda functions, create a role with trusted entity as Lambda. Then attach AWSLambdaBasicExecutionRole managed policy for sending logs to Amazon CloudWatch and an inline JSON policy for SNS publish action as shown below.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "*"
        }
    ]
}

Attach this IAM role to your AWS Lambda function and you should be able to send SMS messages when you test it by providing a phone number which is in E.164 format such as +1XXX9990900 in US or +90XXX1112233 in Turkey. Your message should be maximum 140 bytes size or Amazon SNS will send multiple messages and it will cost accordingly.

Conclusion

In this post, I discussed a serverless solution to send SMS messages using Amazon SNS, AWS Lambda and Python. You can send SMS messages without creating a topic and subscribing receiving phone numbers, only using Amazon SNS SDKs and your favourite programming language supported by AWS Lambda.

I hope it gave you an idea about how you can use this feature in your applications. If you need help, contact me and let’s work together on a solution for your use case.

Thanks for reading!

References

Emre Yilmaz

AWS Consultant • Instructor • Founder @ Shikisoft

Follow