2018-09-15

О почте

Бывает так.
Где-то на выделенном сервере работает тщательно настроенный Postfix. Через него ваше приложение, запущенное на этом же сервере, отправляет письма.
И SPF запись настроена. Она говорит, что с IP адреса нашего сервера действительно разрешается отправлять письма от нашего домена.
$ dig +noall +question +answer txt example.ru
;example.ru.              IN      TXT
example.ru.       28800   IN      TXT     "v=spf1 +a +mx include:_spf.yandex.net ~all"
И DKIM настроен. Письма подписываются, а ключ для проверки подписи тоже лежит в DNS.
$ dig +noall +question +answer txt mail._domainkey.example.ru
;mail._domainkey.example.ru. IN   TXT
mail._domainkey.example.ru. 28800 IN TXT  "v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTFcJLY5SlBNwtTqCHx5VHZZBnap4Z75T9Jb6g/JpNcwu3sMdBPmt8zQsxNflBXmovlBzowa4rAwu0MCk1HgZHt+5Ohm+qRscXTrP19XAcV+DA6ZVXekRNwoY7K+jwn3VJaUpEn3BK171M3gUPQ1G4sRDwh0A+S5ZEetH7V3SjmwIDAQAB;"
И даже все предыдущие письма, которые мы сами себе отправляли в Gmail, содержат заголовки, подтверждающие, что все проверки проходят успешно.
Authentication-Results: mx.google.com;
 dkim=pass [email protected];
 spf=pass (google.com: domain of [email protected] designates 1.2.3.4 as permitted sender)
 [email protected]
Но вот в один прекрасный день мы видим в логах Postfix вот такое:
421-4.7.0 Our system has detected an unusual rate of unsolicited mail originating from your IP address. To protect our users from spam, mail sent from your IP address has been temporarily rate limited. Please visit https://support.google.com/mail/?p=UnsolicitedRateLimitError to review our Bulk Email Senders Guidelines. gsmtp (in reply to end of DATA command)
Google отказывается (временно) принимать письма, адресованные пользователям Gmail, когда они отправляются с нашего сервера.
Ну да, мы слали подтверждения регистрации. Да, это очень похожие письма. Да, это были десятки похожих писем. Но отправлялись они не все скопом, а по мере регистрации пользователей.
Что мы можем сделать ещё, чтобы удовлетворить Google? Давайте внимательно почитаем, что нам предлагают по указанной ссылке.
Gmail
Читаем внимательно, обращая внимание на каждый пункт.
Используйте Postmaster Tools.
Теоретически, Postmaster Tools — это такая веб консолька, где вы видите статистику получения почты Гуглом из вашего домена, и можете увидеть истинную причину ошибки. На практике я им не пользовался. Потому что там было пусто. Видимо, сильно мало писем мы рассылаем, чтобы там была хоть какая-то статистика.
Всегда отправляйте письма определенной категории с одного адреса.
Ну как бы у нас одна категория: письма подтверждения регистрации. И отправляются с одного адреса.
Не смешивайте разнотипный контент в одном сообщении.
Не такие уж и большие у нас письма, чтобы там появилось более одного типа контента.
Отправляйте сообщения с одного IP-адреса.
Сервер у нас один, так что IP адрес тоже один.
Убедитесь, что для ваших IP-адресов существуют действительные обратные записи DNS, указывающие на ваш домен.
Уже теплее.
DNS, как вы знаете, предназначен для преобразования символических (доменных) имён, типа "gmail.com", в IP адреса, типа "216.58.207.37" или "2a00:1450:4001:821::2005".
$ dig +noall +question +answer a gmail.com
;gmail.com.                     IN      A
gmail.com.              260     IN      A       216.58.207.37
$ dig +noall +question +answer aaaa gmail.com
;gmail.com.                     IN      AAAA
gmail.com.              55      IN      AAAA    2a00:1450:4001:821::2005
Но существует и обратное преобразование. IP адресу может быть сопоставлено некоторое каноничное доменное имя.
$ dig +noall +question +answer -x 216.58.207.37
;37.207.58.216.in-addr.arpa.    IN      PTR
37.207.58.216.in-addr.arpa. 86378 IN    PTR     fra16s24-in-f5.1e100.net.
$ dig +noall +question +answer -x 2a00:1450:4001:821::2005
;5.0.0.2.0.0.0.0.0.0.0.0.0.0.0.0.1.2.8.0.1.0.0.4.0.5.4.1.0.0.a.2.ip6.arpa. IN PTR
5.0.0.2.0.0.0.0.0.0.0.0.0.0.0.0.1.2.8.0.1.0.0.4.0.5.4.1.0.0.a.2.ip6.arpa. 86400 IN PTR fra16s20-in-x05.1e100.net.
Как видите, это DNS записи типа PTR в поддоменах in-addr.arpa. и ip6.arpa.. Из IP адреса там формируется доменное имя задом напёред.
Если что, домен 1e100.net, принадлежит Гуглу.
От нас требуется, чтобы обратная зона IP адреса нашего сервера, во-первых, существовала, и во-вторых, соответствовала нашему домену, с которого мы отправляем почту.
Обратная зона неразрывно связана с IP адресом. А значит, изменить её можно там, где вам выдали IP адрес. То есть, у хостера. Ищите где-нибудь в панельке управления сервером, где поменять обратную зону.
Reverse DNS settings
Раньше бывали почтовые сервера, которые не принимали письма с IP адресов, если обратная зона не соответствовала домену отправителя. Подобную проверку и сейчас можно включить в Postfix. Google, вроде, не настолько жесток. Но вполне очевидно, что правильная обратная зона улучшает репутацию сервера. Ведь наличие обратной зоны говорит о том, что это не какой-то домашний сервер с динамическим IP адресом, а честный оплаченный хост у приличного хостера.
Reverse DNS Check
Используйте во всех письмах массовой рассылки один и тот же адрес в поле "От:".
Ну мы так и делаем.
Подписывайте сообщения ключом DKIM. Gmail принимает ключи длиной не менее 1024 бит.
Это мы тщательно настроили в прошлый раз.
Опубликуйте запись SPF.
Есть такая запись.
Опубликуйте политику DMARC.
А вот это мы поленились сделать. Кажется, пришла пора каждому приличному почтовому домену, помимо SPF и DKIM, иметь ещё и DMARC.
В простейшем случае хватит и такого:
$ dig +noall +question +answer txt _dmarc.example.ru
;_dmarc.example.ru.       IN      TXT
_dmarc.example.ru. 28800  IN      TXT     "v=DMARC1;p=none"
Мол, про DMARC мы знаем, вот вам эта грешная политика, но ничего специального не хотим, отвалите. Главное, чтобы нужная TXT запись была.
Если вы уверены, что SPF и DKIM работают правильно, и хотите получать хоть какие-то сведения о том, кто шлёт почту от вашего домена, имеет смысл усложнить до "v=DMARC1;p=reject;pct=100;rua=mailto:[email protected]". Тут, во-первых, письма с неправильным SPF или DKIM будут отбрасываться, а во-вторых, сводная статистика по письмам с вашего домена будет присылаться на указанный емейл. Там приходят зазипованные XML, которые имеет смысл автоматически парсить и где-то диаграммки рисовать. В принципе, это всё уже автоматизировано.
DKIM, SPF, DMARC
У IP-адреса отправителя должна быть запись PTR для выполнения обратного запроса DNS. Необходимо, чтобы он совпадал с IP-адресом, который получен путем прямого преобразования доменного имени, указанного в записи PTR.
Ага. Значит, нужно пойти чуть глубже, чтобы доменное имя обратной зоны IP адреса нашего сервера резолвилось в тот же IP адрес.
$ dig +noall +question +answer a gmail.com
;gmail.com.                     IN      A
gmail.com.              147     IN      A       216.58.207.69
$ dig +noall +question +answer -x 216.58.207.69
;69.207.58.216.in-addr.arpa.    IN      PTR
69.207.58.216.in-addr.arpa. 82607 IN    PTR     fra16s25-in-f5.1e100.net.
$ dig +noall +question +answer fra16s25-in-f5.1e100.net.
;fra16s25-in-f5.1e100.net.      IN      A
fra16s25-in-f5.1e100.net. 86400 IN      A       216.58.207.69
Это требование слабее предыдущего упоминания обратной зоны. Приличные провайдеры заводят домен и обратную зону даже для динамических IP адресов.
$ dig +noall +question +answer -x 188.232.179.78
;78.179.232.188.in-addr.arpa.   IN      PTR
78.179.232.188.in-addr.arpa. 2572 IN    PTR     dynamicip-188-232-179-78.pppoe.omsk.ertelecom.ru.
$ dig +noall +question +answer dynamicip-188-232-179-78.pppoe.omsk.ertelecom.ru
;dynamicip-188-232-179-78.pppoe.omsk.ertelecom.ru. IN A
Упс. Или нет.
Reverse DNS
Домен отправителя должен пройти проверку SPF или DKIM.
Да. Уже да.
Чтобы получатель мог быстро отказаться от подписки, не покидая Gmail, мы настоятельно рекомендуем добавить заголовок List-Unsubscribe.
Упоминаются два RFC. RFC 2369 описывает List-* заголовки писем, в частности, заголовок List-Unsubscribe. RFC 8058 описывает заголовок List-Unsubscribe-Post.
Теперь понятно, как работают эти ссылки "отписаться" в Gmail. Если вы делаете рассылки, то включите эти заголовки в ваши письма, и Google будет лучше их воспринимать. А у пользователей будет возможность быстро отписаться от рассылки. Вам будет приходить HTTP POST запрос.
List-Unsubscribe: <https://example.com/unsubscribe.html/opaque123456789>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
Но вообще-то у нас не рассылки, а уведомления.
List-Unsubsribe
С помощью поля заголовка "Precedence: bulk" обозначена массовая рассылка.
Precedence — это нестандартный заголовок. Он пару раз упоминался в довольно старых RFC как выходящий из употребления, и в основном использовался для предотвращения зацикливания автоматических ответов в списках рассылки. А вот эта вот рекомендация использовать Precedence: bulk — уникальная для современного Gmail.
Чёрт его знает, как Gmail обрабатывает этот заголовок. Но, вероятно, если вы рассылаете много похожих писем, стоит этот заголовок выставить. Не жалко.
No Spam
Итак. Чтобы уменьшить вероятность проблем с Gmail (и другими получателями), нужно:
  • Иметь валидную SPF запись в домене.
  • Настроить и использовать DKIM.
  • Иметь хоть какую-нибудь политику DMARC для домена.
  • Определить обратную зону для IP вашего сервера. Убедиться, что домен обратной зоны снова резолвится в IP сервера.
  • Если вы действительно делаете рассылку, добавить заголовки List-Unsubscribe и List-Unsubscribe-Post. Дайте пользователю возможность быстро отписаться.
  • Если вы рассылаете много похожих писем, добавить заголовок Precedence: bulk.
  • Следить за заголовками From, To, Return-Path, Reply-To. Они должны отражать действительность.
  • Следить за телом сообщений, не забывайте включать текстовую версию, помимо HTML.
  • Быть честными с пользователями, пишите в письмах только то, что нужно, не надо рекламы.
Успехов.

2018-09-02

О Сочи

Сочи — это не город. Это — сборище санаториев, профилакториев, лечебных учереждений, дач, бывших дач, экспроприированных и превращённых в парки, посёлков, отелей, посёлков из отелей, горных черкесских аулов, пасек и виноградников, а также немного заказников, зажатые между Северо-Западным Кавказом и Чёрным морем узкой полоской от границы с Абхазией и на 120 километров на северо-запад.
Самая юго-восточная часть всего этого называется Адлер. Именно тут находится аэропорт. Именно тут построены те самые стадионы, которые вы видели по телевизору на трансляции Зимней Олимпиады 2014. Олимпиада принесла сюда ровные дороги, многоуровневые развязки и два модерновых железнодорожных вокзала. Плюс навороченная горнолыжная инфраструктура где-то в горах, где я не был.
Говорят, после Олимпиады Сочи стал круглогодичным курортом. Летом сюда едут на море. Зимой сюда едут в горы.
Далее на северо-запад у нас находятся: Хоста (Хостинский район), собственно Сочи (Центральный район)... Ну и считается, что Большой Сочи простирается куда-то до посёлка Лазаревка (Лазаревский район) и немного дальше.
Карта Большого Сочи
Из Адлера в Сочи идёт прямая автомобильная дорога: улица Ленина, тихо и незаметно переходящая в Курортный проспект. Это — единственная прямая дорога в Сочи. Далее на север — только горные серпантины. Вправо-вверх, влево-вверх, вправо-вверх, влево-вверх,... перевал, вправо-вниз, влево-вниз...
Автомобильное движение тут адовое. Я очень обрадовался, что оказался тут без авто. В движении на горных дорогах есть куча неявных нюансов. Тормозить двигателем на спуске. Пропускать фуры и автобусы на поворотах. Они не влезают по ширине и в повороте им нужны обе полосы, включая встречную. И их пропускают, и встречные, и попутные. Никаких обгонов. Зато автобус периодически пропускает скопившиеся за ним легковушки там, где дорога слегка расширяется.
Вдоль всего побережья проходит ещё и железная дорога. В единственном ровном месте, где её можно проложить. То есть по самой границе пляжа. Поэтому шутка Михаила Задорнова про железную дорогу на пляже — вовсе не шутка. Отдыхающим в большинстве санаториев придётся перебираться через автомобильную и железную дороги по подземным переходам, чтобы попасть на пляж. Единственное место, где железная дорога отходит от моря вглубь — это Адлер, тот самый его район, где стоят олимпийские стадионы, и Имеретинский район чуть южнее. Поэтому именно туда мы рванули, чтобы к морю.
Улица Ленина на Google Street View
Море есть. Море тёплое. В конце августа вода была +28°C. А пляж — галечный. Песка нет. Есть камни. Круглые, овальные... На них можно лежать. Но ходить лучше только в тапочках.
Эти камни тут везде. Ими прижимают листочки с рекламами туристических туров в киосках на каждом углу. Ими придавливают основания зонтиков от солнца, чтобы устойчивей стояли. Тащить с черноморского побережья красивые круглые камушки — бессмысленно. Ибо их тут — килотонны.
Камни берутся из гор. Тут нет этой чёрной мясистой почвы. Тут нет грязи. Тут, если голая земля — то это камни. Понятно, как тут растут сосны. Не очень понятно, как тут растёт всё остальное, включая настоящие пальмы и настоящий бамбук. Зато совсем-совсем нет пыли, которая в Сибири через два дня появляется на подоконниках при открытом окне и скапливается на балконах.
Земля в Сочи
По деньгам слетать в Сочи выйдет столько же, что слетать куда-нибудь в Европу. С пересадкой в Москве, естественно.
С жильём вариантов чудовищно много. Но меньшинство из них представлено на booking.com. Только ленивый не сдаёт квартиры или комнаты для туристов. В Адлере целые кварталы застроены двухэтажными домиками для туристов. Или пятиэтажными небольшими отелями с рестораном на первом этаже. Цены на жильё могут различаться в десятки раз, ведь тут есть и несколько штук Radisson. Но, в общем-то, гостиница уровня европейского Ibis, и стоить будет соответствующе.
Нам с жильём не повезло лишь по одному пункту. На первом этаже отеля оказался ресторан. И не просто ресторан, а ресторан со столиками на улице, где вечерами громко поют. А в соседнем отеле — тоже ресторан, где вечерами тоже поют. И они друг с другом соревнуются, кто поёт громче. И окна номера как раз выходят на них обоих (и на море, эх). Заснуть можно только плотно закрыв все окна. Хорошо, что эти ребята стабильно затыкались где-то за полчаса до полуночи.
Еда — очень дешёвая. Я ожидал, что будет дороже, как в Москве. Но нет, оказалось так же дёшево, как в Омске. Это если не ходить по барам и ресторанам, а питаться в столовках, которых на побережье южнее Олимпийского парка едва ли не больше, чем баров. За 300-700 рублей вполне можно пообедать втроём (два взрослых + ребёнок). Ну и ясен пень, всюду просто на улице — шашлыки и люля-кебаб. Впрочем, индейки тут нет, не выращивают.
Развлечения стоят по-разному. Но обычно в два-три раза дешевле, чем что-нибудь аналогичное в Европе.
На пляж вход свободный и бесплатный. За лежак, или зонтик, или качели-лежанки — почасовая оплата. За разные водные покатушки — плата отдельно.
Солнце встаёт из-за гор в шесть утра. Солнце садится в море в семь вечера. Пешеходная набережная с велодорожкой. Продают всякую детскую пластиковую фигню. Катят на велосипедах, самокатах, электросамокатах, трехколёсных велосипедах с электроприводом, рикшах, чёрт знает на чём. Художники рисуют. Гитаристы поют. Какие-то ребята каждый вечер играли дуэтом на гитаре и скрипке. Молодцы!
Вид с балкона отеля
Сходили разок с ребёнком в Сочи Парк. Впервые попал в парк развлечений, где плата за вход. Нехилая плата: больше полутора тысяч. Но не пожалел. Потом можно развлекаться целый день. На всех аттракционах. Без дополнительной платы. Там шикарные американские горки. С не менее шикарной длиннющей очередью на вход, но организованной а-ля-аэропорт накопителями зигзагом. А на цепочную карусель меня не пустили, потому что там ограничение на массу в 75 кг на посетителя.
Но аттракционы там — не самое интересное. Есть шоу. Научные, развлекательные, цирковые. Надо только заранее узнать, когда и где они будут проходить. Есть площадки под открытым небом. Просто лазалки. Прыгалки с музыкальными инструментами. Мини-лабиринты с кривыми зеркалами. Большая площадка с водой, насосами, брызгалками, водяными колёсами и прочей прелестью. На этих площадках, даже безо всяких аттракционов, ребёнок может спокойно провести полдня.
Позднее выяснилось, что в Москве, в Парке Горького, тоже есть подобные площадки, даже круче. С совершенно свободным доступом, и, соответственно, толпами орущих ребятишек. Москвичи и гости столицы, или просто, у кого есть полдня до вечернего самолёта, имейте в виду.
Лазалки в Сочи Парке
Разок выбрались в центр Сочи. Познакомились с общественным транспортом. Всё плохо.
Есть электрички. Но станции идут километров через пять. Это вам не метро. До ближайшего вокзала может понадобиться пройти несколько километров. Далековато.
Есть автобусы. Цена — нормальная. По району — 22 рубля. Между районами (из Адлера в Сочи) — в четыре раза дороже. Платить водителю на входе через переднюю дверь. Кондиционеры — есть. Расписание — тоже есть. Но оно не работает. Двагис утверждает то же, что и таблички на остановке, что автобус тут ходит три-четыре раза в час. На самом деле: один автобус в час-полтора. Поэтому — набит битком, и надо стоять. На остановках в центре встречаются табло, показывающие время прибытия ближайших автобусов, но они работают нестабильно, автобусы умудряются оттуда исчезать или появляться мимо данных на табло.
Есть море. Но по нему ходят только редкие прогулочные яхты, да многочисленные катера, катающие отдыхающих на «бананах» и парашютах. Морского транспортного сообщения — нет. Единственный морской порт — в центре Сочи.
Самый-самый центр Сочи
Доехали на автобусе до парка «Ривьера». Мы хотели туда сходить в дельфинарий. Даже купили билеты онлайн. Но в тот день поехать не смогли. Спасибо sochi.kassir.ru. Хоть их заявление на возврат билета, в формате doc, — совершенно дурацкое, но моё письмо, присланное за три часа до представления, они рассмотрели, и деньги вернули.
Попали в «Ривьеру» на другой день. Оказалось, что «сад бабочек» — это лишь одна комната в дельфинарии. С кучей дохлых бабочек на булавках и парочкой полудохлых ещё летающих. И весь остальной «Ривьера» оставил какое-то впечатление старого советского никому не нужного парка развлечений.
Прогулялись по Курортному проспекту. Сочи — не город. Даже когда идёшь по центральной улице, нет ощущения, что ты в городе. Слева — горы. Справа — проглядывает море. Вокруг — сплошная зелень. И где-то в этой зелени вылезают здания этих самых санаториев или торчит шпиль морского вокзала. Какие-то отдельные строения в горном лесу. Где город? Где гущи домов? Где простор (помимо морского)? Или это я, прирождённый житель равнин, ничего не понимаю?
Посетили Сочинский дендрарий. Милое местечко. Крутая дача конца XIX века, сохранившаяся до наших дней. Забирайтесь наверх на канатной дороге. Спускайтесь зигзагами, разглядывая растения и животных. Там есть страусы и лебеди. А в нижней части парка живёт куча мелких петухов, которые кукарекают, выпрашивая вкусняшки.
Снова самый центр Сочи
По всему Сочи продают экскурсии. Сотни киосков. Десятки экскурсий. Напоминает Израиль. Экскурсионные автобусы собирают туристов пару часов, объезжая полсочи. А потом куда-то везут. К вечеру развозят обратно.
Мы поехали на 33 водопада. Это — ущелье, где действительно имеется куча водопадов. Небольших. Где-то 17 из них доступны туристам по проложенным дорожкам. Ещё свозили посмотреть на крупнейший на побережье дольмен. Это такие древнючие погребальные сооружения в виде громадного каменного домика с дыркой.
Дорогу к водопадам устроили с мокрым развлечением. Туристов погрузили в старенькие ГАЗ-66 и, кажется, в Урал-375. И повезли прямо по руслу горной реки. В конце лета горные реки пересыхают, и есть только отдельные неглубокие протоки. Вот эти протоки и форсировали вездеходы на скорости явно больше оптимальной. Туристы тряслись и визжали от радости, когда их окатывало брызгами от водной преграды. По мнению моей дочи, это было веселее американских горок.
Вторая наша экскурсия — на гору Ахун, где построена башня, с которой видно весь Большой Сочи. Да, видно. Да, красиво. Виды как в сторону моря, так и в сторону гор — замечательные. И в Агурское ущелье. Водопадов там не было, ибо для водопадов — не сезон, горные реки пересыхают.
На обеих экскурсиях нам устраивали дегустации. Мёда, сыра, вина и чачи. В двух разных местах. Как будто сыр и вино тут не делает только ленивый. Сыр — обычный сыр. Адыгейский, копчёный, как обычно. Мёд — разный и своеобразный. Вино — тоже разное. Чача — это 65-градусный самогон на отходах виноделия. Просто крепкий самогон.
Про вино понарассказывали много интересного. Тут, в Сочи, растёт только Изабелла, остальные сорта винограда привозят, и делают из них вино. На кавказском застолье предпочитают белые вина, потому что от них меньше пьянеешь. А на кавказком застолье нужно выпить много: по стакану на тост. Сухие вина — более натуральные. В сладких принудительно останавливают процесс брожжения, и уже типа не то. Вино вполне можно разбавлять водой (не из крана, но хотя бы кипячёной), это меняет (и даже улучшает) его вкус. Сталин любил Киндзмараули, или Хванчкару.
Сталина тут до странного часто поминают. «Тут была дача Сталина». «Этот проспект проложили по приказу Сталина»...
Всё, что дают продегустировать, можно купить. И даже увезти домой. И даже на самолёте, если у вас есть багаж. Вино наливают в пластиковые бутылки.
Тут я впервые попробовал полусухое вино, которое мне понравилось. А то белое полусладкое, полторашку которого мы таки купили, оказалось сногсшибательным. Оказалось, что достаточно двух стаканов, чтобы им напиться.
Шайтан-машины
Аэропорт Сочи, который в Адлере, теперь занимает первое почётное место в моём рейтинге аэропортов. Он — не похож на аэропорт. Нет очередей на входе. Нет многочисленных стоек регистрации, они как-то аккуратно прячутся за пальмами в холле. Ненавязчивый досмотр. А после досмотра на посадку ты попадаешь в магазин. Не в тесные коридоры терминала, заставленные сиденьями, а в нормальный duty free магазин. И должен зигзагами через этот магазин пройти. Гениальный маркетинг!
Сиденья и выходы будут потом. Но снова совершенно естественно перемешиваясь с магазинами и кафе. Там даже есть маленькая детская площадка, между двумя магазинами игрушек. Всё-таки ребята с Кавказа любят и умеют продавать. Даже экскурсовод Армен, человек-не-умолкающий-ни-на-минуту, не просто рассказывал о достопримечательностях, но и нещадно, но ненавязчиво, рекламировал, что там можно купить.
В аэропорту
Сочи — хорошее место для отдыха. Не бюджетное, в силу расстояний (бо́льшая часть потраченных денег — авиабилеты). Но хоть виза не нужна. А вот кроме отдыха там делать нечего. Убери туристов — и весь смысл существования этих санаториев полностью исчезнет.