﻿# Рассылки от программистов для программистов

У нас появились почтовые рассылки новостей\! Наши программисты обратили внимание, что любят получать информацию о других продуктах по электронной почте, а для PVS\-Studio такой возможности нет\. Поэтому одна из команд разработки собралась и сделала рассылки, какими хотела бы их видеть\. Свой "велосипед" за год, зато интересно\! Узнали себя? Добро пожаловать под кат\.

![0979_Mailling_ru/image1.png](https://import.viva64.com/docx/blog/0979_Mailling_ru/image1.png)

## Введение

В августе 2021 года мы были на середине разработки новой системы для обработки запросов от наших пользователей \(пробные лицензии, поддержка и т\.п\.\)\. Именно в этот момент мы поняли, что новости из нашего блога – это точно такой же материал о нашем продукте, который мы уже доставляем нашим пользователям по почте в ответ на запросы с сайта\. А технически это реализуется почти идентично\. Тогда мы решили включить разработку рассылок в новый проект и ввязались в эпический таск на целый год:

![0979_Mailling_ru/image2.png](https://import.viva64.com/docx/blog/0979_Mailling_ru/image2.png)

## Анализ контента

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

Наш [блог](https://pvs-studio.ru/ru/blog/posts/) сейчас выглядит примерно так:

* около 10 статей в месяц для разных языков программирования;
* каждые 2 месяца пишется статья о новом релизе;
* иногда публикуются статьи не на технические темы;
* всё делится на 4 категории: C\+\+, C\#, Java, без категории;
* есть ещё целых 16 тегов\.\.\.

Конструктор рассылок со всеми возможными опциями показался слишком сложным решением для восприятия даже по мнению программистов\. 

В итоге мы упростили концепт рассылки до таких сущностей:

1. Дайджест интересных статей — 1 раз в месяц \(смешанный контент\)\.
1. Статья о новом релизе — каждые 2 месяца\.

Можно подписаться на эти опции вместе или раздельно\.

## Свой "велосипед" уже давно на проде

![0979_Mailling_ru/image3.png](https://import.viva64.com/docx/blog/0979_Mailling_ru/image3.png)

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

Мы пишем статьи с комфортом в Word, а собственная программа Publisher делает из документов страницы для сайта в такой последовательности:

|\*\*Этап движения статьи\*\*|\*\*Описание\*\*|
|---|---|
|Автор|Пишет и закладывает статью в репозиторий\\\.|
|SCM|Система контроля версий хранит последнюю версию файла\\\.|
|Local Server|Выкачивает себе все актуальные документы\\\.|
|Publisher|Конвертация Word\\\-файлы в Html страницы\\\.|
|Importer|Загружает файлы на облачный сервер\\\.|
|Site|Публикует статью на сайте в раздел "Блог"\\\.|

Для поддержи рассылок просто расширяем функционал программы Publisher\.

Телом писем для рассылки будет Html\-разметка\. Поэтому мы заказали вёрстку у коллег из web\-команды, взяли готовый класс, который уже реализует конвертацию Word в Html:

```cpp
public class HtmlTransform : WTransform
{
  ....
}
```

и реализовали новый класс рассылки \(сначала релизы\), переопределяя реализацию разных элементов документа:

```cpp
public class ReleaseTransform : HtmlTransform
{
  ....
  public override bool SaveImages() => false;
  
  public override string DocumentStart() => Resource.Release_Start;
  
  public override string DocumentEnd() => Resource.Release_End;
  ....
}
```

Новость о релизе — это фактически та же статья о релизе, но с другими стилями\.

А вот с рассылкой новостей посложнее\. Сначала пришлось запретить многие элементы родительского генератора:

```cpp
public class DigestTransform : HtmlTransform
{
  ....
  public override void TransformHeading3(StringBuilder content,
                                         WHeading header)
  {
    NotSupported("Digest doesn't support Heading 3.");
  }
  
  public override void TransformTable(StringBuilder content,
                                      WTable table)
  {
    NotSupported("Digest doesn't support tables.");
  }
  
  public override void TransformList(StringBuilder content,
                                     List<WListItem> listItems)
  {
    NotSupported("Digest doesn't support lists.");
  }
  ....
}
```

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

## Помогать в реализации рассылок до конца

Как я упоминал ранее, все авторы пишут статьи в Word\. Чтобы упростить автоматическую конвертацию для новостей, мы придумали определённый формат написания текста\.

Вот как выглядит исходник будущего письма из двух новостей:


> Новые публикации в блоге PVS\\\-Studio
> 
> 
> 
> PVS\\\-Studio 7\\\.19: что новенького?
> 
> Дата: 24\\\.06\\\.2022
> 
> Теги: Release
> 
> Пост: https://pvs\\\-studio\\\.com/ru/blog/posts/0958/
> 
> Картинка: https://import\\\.viva64\\\.com/docx/blog/0958\\\_Release\\\_7\\\_19\\\_ru/image1\\\.png
> 
> Недавно вышла новая версия PVS\\\-Studio – 7\\\.19\\\. В этой заметке расскажем, что нового появилось в анализаторе, какие разделы документации мы улучшили, а также о том, что почитать, посмотреть и\\\.\\\.\\\. во что поиграть\\\.
> 
> 
> 
> Игра: найди ошибку в C\\\+\\\+ коде
> 
> Дата: 29\\\.06\\\.2022
> 
> Теги: Cpp
> 
> Пост: https://pvs\\\-studio\\\.com/ru/blog/posts/cpp/0960/
> 
> Картинка: https://import\\\.viva64\\\.com/docx/blog/0960\\\_Game\\\_Cpp\\\_ru/image\\\.png
> 
> Авторы анализатора PVS\\\-Studio предлагают вам проверить свою внимательность и развлечься\\\. Попробуйте быстро отыскать баг в фрагменте исходного кода и ткнуть в него мышкой\\\.

Так как 99 % записей будут состоять из собственных статей, то здесь напрашивалась полная автоматизация\.

Поэтому мы добавили новый функционал в наш плагин для Word:

![0979_Mailling_ru/image4.png](https://import.viva64.com/docx/blog/0979_Mailling_ru/image4.png)

Теперь достаточно нажать на значок с папкой Word, в открывшемся окне выделить нужные документы со статьями, после чего сгенерится новостной текст прямо в открытом документе\. При желании можно дописать новость, не связанную с опубликованной ранее статьёй\. При нажатии на _Digest_ будет создано письмо в Html, которое надо только заложить в систему контроля версий\. Это нужно, чтобы в письме можно было дать ссылку на версию для браузера\.

Для создания письма про релиз достаточно просто открыть статью о нём и нажать _Release_\.

В админке сайта появился планировщик рассылок, в который необходимо добавить полученные Html\-файлы и нажать _Schedule_:

![0979_Mailling_ru/image5.png](https://import.viva64.com/docx/blog/0979_Mailling_ru/image5.png)

## История завершения проекта

![0979_Mailling_ru/image6.png](https://import.viva64.com/docx/blog/0979_Mailling_ru/image6.png)

В октябре 2021 года полностью был готов генератор писем\. А также мы ещё раз переделали верстку, потому что если долго не выпускать проект в свет, то внешние условия меняются без учёта его существования, и приходится догонять разработки коллег из других отделов\.

В феврале 2022 года состоялся релиз нашей новой системы для работы с запросами пользователей, но рассылки не были включены, потому что мы ещё не провели необходимую работу с нашим сайтом\. Поэтому следующим этапом стала разработка функционала подписки/отписки на сайте\.

В июле 2022 года мы возвращаемся к рассылкам \(хотя сайт давно готов\), потому что с момента запуска новой системы в феврале нас накрыло новыми идеями её развития, что стало занимать абсолютно всё время\. Также часть рассылок снова сломалась, т\.к\. на сайте изменились пути к картинкам\. Причина всё та же – пока мы не релизнули этот функционал, другая команда развивала сайт без оглядки на наш незапущенный подпроект\. Вывод: затягивать с релизом очень вредно для разработки\.

В августе 2022 мы снова возвращаемся к рассылкам :D, в этот раз после отпусков, чтобы закончить начатое ровно год назад\.

## Заключение

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

Если вам понравилась идея менять документы через плагин Word \(пишется на C\#\), то рекомендую не торопиться начинать новый такой проект\. Будущее этой технологии туманно\. Microsoft уже объявила о прекращении развития VSTO\-плагинов, заморозив SDK на версии \.NET Framework 4\.8\. Но многочисленное комьюнити продолжает [бороться](https://developercommunity.visualstudio.com/t/Please-port-Visual-Studio-Tools-For-Offi/757925) за развитие своих подобных проектов\. Возможно, мы увидим перерождение этой технологии после открытия исходников, если этого добьются\.

Как вы уже поняли, в PVS\-Studio есть ещё несколько команд разработки, которые занимаются не статическим анализатором кода\. Наша работа состоит в другом – нести автоматизацию во все процессы компании и помогать другим командам быть более заметными для наших клиентов, пользователей и подписчиков\. Поэтому залетайте на долгожданную страницу подписки [здесь](https://pvs-studio.ru/ru/subscribe/), чтобы увидеть результат нашей разработки своими глазами\.