Как отправлять SMS с помощью AWS Lambda, SNS и Python 3

Illustration of a robotic arm interacting with a laptop while a man observes closely, hinting at a concept of automation or robotic programming. Illustration of a robotic arm interacting with a laptop while a man observes closely, hinting at a concept of automation or robotic programming.

Вступление

В этой статье мы поговорим о том, как отправлять и получать СМС с помощью AWS. Мы начнем с создания логгера сообщений, который будет получать сообщения и записывать их содержание и отправителя. Затем мы создадим echo-сервис, который будет отвечать на любое сообщение полученным текстом. И наконец, мы назначим ежедневное сообщение на указанный номер телефона. Мы будем использовать СМС и различные сервисы AWS. Обратите внимание, что в рамках данной статьи мы взаимодействуем со всеми сервисами только через их веб-интерфейсы. Полноценные приложения в данном случае управляли бы кодом и службами с помощью технологий контроля версий, непрерывной интеграции/непрерывной доставки и инфраструктуры-как-кода, например Terraform или AWS CloudFormation. Однако для практики в использовании сервисов будет достаточно только интерактивной консоли AWS.

Amazon Web Services (AWS) предоставляют Lambda — бессерверную среду, позволяющую программистам выполнять дискретные функции без сервера. Написать и развернуть функцию AWS Lambda можно очень быстро, и она не нуждается в такой в поддержке, как, например, приложение, работающее на виртуальном сервере типа EC2. Функции в Lambda дешевы: обычно Amazon просит 20 центов (13 рублей) за миллион запросов (каждое выполнение функции считается запросом), а первый миллион запросов в месяц является бесплатным всегда и для всех пользователей. AWS предлагает множество методов для запуска этих дешевых и простых функций. В данной статье мы расскажем, как использовать AWS Lambda для отправки и получения СМС.

SMS (Short Message Service — служба коротких сообщений, СМС) — старейший протокол, используемый в миллиардах мобильных устройств по всему миру. Некоторые из его свойств могут выглядеть странно в сравнении с интернет-протоколами. Например, у каждого номера телефона есть код региона. В данной статье мы рассматриваем сервисы AWS в США и, соответственно, используем американский телефонный номер с кодом региона +1. Также этой устаревшей инфраструктурой можно объяснить тот факт, что СМС, в отличие от AWS Lambda, — довольно дорогой сервис. Когда все бесплатные сообщения израсходованы, вы вынуждены платить 0.0075$ (48 копеек) за получение и 0.00645$ (41 копейку) за отправку сообщения. Чтобы протестировать функции, описанные в этой статье, бесплатных сообщений будет достаточно, но подумайте хорошенько, подходит ли СМС-сервис для вашего приложения, принимая во внимание его цену. Например, приложение, которое отправляет всего одно СМС тысяче пользователей каждый день будет стоить вам почти 200$ (13 000 рублей) в месяц.

Получение СМС

Прежде всего, вам нужен аккаунт в AWS. Этот аккаунт даст вам доступ ко всем сервисам AWS, а также к «бесплатному уровню», позволяющему по доступной цене или абсолютно бесплатно попробовать большую часть продуктов и даже запустить небольшие приложения. Зайдите в аккаунт, перейдите к Lambda и создайте новую функцию.

Создание функции в Lambda

Имя функции может быть любым. Выберите Python 3.7, самый стабильный релиз Python 3, в качестве среды исполнения. AWS оперирует всеми своими сервисами, используя разрешения на основе ролей, систему, о которой в рамках этой статьи мы говорить не будем (хотя мы и рассмотрим ее позже). Для этой функции, выберите "Create a new role with basic Lambda permissions", и AWS все сделает за вас. После настройки параметров, кликните "Create Function", чтобы попасть на страницу редактирования функции.

Дизайнер функции в Lambda

В этом окне есть несколько важных кнопок. Самая важная — "Save" сохраняет любые изменения в Lambda-функции, а "Test" дает вам писать и выполнять тесты для вашей функции. Если вы не нажмете кнопку "Save", изменения в вашей функции не будут сохранены.

Дизайнер функции в Lambda позволяет вам выбрать, какие сервисы могут запускать функцию, и к каким из них функция может обращаться во время запуска. Мы будем использовать следующие сервисы: SNS (Simple Notification Service — Простой сервис уведомлений), CloudWatch Events для триггеров, а Amazon Pinpoint и Amazon CloudWatch Logs во время выполнения функции.

Чтобы добавить сервис в функцию, просто кликните на него в списке слева от дизайнера. Для начала добавьте SNS в качестве триггера. Вам нужно будет присвоить SNS роль, необходимую для запуска Lambda-функций (AWS предложит вам это сделать), затем сохранить функцию. Обновите страницу и прокрутите вниз, чтобы увидеть код функции.

Написание функции в Lambda

AWS предлагает онлайн-среду разработки для программирования функции в Lambda. Вы можете импортировать библиотеки и писать свои методы. Однако когда Lambda-функция срабатывает, на самом деле запускается функцияlambda_handler(). Этот основной метод принимает event и context в качестве параметров. event — огромный словарь, доступный функции, аcontext хранит собственно контекст выполнения. Нам нужно будет ссылаться только на event. Наша первая функция будет невероятно простой: она получает номер телефона и текст сообщения и записывает их в ваши логи CloudWatch.

import json
def lambda_handler(event, context):
    message = json.loads(event['Records'][0]['Sns']['Message'])
    words = message['messageBody']
    number = message['originationNumber']
    return {
        'statusCode': 200,
        'body': json.dumps("Phone number: {}\nMessage Text: {}".format(number, words))
    }

message — словарь, который мы выгружаем из event. Мы извлекаем тело сообщения (сам текст сообщения) и номер источника (номер, с которого отправлено СМС). Пока что просто скинем эту информацию в CloudWatch. В качестве теста можно отправить СМС на связанный с функцией номер. Для этого нужно активировать AWS Pinpoint. Хотите пропустить этот шаг? Ниже я объясню, как тестировать функцию, используя встроенную в Lambda службу тестирования, но важно понимать Pinpoint для, собственно, отправки сообщений.

Создание Pinpoint-проекта

После того, как вы активируете свой первый Pinpoint-проект, на экране настроек кликните "Manage" под "SMS and Voice".

Настройка Pinpoint-проекта

Запрос длинного (федерального) номера

Затем запросите длинный номер — телефонный номер специально для вашего проекта. Такие номера стоят 1 доллар (64 рубля) в месяц, так что не забудьте отказаться от него после окончания тестирования. Выберите нужную вам страну, куда будут отправляться сообщения, и установите тип вызова как «рекламный» ("Promotional") по умолчанию. После получения номера нужно будет добавить Pinpoint к роли IAM, связанной с Lambda-функцией, посредством добавления следующего разрешения к роли в консоли IAM.

Разрешения для Pinpoint

Теперь вы можете отправлять сообщения вашей Lambda-функции. Однако вместо этого вы можете имитировать отправку с помощью тестирования, встроенного в Lambda. В качестве шаблона выберите "Amazon SNS Topic Notification" и назовите событие, как вам захочется. Вставьте следующую строку в качестве значения, ассоциированного с ключом Message, как показано на картинке.

Настройка тестового события

"{\"originationNumber\": \"+19997771111\",\"messageBody\": \"This is the test message\",\"inboundMessageId\": \"EXAMPLE\",\"previousPublishedMessageId\": \"EXAMPLE\",\"messageKeyword\": \"keyword_example\",\"destinationNumber\": \"+10120120123\"}"

Не забывайте о том, что event — это просто словарь, и именно поэтому мы можем протестировать Lambda-функцию с помощью создания собственного события. Сохранив тест, нажмите "Test" в правом верхнем углу экрана, чтобы выполнить Lambda-функцию. При успешном выполнении консоль покажет вам, что вернула функция.

Отправка СМС

Мы уже научились получать СМС, так что теперь самое время поговорить об отправке. Этот шаг, в отличие от получения сообщений, требует, чтобы вы заранее настроили AWS Pinpoint для тестирования. Чтобы продемонстрировать процесс отправки и получения СМС, мы настроим простой echo-сервис: вы отправляете сообщение, на которое сервис отвечает вашим же текстом.

import json
import boto3
pinpoint = boto3.client('pinpoint')
def lambda_handler(event, context):
    message = json.loads(event['Records'][0]['Sns']['Message'])
    pinpoint.send_messages(
        ApplicationId='YOUR_PINPOINT_APPLICATION_ID',
        MessageRequest={
            'Addresses': {
                message['originationNumber']: {'ChannelType': 'SMS'}
            },
            'MessageConfiguration': {
                'SMSMessage': {
                    'Body': message['messageBody'],
                    'MessageType': 'PROMOTIONAL'
                }
            }
        }
    )

Импортboto3 позволяет нам инициализировать pinpoint-объект для отправки сообщений. Сообщение будет отправлено с того самого длинного телефонного номера, который вы запросили ранее. Все, что вам нужно сделать для настройки, это вставить ваш идентификатор приложения для Pinpoint.

Эту систему можно использовать для создания СМС-чатбота, например, виртуальной службы поддержки клиентов (хотя веб-чат будет в разы дешевле). Еще одна область применения — отправка отложенных СМС. Изменив триггер с SMS на события CloudWatch, можно создать приложение, каждое утро уведомляющее вашего босса о вашем опоздании с извинениями. Выберите "CloudWatch Events" в левом меню и настройте параметры, как показано на рисунке.

Настройка тестового события

import json
import boto3
import random
pinpoint = boto3.client('pinpoint')
def lambda_handler(event, context):
    messages = ['Стою в пробке, извините.',
                'Проблемы с машиной, скоро буду.',
                'Сын заболел.',
                'Вчера вечером остался в офисе допоздна, нужно было доделать контракт.']
    pinpoint.send_messages(
        ApplicationId='YOUR_PINPOINT_APPLICATION_ID',
        MessageRequest={
            'Addresses': {
                'BOSS_PHONE_NUMBER': {'ChannelType': 'SMS'}
            },
            'MessageConfiguration': {
                'SMSMessage': {
                    'Body': random.choice(messages),
                    'MessageType': 'PROMOTIONAL'
                }
            }
        }
    )

Оправдания получше, как и установка номера AWS Pinpoint в качестве вашего контакта в телефоне вашего начальника, лежат на ваших плечах. Я, конечно же, ни в коем случае не одобряю подобные вещи.

Теперь вы знаете, как отправлять и получать СМС с помощью AWS Lambda. У AWS Lambda много мощных и разнообразных функций, которые позволяют сделать гораздо больше, чем просто СМС-сообщения. СМС-сервис, если он необходим для вашего приложения, легко настроить и использовать, но его стоимость, а также проблемы с задержкой сообщений подойдут далеко не для всяких целей. Но это все еще лучший вариант для функций типа подтверждения номера телефона. К тому же, СМС поддерживается такими голосовыми помощниками, как Сири и Алекса. Если вашему клиенту необходимы СМС в его проекте, AWS Lambda — отличный выбор.

Давайте повторим, что мы сегодня использовали:

  • Lambda для бессерверных функций,
  • SNS для получения уведомлений и СМС,
  • Pinpoint для отправки СМС и получения телефонного номера,
  • IAM для управления доступом и разрешениями,
  • CloudWatch для процессов мониторинга, регистрации и запуска.