Как делать email-рассылки и не косячить: практические советы
У разработчика, который впервые столкнулся с генерированием электронных писем, практически нет шансов написать приложение, которое будет делать это корректно. Около 40% писем, генерируемых корпоративными приложениями, имеют те или иные нарушения стандартов, и, как следствие, проблемы с доставкой и отображением. На это есть причины: электронная почта технически гораздо сложнее, чем веб, работа почты регулируется несколькими сотнями стандартов и несчетным количеством общепринятых (и не очень) практик, а почтовые клиенты отличаются разнообразием и непредсказуемостью. Тестирование может заметно улучшить ситуацию, но материалов, посвященных тестированию почты, практически нет.
Почта Mail.Ru регулярно взаимодействует со своими пользователями посредством электронных писем. В нашем проекте все компоненты, отвечающие за генерирование писем, и даже единичные рассылки проходят обязательное тестирование. В этой статье мы поделимся своим опытом (и набитыми шишками).
Какие бывают электронные письма
Приложение может генерировать различные виды писем. Их можно классифицировать по нескольким категориям. По способу выбора получателей: триггерные — выборочные — групповые. По назначению: транзакционные — маркетинговые — служебные. К разным типам писем можно предъявлять разные требования и применять разные сценарии тестирования.
Триггерные письма генерируются в ответ на какие-либо события, например, действия пользователя или изменения статуса каких-либо системных объектов. Они генерируются приложением, а потому наиболее интересны в плане тестирования. Триггерные письма могут быть как транзакционными, так и маркетинговыми.
Выборочные письма отправляются в динамическую выборку пользователей, соответствующих каким-либо критериям.
Групповые письма отправляются известной группе получателей, например, всем пользователям или партнерам. Выборочные и групповые письма чаще всего являются маркетинговыми, отправка таких писем инициируется вручную или по расписанию.
Транзакционные письма генерируются в процессе совершения пользователем какого-либо действия. К таким письмам относятся, например, счета, билеты или уведомления о статусе доставки, письма с кодом восстановления доступа и т.д. Транзакционные письма всегда являются триггерными. Для них важна максимальная совместимость, значит, они должны быть максимально просты, а тестировать их необходимо на большом количестве клиентов.
Маркетинговые письма побуждают пользователя совершить какие-либо действия, например, это может быть предложение индивидуальной скидки исходя из предыдущих покупок. В этих письмах могут использоваться транзакционные данные, они могут быть как триггерными, так и массовыми — периодическими или разовыми. Для данных писем важнее эффективность, обычно она определяется результатами сплит-теста. Некоторыми аспектами совместимости можно пожертвовать ради эффективности.
Групповые маркетинговые письма, например, сообщения о сезонных предложениях, акциях и распродажах, часто рассылаются «вручную» и не являются частью вашего приложения, но к ним также можно (и нужно) применять общие принципы тестирования.
Кроме того, могут быть служебные письма, генерируемые для сотрудников, для автоматических или автоматизированных систем CRM, журналирования, аудита или DWH. Такие письма являются триггерными, а это значит, что они также являются частью приложения и должны проходить тестирование.
Кто участвует в процессе тестирования и контроля
- QA-инженер — участвует на всех стадиях процесса.
- Сетевой инженер — отвечает за конфигурацию сетевой инфраструктуры и инфраструктуры доставки сообщений. Сетевого инженера следует привлекать при планировании тестирования инфраструктуры.
- Deliverability-специалист — это человек, следящий за доставляемостью писем, который также участвует в контроле технических и административных параметров всех отправляемых сообщений и следит за ходом процесса рассылки. Он отвечает за то, чтобы отправленные письма дошли до максимально возможного процента пользователей и не попали в спам, а для этого специалист должен обладать определенными знаниями и контактами. При возникновении проблем с доставкой писем именно он должен понять вероятную причину и устранить её: либо устранив технические препятствия; либо что-то поменяв в содержимом писем; либо решив проблему вместе со службой поддержки почтового провайдера, до которого не доходят письма. Такого специалиста (если он есть) также следует привлекать к составлению чеклиста и тестированию инфраструктуры, генерирующего приложения и писем. Однако сам процесс тестирования должен быть под контролем службы QA.
- Email-маркетолог — определяет эффективность маркетинговых рассылок. Под его контролем проходят необходимые для маркетинговых рассылок сплит-тестирования на аудитории. Email-маркетолог также контролирует сегментирование пользовательской базы, состав и частоту отправляемых писем, визуальное «представление» письма для пользователя.
Все эти роли не обязательно выполняет отдельно выделенный сотрудник: роль маркетолога может выполнять кто-то из продуктовых менеджеров, а роль deliverability-специалиста — например, сотрудник поддержки или сетевой инженер. А в стартапах с высокой долей вероятности всем этим придется заниматься одному человеку, и им может оказаться специалист по качеству.
Почтовое сообщение и почтовый транспорт
Структура почты похожа на огромный айсберг, и в ней есть два уровня. Существует более сотни различных стандартов, регулирующих почту, но практически все они относятся к одному из этих двух уровней:
Подводная часть айсберга — это сетевая служба, базовым протоколом которой является прикладной протокол SMTP, определяемый RFC 5321. Он отвечает за доставку писем. Для доставки письма формируется так называемый SMTP-конверт, в который включаются адреса отправителя и получателя уровня SMTP. Также за доставку письма отвечают другие сетевые службы, такие как DNS. Основным компонентом сетевой инфраструктуры является Агент Передачи Сообщений (Mail Transfer Agent, или чаще используется аббревиатура MTA). MTA отвечает за работу с очередью доставки сообщений и сам процесс доставки на серверы получателей. Примеры MTA — Postfix, Sendmail, exim, служба Microsoft SMTP.
Эту подводную часть айсберга, к которой относятся MTA, параметры DNS и прочие сетевые параметры, мы будем называть почтовой инфраструктурой, или инфраструктурой доставки сообщений.
Надводная часть айсберга — это само письмо. Базовая структура письма определяется стандартом RFC 5322. Письмо состоит из служебных заголовков и одной или нескольких частей с данными. В данных может быть текст письма в формате plain text и/или HTML, инлайновые изображения или вложения практически любого типа.
Интерфейс почтовой инфраструктуры и границы тестируемого приложения
У почтовой инфраструктуры, как правило, есть один или несколько интерфейсов, с помощью которых отправляется письмо (попадает в очередь доставки MTA). Например, сервис SMTP Submission, функция mail()
в PHP, передача данных во внешнее приложение mail или sendmail, API внутренних или внешних сервисов (к примеру, GetResponse, SendPulse или Amazon SES). Мы будем считать эти интерфейсы частью инфраструктуры. Достаточно часто бывает ситуация, когда приложение A подготавливает данные для письма и список получателей, а затем передает их в приложение B через его API (для маркетинговых массовых рассылок это может производиться вручную через пользовательский интерфейс — UI), а уже приложение B генерирует почтовое сообщение в формате RFC 5322 и каким-либо образом ставит его в очередь доставки MTA. С точки зрения приложения A (и при его тестировании), приложение B будет частью почтовой инфраструктуры. API или UI приложения B будет для приложения A интерфейсом почтовой инфраструктуры. Хотя с точки зрения приложения B ситуация будет иной, и почтовой инфраструктурой для него будут более низкоуровневые сетевые приложения или протоколы.
Определение тестируемых параметров
При тестировании каждого приложения важно выделить все используемые им почтовые инфраструктуры (их может быть несколько), и для каждой инфраструктуры выделить используемые интерфейсы (их тоже может быть несколько для каждой инфраструктуры). Для каждого интерфейса как можно точнее определяется состав и формат передаваемых в него данных, например: текст письма в TEXT/HTML, текст письма в TEXT/PLAIN, тема письма, имя получателя, адрес получателя, имя отправителя, адрес отправителя письма (RFC5321.From), адрес отправителя SMTP-конвера (RFC5322.mailfrom). Далее разрабатывается набор требований для каждого параметра (представления, кодировки, граничные значения и т.д.), определяются методы контроля каждого из параметров (каким способом можно сравнить фактический результат с ожидаемым).
Типичная структура генерирующего приложения
За генерирование письма и данных в нем, как правило, отвечает тот самый продукт, который мы тестируем. Обычно это серверное (но иногда клиентское) приложение. Оно определяет структуру письма, часть служебных заголовков, форматы инкапсуляции данных, представления строк и кодировки текста. Простым примером такого приложения может послужить скрипт, который формирует письмо и вызывает функцию mail()
.
Основные элементы приложения, которые необходимо контролировать:
- код, отвечающий за генерирование заголовков и/или структуры письма, если структура письма генерируется динамически, и/или статический шаблон письма, описывающий его структуру;
- верстку HTML-части письма (в идеале, это отдельная сущность или часть шаблона/макета письма, но может быть зашита в код приложения);
- подстановку данных приложения в письмо (или в шаблон письма);
- интеграцию приложения с инфраструктурой доставки письма, корректность параметров, передаваемых в интерфейс инфраструктуры.
Что и когда тестировать
Хотим мы этого или нет, но айсберг надо тестировать весь. Можно выделить несколько основных компонентов, требующих тестирования:
1. Инфраструктура доставки
Упор в тестировании следует делать на: доставляемость письма; корректность DNS-записей, включая PTR/FCrDNS, MX- и A-записи; параметры SMTP-протокола (HELO, использование TLS); авторизацию письма (SPF/DKIM/DMARC); адреса SMTP-конверта (если они не управляются приложением); корректность обработки входных параметров интерфейса инфраструктуры; отслеживание, учет и обработку не доставленных писем.
Надо тестировать инфраструктуру при начальном внедрении и каждый раз, когда вносятся изменения в саму инфраструктуру (меняется конфигурация MTA, DNS или сети) или интерфейс отправки письма; используется новый домен, сеть или API; существенно меняются характеристики отправляемых писем, такие как их язык, размер или количество. По опыту, инфраструктура имеет склонность меняться без объявления войны, поэтому базовые тесты следует проводить периодически, даже если нет информации о каких-либо изменениях.
К составлению плана и чек-листов тестирования инфраструктуры можно и нужно привлекать сетевого инженера и deliverability-специалиста.
2. Генерирующее приложение
Следует контролировать адреса SMTP-конверта (если они управляются приложением, т.е. передаются в интерфейс — envelope-from, envelope-to), значения служебных заголовков письма (Date, Message-ID, List-Unsubscribe, Auto-Submitted и т.п.), авторизацию письма (DKIM/DMARC), MIME-кодировки (base64, quoted-printable), общую правильность формата письма, например отсутствие не-ASCII символов в заголовках, состав подставляемых данных, корректность срабатывания триггеров, механизмы отписки, механизмы трекинга письма и сбора статистики (postmaster-заголовки, например, Feedback-ID или X-Mailru-Msgtype, а также трекинговые пиксели).
Тестировать приложение нужно при его разработке, при изменении всех его связанных компонентов, отвечающих за генерирование и хранение данных, при существенных изменениях шаблонов писем, при изменении используемой инфраструктуры или интерфейса к ней, а также в рамках общих регрессов.
3. Структурный и вёрсточный шаблоны письма (могут быть частью генерирующего приложения или разрабатываются отдельно)
Проверяется структура письма (Content-Type, Content-Disposition, вложенность Multipart-частей письма, кодировки текста, строковые параметры), значение целевых и отображаемых заголовков (From, To, Reply-to, Subject), отображение письма в списке писем и при чтении в различных интерфейсах, микроформаты (например, что событие календаря распознается как событие календаря, или авиабилет как авиабилет), брендирование.
Шаблоны писем следует тестировать каждый раз при внесении хотя бы малейших изменений, а также отдельно, например, в ситуации, когда письма попадают в приложение до того, как готова серверная часть.
К составлению чек-листа по тестированию шаблона письма рекомендуется привлечь email-маркетолога и deliverability-специалиста.
Базовые требования при проверке инфраструктуры
IP-адрес, выбранный для почтового сервера, должен быть максимально похож на IP-адрес почтового сервера. Рекомендуется проверить его с помощью утилиты whois. В частности, адрес отправителя не должен принадлежать сети, которая может восприниматься как динамическая; у выбранной сети должны быть действующие контакты, на которые можно отправлять жалобы; сеть обязательно должна быть используемой (иметь статус ASSIGNED в RIPE). IP-адрес должен иметь корректно настроенную PTR-запись. Ее можно настроить самостоятельно через панель управления хостингом, либо с помощью службы поддержки провайдера. PTR-запись должна указывать на реальное имя хоста и при этом быть содержательной, разрешаться обратно в тот же самый IP-адрес (т.н. проверка FCrDNS), не напоминать имя динамического хоста и не включать в себя большую группу цифр или символов. Хороший пример — mailserver.example.com.
У каждого домена, используемого в адресах конверта или заголовках письма, должна быть валидная MX-запись, указывающая на A-запись хоста, который, как минимум, может обрабатывать сообщения о невозможности доставки. Для MX недопустимо напрямую ссылаться на IP-адрес.
Контролируйте прохождение SPF, DKIM, DMARC. SPF позволяет владельцу домена указать в TXT-записи список серверов, имеющих право отправлять email-сообщения с обратными адресами в этом домене. Настраивается она для адреса, используемого в envelope-from (SMTP-конверте), в разделе управления DNS-зонами домена. DKIM обеспечивает проверку авторства сообщения или принадлежности его отправителя определенному домену с помощью технологий цифровой подписи, которая добавляется в само письмо (в его заголовок DKIM-Signature). Обычно DKIM-подпись настраивается на уровне MTA (инфраструктуры). DMARC задает политику проверки приходящей почты в определенном домене и действия над письмами, не проходящими аутентификацию SPF или DKIM. При попытке нарушения этой политики приходит структурированный отчет со сведениями о такой попытке. DMARC, также как и SPF, публикуется в виде TXT-записи в доменной зоне.
Проверьте доставляемость писем до основных почтовых служб — для России Mail.Ru, Yandex, GMail, Microsoft (Hotmail / Outlook.com / Office365), Rambler, nic.ru. В пришедших письмах нужно проконтролировать правильность HELO; наличие и прохождение проверок PTR/FCrDNS, SPF, DKIM и DMARC; валидность заголовков и данных в них, в частности, синхронность часов в датах и правильность временных зон.
На формирование некоторых параметров, например, авторизацию, доставляемость и попадание в спам интегрально влияют все компоненты, однако для их контроля обычно есть отдельные оперативные инструменты — DMARC и FBL-отчеты, API сервисов postmaster, инструменты трекинга писем, статистика доставки. Тестирование должно учитывать уровень внедрения инструментария оперативного мониторинга в компании — например, при отсутствии оперативного контроля DMARC-отчетов следует регулярно тестировать авторизацию писем, при отсутствии оперативного контроля доставляемости — регулярно проверять, как и куда попадают письма, даже если никакой разработки, связанной с отправкой писем, не ведется.
Для проверки инфраструктуры можно использовать специализированные сервисы, например, mail-tester.com, mxtoolbox.com.
Требования к авторизации
Проверить прохождение SPF, DKIM, DMARC обычно можно по заголовку Authentication-Results на сервере получателя.
Проверьте валидность SPF-записи на предмет синтаксиса, лимита на DNS-запросы (например, с помощью mxtoolbox.com). При формировании SPF должны быть учтены все источники рассылок (не забудьте CRM-системы, все используемые инфраструктуры доставки, в том числе те, через которые проводятся разовые маркетинговые кампании). Рекомендуется задавать разрешенные серверы для домена через список сетей («ip4» / «ip6»). SPF проверяется для адреса отправителя из SMTP-конверта. Проверьте, что домен SMTP-конверта (envelope-from) соответствует домену из заголовка From. Типичные ошибки, связанные с SPF, перечислены в этой статье:
https://habr.com/company/mailru/blog/338700/.
Проверьте DNS-запись DKIM, валидность и состав DKIM-подписи (DKIM-Signature). Проверьте, что используется DKIM-ключ размером не менее 1024 бит. Рекомендуемый режим хэширования DKIM-подписи: relaxed/relaxed. Убедитесь, что подписаны все важные заголовки (From, To, Subject, Date, Message-ID, MIME-Version, Content-Type), не подписаны трекинговые заголовки (Received, Delivered-To, Return-Path), и DKIM проходит валидацию на основных почтовых службах. Настройте на одной из почтовых служб переадресацию на другую, DKIM не должен «биться» на переадресованных письмах. Убедитесь, что домен DKIM-подписи соответствует домену отправителя из заголовка From.
Проверьте прохождение DMARC на основных почтовых службах. Проверьте получение DMARC-отчетов, идентифицируйте и устраните проблемы с прохождением SPF и DKIM для всех IP-адресов вашей инфраструктуры.
Проверьте, что письма доставляются на внешние серверы с использованием шифрования (TLS). Проверить наличие TLS иногда можно по заголовку Received на сервере получателя: например, указание протокола ESMTPS или наличие параметров вида (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); указывает на наличие TLS.
Проверка генерирующего приложения
Требования к почтовым адресам
Адреса конверта
Проверку генерирующего приложения начнем с адресов в SMTP-конверте.
Адреса конверта — это адреса уровня почтовой инфраструктуры. Они не видны пользователю, но важны для доставки, потому что в какой ящик попадёт письмо, определяется именно адресом конверта.
Адрес получателя в конверте (envelope-to, он же RCPT TO:) — это адрес, на который будет реально доставлено письмо.
- для всех писем, кроме регистрационных, адрес должен быть легально подписан и валидирован на рассылку в соответствии с административными требованиями.
- для рассылок адрес должен быть «живой», адреса, на которые регулярно не получается доставить письма, должны помечаться как неактивные, рассылки по ним не должны производиться. Но некоторые категории писем (например, восстановление доступа) возможно, следует отправлять и на адреса, ранее помеченные как неактивные.
Адрес отправителя в SMTP-конверте (обычно называется envelope-from, smtp.mailfrom или Return-Path) — на этот адрес будут доставляться сообщения о невозможности доставить письмо и автоответы. Пользователю этот адрес невидим. Также этот адрес используется для авторизации SPF. Проверяем, что:
- адрес доступен;
- не является адресом сотрудника и не перенаправляется в него, чтобы исключить автоответы, сообщения о недоступности и т.п.;
- обрабатывается скриптом, который будет помечать адреса недоступных пользователей как неактивные;
- адрес может быть автоматически генерируемым, т.е. уникальным для каждого письма;
- письмо на этот адрес не должно приводить к генерированию какого-либо ответного письма, например, сообщения о переполнении ящика.
Адреса заголовков письма
Эти адреса либо непосредственно видны пользователю, либо используются при ответе на письмо.
Адрес отправителя (заголовок From:) — это адрес и имя отправителя, отображаемые в списке писем и при чтении письма. Проверяем, что:
- Это «человекочитаемый» понятный адрес, идентифицирующий компанию.
- Содержит не только e-mail, но и имя отправителя.
- noreply@ возможен, но только если мы хотим подчеркнуть, что не рассчитываем получить ответ на письмо и он не будет читаться. Лучше продублировать эту мысль в тексте письма.
- При наличии не-ASCII символов (например, кириллицы) имя отправителя должно быть закодировано в соответствии с MIME, домен при наличии не-ASCII символов должен быть закодирован в Punycode.
- У писем одной категории адрес должен быть одинаков, не допускается использование автогенерируемых адресов. Это связано с тем, что From: чаще всего используется людьми для сортировки писем по папкам с помощью фильтров.
- Адрес должен быть разным (лучше в разных поддоменах) у транзакционных, маркетинговых и неотложных писем (таких как письма от службы поддержки). Это также связано с тем, что пользователь может пометить маркетинговые письма как спам или отфильтровать их в не читаемую папку.
- Адрес From и адрес SMTP-конверта должны находиться в одном домене или в поддоменах одного организационного домена для прохождения SPF в рамках DMARC.
- Адрес должен быть из домена организации. Недопустимо использовать во From домены бесплатных почтовых сервисов и других публичных почт, поскольку подобные рассылки не пройдут аутентификации SPF и DKIM в рамках DMARC.
Адрес Reply-To — на этот адрес будут отправляться «ручные» ответы при ответе пользователя на письмо. Он не является обязательным: при его отсутствии для ответа используется адрес из From. Проверяем, что Reply-To:
- Может быть автогенерируемым, т.е. уникальным для письма (позволяет узнать, на какое письмо пришел ответ).
- Не должен попадать в ящик сотрудника, чтобы избежать автоответов, а в идеале должен быть «завернут» в CRM.
- Может генерировать стандартный автоответ CRM, но не должен генерировать ничего лишнего, например, сообщений о переполнении ящика. При генерировании автоответов должны быть предприняты меры для исключения зацикливаний, они перечислены в стандарте RFC 3834.
- Может быть из любого домена, не обязательно совпадающего с From, однако иногда это пугает пользователей при ответе.
- Может отсутствовать, тогда его функции выполняет адрес From.
- Помимо адреса указано имя отправителя.
Адрес To:
- Должен содержать e-mail получателя (иначе это пугает получателя письма и настораживает антиспам).
- В идеале, должен содержать имя получателя. Но если имя неизвестно или сомнительно (например, адрес еще не подтвержден), лучше его не указывать (кто-то может ввести чужой адрес с плохим именем, а получатель может на вас обидеться).
Требования к заголовкам писем
Реальная кодировка текста должна совпадать с указанной в заголовке. Желательно использовать одну кодировку во всех заголовках и частях письма. Рекомендуется использовать UTF-8 как широко поддерживаемую. Кодировка указывается в заголовках Content-Type и в теге HTML-части.
Заголовки From:, Message-ID: и Date: должны формироваться непосредственно в скрипте отправки письма (а по стандартам — вместе с текстом письма) и обязательно в правильном формате. В случае их отсутствия или некорректности формирования, эти заголовки может добавить один из транзитных серверов, что приводит к нарушению целостности DKIM-сигнатуры.
8-битные символы в заголовках, включая тему письма (Subject) и имена вложенных файлов (Content-Type и Content-Disposition), должны отсутствовать; все символы, отличные от ASCII, в том числе кириллица, должны быть закодированы в quoted-printable или base64.
Требования к структуре письма
Для HTML-части письма желательно формировать альтернативную — текстовую (plain) часть. Также необходимо проверять соответствие и читаемость plain text-части письма (при её наличии) и общую структуру письма.
По стандарту RFC 5322, длина строки в письме не должна превышать 998 8-битных символов. Следует учитывать что в UTF-8 символ может занимать несколько октетов. Терминатором строк в электронной почте выступает пара CRLF (<сr> ascii 13, lf> ascii 10), занимающая 2 октета. Нужно проверять корректность терминатора строк, так как письма часто посылают с помощью Unix-скрипта, а в Unix терминатором строк служит один символ lf — для электронной почты это ошибка. Также следует проверять, не разбивают ли терминаторы строк символы в кодировке UTF-8: нельзя допускать наличие терминатора строк между двумя октетами одного символа, например, кириллического. Во избежание таких ситуаций необходимо разбивать текст до формирования письма, либо кодировать текст в base64.
Необходимо проверить правильность разметки аттачей и инлайнов — то есть корректность формирования заголовков «Content-Disposition: inline», если это картинка, отображаемая внутри письма, либо «Content-Disposition: attachment», если файл предназначен для скачивания.
Структура письма, по возможности, должна быть максимально простой: в частности, не должно встречаться больше одной multipart-части каждого типа (mixed, alternative, related), причем multipart/mixed используется только если письмо содержит вложенные файлы, multipart/related — при наличии инлайновых изображений, multipart/alternative — при наличии plain text- и HTML-частей. В общем виде структура письма, при отсутствии в нем аттачей и инлайн-картинок, должна выглядеть следующим образом:
multipart/alternative
— text/plain
— text/html
Порядок частей важен, text/plain должен идти ДО text/html или multipart/related. Это нужно для того, чтобы по умолчанию показывалась HTML-часть, и только если её отображение по каким-то причинам недоступно — отображалась plain-часть.
При наличии в письме инлайн-картинок его структура должна выглядеть следующим образом:
multipart/alternative
— text/plain
— multipart/related
—— text/html
—— image/… (инлайн-картинка)
—— image/… (инлайн-картинка)
Инлайн-картинки должны иметь Content-Disposition: inline и находиться строго внутри multipart/related-части.
В самом сложном случае, когда имеются и инлайновые изображения, и вложенные файлы, письмо имеет следующую структуру:
multipart/mixed
— multipart/alternative
—— text/plain
—— multipart/related
——— text/html
——— image/png
——— image/png
…
— application/octet-string (content-disposition: attachment)
— application/octet-string (content-disposition: attachment)
…
(multipart/related- и multipart/alternative-части должны быть закрыты до аттачей, аттачи относятся к внешней multipart/mixed-части)
Требования к URI
Любые URI (в атрибутах src, href, стилях и т.п.) должны содержать протокол и имя хоста (https://example.com/somepath). Типичными ошибками является использование относительных ссылок (/somepath) и отсутствие протокола (//example.com/somepath), что недопустимо для писем, т.к. в них протоколом по умолчанию может быть file://.
- Любые служебные и неASCII-символы (в частности, кириллица) в URI обязательно должны быть закодированы с помощью percent encoding.
- Ссылка, вставленная как текст (т.е. видимая пользователю как URL, а не как фрагмент текста), всё равно должна быть размечена через тег <а>, иначе пользователь не сможет по ней перейти по клику. Некоторые веб-почты размечают такие ссылки самостоятельно, но это не является стандартным поведением. Адрес href внутри A в таком случае должен совпадать с текстом ссылки, иначе контент-фильтр может среагировать на такую ссылку как на попытку обмануть пользователя. На это особенно следует обращать внимание при наличии «кликеров», отслеживающих переходы пользователя из письма.
- Лучше ограничиться использованием протоколов httр://, httрs:// и mаilto:.
- При высоких требованиях к безопасности следует полностью отказаться от использования http:// в пользу httрs://.
- Не должны использоваться нестандартные порты (например, example.com:8080/somepath), т.к. они могут быть недоступны пользователю.
- Переход по ссылке внутри HTML-части не должен приводить к каким-либо изменениям состояния приложения (подписке, отписке, отмене заказа и т.п.) без дополнительного подтверждения пользователем на странице, т.к. некоторые системы контент-фильтрации могут самостоятельно проверять безопасность такого перехода, запрашивая страницу по ссылке; почтовое приложение может показывать превью страницы по ссылке при наведении мыши, а современные браузеры могут подгружать страницу до того, как пользователь щелкнул по ссылке, чтобы сократить время загрузки (в веб-приложении вообще не рекомендуется делать любые модифицирующие действия по GET-запросу, все модифицирующие запросы должны идти через POST или PUT).
- Переход по ссылке в заголовке List-Unsubscribe, наоборот, не должен требовать от пользователя каких-либо дополнительных действий, т.к. за пользователя отписку по этому заголовку обычно делает почтовая программа.
- Не стоит ожидать от пользователя, что он читает письмо и переходит по ссылке в том же браузере, в котором инициирует действие, приводящее к отправке письма (например, регистрирует учетную запись). Ссылка должна работать в любом другом браузере или на мобильном устройстве. В частности, пользователь может открыть ссылку, будучи не авторизованным, или авторизованным в аккаунте, отличном от того, на который было отправлено письмо.
- Т.к. длина URI может быть ограничена, не стоит для крупных объектов использовать URI типа data:. По той же причине не стоит использовать в ссылках слишком длинные URI.
- Нельзя использовать внешние сокращатели ссылок, это негативно влияет на доставляемость писем. Лучше, если все ссылки будут указывать на ваш домен, это сократит потенциальное негативное влияние чужой репутации на доставляемость писем.
- Не стоит располагать внешние картинки на каких-то публичных сервисах или бесплатных хостингах.
Требования к верстке письма
Почему верстать письма так сложно?
Почтовые клиенты так или иначе показывают пользовательский контент в рамках своего интерфейса. Потенциально это может приводить к различным проблемам безопасности — межсайтовому скриптингу (XSS, Crossite scripting), подмене интерфейса (interface spoofing), DOM clobbering, деанонимизации пользователя / утечке информации (например, IP-адреса пользователя или куки через внешние запросы) и т.д., поэтому любой почтовый сервис и почтовое приложение имеет ту или иную степень защиты от каждого класса атак. К сожалению, нет единого подхода к организации этой защиты. Она может быть организована через:
- изолированные ограниченные фреймы,
- фильтрацию тегов и/или атрибутов,
- ограничения на абсолютное позиционирование,
- запрет или ограничение на использование блочных стилей (что критично для адаптивной верстки),
- запрет на внешние элементы по умолчанию (т.е. загрузка внешних изображений требует разрешения пользователя) или использование прокси для доступа к ним,
- конвертацию HTML-писем в другой промежуточный формат (например Microsoft Exchange / Outlook используют RTF, из-за чего добиться адекватного отображения элементов в Outlook обычными методами может быть чрезвычайно сложно),
- запрет или ограничение на использование форм или их отдельных элементов.
Также в письмах используются специфические элементы, такие как инлайн-изображения и URI cid://, поддержка которых может быть ограничена. Например, Mozilla Thunderbird не поддерживает cid:// для фоновых изображений.
Даже корректно сформированное письмо может по-разному отображаться в разных интерфейсах из-за особенностей их реализации и фильтрации содержимого письма.
При наличии ошибок в формате письма поведение становится полностью непредсказуемым. Например, в почтовых клиентах может быть разное поведение при неправильных URI, по-разному обрабатывается некорректное форматирование заголовков, по-разному работает автоопределение кодировки, если она не указана или указана неверно. Поэтому письмо надо обязательно посмотреть в разных интерфейсах: корректное отображение письма в одном интерфейсе не говорит о том, что оно составлено правильно (на самом деле, даже корректное отображение письма во всех интерфейсах не гарантирует отсутствие проблем с отображением в будущем).
Необходимо обратить внимание на следующие моменты:
- Проверить текст письма на смысловое содержание, отображение, отсутствие опечаток, синтаксических, орфографических и лексических ошибок.
- Проверить корректность подстановки данных приложения в шаблон или макет письма.
- Проверить корректность сумм, дат, чисел, позиций товара и другой информации с учетом допустимых граничных условий. В датах должен присутствовать год (некоторые пользователи заходят в ящик очень редко). Во времени должна присутствовать временная зона. В адресе должен присутствовать город, а в некоторых случаях необходимо указывать и страну.
- Проверить рабочее состояние всех ссылок в письме, если таковые имеются.
- В письмах, отправленных до подтверждения адреса, в т.ч. письмах со ссылкой-подтверждением, не должно присутствовать какого-либо текста, контролируемого cнаружи, даже имени пользователя, иначе они могут быть использованы для спама (в поле, отображаемое в письме, например, в имя, вставляется спам-текст и в качестве адреса указывается адрес жертвы). Например, если вы можете от имени вашего сервиса отправить нецензурный текст на адрес разработчика, то налицо наличие проблемы.
- Проверить отсутствие внешних картинок на сторонних сервисах.
- Проверить наличие счетчиков отправки, доставки, прочтения письма, переходов. Некоторые из них находятся в самом письме (например, счетчик-пиксель прочтения письма), некоторые отслеживаются рассыльщиком, но, как правило, все доступны в админке рассыльщика.
- Проверить правильность категории подп