История создания одного бессерверного приложения рассылки с открытым ПО

Как-то я создал сервис информационных рассылок Revue для публикации авторских материалов по бессерверной разработке. Он отлично работал и включал ряд интересных функциональностей, которые предоставляли краткие недельные отчеты. Revue был интегрирован напрямую с Twitter, позволяя пользователям регистрироваться из моего профиля. А самое главное, он был бесплатным

К моменту написания статьи сервис Revue прекратил работу. Пришлось искать другое решение для выпуска информационной рассылки, поскольку было бы несправедливо по отношению к подписчикам прерывать обслуживание. 

Я изучил такие сервисы рассылок, как MailChimp, Sendinblue и ConvertKit. Они вполне подходили для намеченных целей, если бы не платные расширенные возможности. Большинство из подобных сервисов на бесплатной основе поддерживали до 300 подписчиков. Мне же повезло обзавестись намного большим количеством читателей, подписанных на рассылку Serverless Picks of the Week (Недельная подборка новостей из мира бессерверных технологий).

В итоге я решил сам создать платформу для рассылки. А что? Разве состоявшийся инженер-программист, который разбирается в бессерверных технологиях и заслужил звание AWS Hero (Героя AWS), не справится с этой задачей? Бессерверные технологии обладают рядом преимуществ: стоят недорого, автоматически масштабируются в соответствии с требованиями и котируются как один из самых быстрых способов создания ПО. 

Кроме того, мне удалось автоматизировать перекрестную рассылку статей на несколько сайтов со ссылкой на свой блог. Эта функциональность также могла послужить основой для выпуска рассылок. Задача казалась вполне осуществимой! 

Самым нетерпеливым и желающим познакомиться сразу с результатом, предлагаю ссылку на репозиторий с открытым исходным кодом. Изучайте и практикуйте! 

Поиск движка для email-рассылки

Чтобы создать пользовательское приложение для информационной рассылки, прежде всего требовалось решить вопрос с отправкой самого электронного письма. Для этой цели существует множество библиотек, но нужно было подобрать именно управляемый сервис. 

Добиться того, чтобы отправленные электронные письма не попадали в категорию спама, было сложно. Для этого требовались специальные знания и постоянное сопровождение, но обеспечить выполнение этих условий не представлялось возможным. Поэтому из всех существующих вариантов рассматривались два, наиболее знакомых: Amazon SES и SendGrid

По умолчанию предпочтение отдается сервисам AWS. Все мои ранее создаваемые продукты размещались и управлялись с использованием AWS. Данный случай не стал исключением. 

Сначала я изучил возможности сервиса Amazon SES, но они не вполне соответствовали требованиям. Предоставлялись управление репутацией и статистика отправки, но не хватало самой важной функциональности  —  управления процессами маркетинговой кампании.

Я отслеживаю каждый выпуск рассылки как отдельную маркетинговую кампанию, что позволяет получать по нему основные статистические данные. Они показывают: количество адресатов рассылки, количество открытых и вернувшихся электронных писем, количество переходов по ссылкам внутри рассылки. 

В поисках требуемой функциональности я обратился к SendGrid и нашел там все что нужно. Сервис позволял создать Single Send, т.е. одноразовое электронное сообщение, доставляемое списку контактов. Как раз подходящий вариант рассылки! 

Кроме того, SendGrid предоставляет замечательный спектр услуг на бесплатной основе: управление контактами общей численностью до 2000 подписчиков и отправка до 6000 одноразовых сообщений Single Send в месяц. Идеальный вариант для формата моей рассылки с учетом перспектив ее роста! 

Выбор сделан  —  и это SendGrid. Он стал движком для управления рассылкой в разрабатываемом бессерверном приложении. 

Создание рабочего процесса

За последние несколько лет мне удалось бегло познакомиться с SendGrid. Мы применяли его в рабочих целях на базовом уровне, когда отправляли пользователям уведомления. Собственно говоря, этими навыками и ограничивался мой опыт взаимодействия с данным сервисом. 

Мне предстояло создать приложение с функциональностями, которые ранее не разрабатывал. Приступив к работе, я быстро сообразил, что не получится программным способом опубликовать сообщение Single Send через SendGrid. Требовалось ручное нажатие на кнопку графика рассылки/отправки. 

Сначало мне это не понравилось. Однако, поразмыслив, расценил данное решение как отличную меру безопасности. Не хотелось бы отправлять тысячам подписчиков электронное сообщение с явной опечаткой или серьезной ошибкой форматирования. В результате получился следующий рабочий процесс: 

Рабочий процесс создания и выпуска информационной рассылки

Весь свой контент я пишу в Markdown. При сохранении новой статьи блога или информационного письма они компилируются в HTML посредством фреймворка Hugo в конвейере CI моего проекта AWS Amplify. После успешного завершения сборки Amplify направляет событие в EventBridge, где оно подхватывается рабочим процессом. 

Последовательность этапов:

  1. Написание информационного письма в Markdown и отправка в главную ветку репозитория GitHub. 
  2. Сборка Amplify компилирует в HTML и публикует контент на сайте. 
  3. Запуск функции Lambda, загружающей файл Markdown из репозитория. 
  4. Запуск рабочего процесса Step Function, который анализирует контент, преобразует его для SendGrid и создает сообщение Single Send.  
  5. Получение электронного письма со ссылкой для просмотра созданного сообщения Single Send и нажатие кнопки Approve (Одобрить). 
  6. Осуществление SendGrid предусмотренной графиком доставки всем подписчикам. 

Такой автоматизированный рабочий процесс еженедельно экономит массу времени. В случае с Revue приходилось локально просматривать HTML-контент на сайте, копировать и вставлять его в Revue, после чего реорганизовывать и повторно отправлять изображения и встроенную информацию.

Сам по себе процесс не представлял сложности, но занимал время и сопровождался ошибками. 

Автоматизация процесса посредством кода экономит время и не позволяет ничего упускать из внимания. 

Преобразование данных 

SendGrid снабжен отличной функциональностью под названием динамические шаблоны. Они предназначены для создания параметризованных электронных сообщений посредством шаблонизатора Handlebars.

Динамические шаблоны позволяют передавать необработанные данные и форматировать их в последовательный структурированный HTML. SendGrid предоставляет замечательные возможности взаимодействия с пользователями в процессе создания шаблонов. Вы можете перетаскивать компоненты информационного письма, расширять их посредством кода, использовать тестовый стенд для просмотра объединенных шаблонов.

Я решил разместить шаблон информационного письма в SendGrid. Использование компоновщика позволяет быстро корректировать формат и оперативно просматривать вносимые изменения. В приложении для рассылки шаблон загружается через SendGrid API, а слияние данных осуществляется с помощью npm-пакета Handlebars.

Однако для слияния данных в динамическом шаблоне требуется привести контент в определенный формат. Функция Lambda, выполняющаяся как часть рабочего процесса Step Function, преобразует разметку Markdown информационного письма в отформатированный объект JSON:  

{
"metadata": {
"number": 1,
"title": "My first newsletter!",
"date": "2023-01-01",
"url": "https://readysetcloud.io/newsletter/1"
},
"content": {
"sections": [
{
"header": "Serverless Superhero",
"text": "<p>Congrats to our serverless superhero!</p>"
}
]
}
}

Структурируя контент информационного письма как объект JSON, вы позволяете пакету Handlebars подставлять значения в шаблон сообщения. Тем самым обеспечивается удобство дальнейшего сопровождения за счет отделения данных от форматирования. Например, вы без труда можете корректировать стиль определенного компонента, поскольку отпадает необходимость трогать данные и привносить дополнительные риски к изменениям. 

После слияния данных в шаблоне приложение задействует SendGrid API для создания сообщения Single Send, вслед за чем я получаю электронное письмо для просмотра созданного сообщения. 

Дополнительные возможности 

Сервис Revue располагал полезной функциональностью, о потере которой я весьма сожалел. По прошествии нескольких дней он отправлял мне краткий отчет о результатах рассылки. Я подумал, что было бы неплохо снять с себя часть нагрузки и перепоручить ее SendGrid. Так что составил список востребованных функциональностей: 

  • спонсорская поддержка; 
  • автоматические напоминания; 
  • краткий отчет о выпуске рассылки; 
  • отслеживание количества подписчиков. 

Все эти функциональности уже встроены в приложение для рассылки, так что можно брать и пользоваться. 

Спонсоры 

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

Данное приложение отслеживает всех спонсоров информационной рассылки и управляет календарем выпусков на основе JSON. За 5 дней до нового выпуска приложение находит очередного спонсора и отправляет контактному лицу электронное письмо с напоминанием о предстоящем рекламном объявлении. Получив от заинтересованной стороны рекламу для размещения, я добавляю ее в метаданные информационного письма, и готово!

Реклама в письме отображается благодаря добавлению короткого кода, который вставляет ее в любое место. Автоматизированный процесс подхватывает этот код и заменяет отформатированное рекламное объявление расширенным контентом о спонсоре. 

Метрики информационного письма

Каждую неделю я просматриваю индивидуальную статистику, отражающую результаты проведения рассылки. SendGrid выполняет мониторинг множества метрик наряду с отслеживанием нажатий, предоставляя ценные данные о взаимодействии подписчиков с контентом. 

Проблема в том, что рассылка не является моей основной работой, и я часто забываю проверить статистику. Когда же вспоминаю, то уже не остается времени внести улучшающие корретивы для следующей рассылки. 

Я создал рабочий процесс Step Function с запланированным запуском для еженедельной проверки статистики. Он загружает последнюю рассылку, затем с помощью SendGrid API получает метрики и текущее количество подписчиков, после чего отправляет электронное сообщение с кратким отчетом и прямую ссылку на страницу подробного анализа:

Такой отчет приходит по пятницам. Я сажусь за компьютер, а на почте уже ждет письмо со статистикой последней рассылки четырехдневной давности и отчет о динамике подписчиков по сравнению с предыдущей неделей!  

Заключение 

Проект сам по себе оказался увлекательным и решал ряд проблем. Как и автоматизация перекрестной рассылки, он еженедельно экономит массу времени.  

Рекомендую убирать человеческий фактор при первой возможности. Люди совершают ошибки, и я не исключение. Теперь же я не забываю отправлять напоминание спонсорам и проверять статистику рассылки. Кроме того, своевременно выявляю ошибки и форматирую версии писем рассылки при копировании и вставке. 

Созданная платформа с открытым исходным кодом. Вы можете свободно пользоваться и обновлять ее по своему усмотрению. Потребуется лишь создать аккаунт SendGrid. Файл README содержит все необходимые инструкции по настройке. 

Благодаря бесплатному уровню SendGrid и низкой стоимости реализации бессерверных AWS, обеспечивающих работу данного сервиса, это решение ничего не будет стоить, пока вы не наберете более 2000 подписчиков или не отправите свыше 6000 сообщений в месяц.

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Allen Helton: How I Built an Open-Source Serverless Newsletter Platform

Предыдущая статьяКак отобразить индикатор выполнения на стандартной консоли с помощью Java
Следующая статьяПочему не стоит писать простой код JavaScript?