В качестве предисловия причины всего этого движа

Техничка начнется только в следующем блоке, поэтому если предыстория не интересна – смело пролистывай.

Яндекс 360 — это уже третья (на моей памяти) реинкарнация одного и того же сервиса для хостинга почты и DNS для собственных доменов. Изначально я начал пользоваться этим функционалом в 2013 году и тогда он назывался Яндекс ПДД (почта для домена) и имел незатейливый интерфейс. Главное он работал, работал качественно и был бесплатен. Далее в 2017 он переименовался в Яндекс Коннект и переехал на новый домен. Возможно, уже тогда появился платный функционал, но это меня не сильно потревожило, т.к для меня это было не заметно. В 2020 Яндекс выкатил новую замену – Яндекс 360. В тот момент, с точки зрения админа своих почтовых доменов я даже не заметил разницу. Чуть позже началось продвижение платных услуг и чем дальше в лес, тем голоднее комары постепенно их продвижение становилось все более навязчивым и агрессивным.

Вводные по моему использованию ресурсов Яндекса:

  • За 10 лет у меня накопилось 10 доменов на сервисе.

  • От 1 до 15 ящиков на каждом домене.

  • Забегая вперед общий объем почтовых переписок по всем доменам – менее 10Гб.

Летом 2022 я поддался на рекламу и купил на 1 месяц подписку для одного домена, оплатив с р/с ИП. Мне просто хотелось посмотреть на функционал. Сумма подписки напрямую зависит от количества ящиков и что бы сократить размер платежа я удалил бесполезные ящики на этом домене и оставил только 5шт. Всеми пятью ящиками пользовался я один. Заплатил чуть меньше 300р за каждый ящик. Через некоторое время я протестировал функционал Яндекс 360 (видеоконференции, календари и т.п.) и для меня он оказался практически бесполезными. Именно практически бесполезным, т.к. направлен на работу в команде, а я сам с собой могу договориться и без использования сервиса Яндекс 360. Далее я отказался продлевать подписку и думал, что история исчерпана.

В феврале 23 года мне поступил интересный звонок, который перевернул всё в верх дном. Мне позвонил менеджер из Яндекса и рассказал удивительную историю, что с 17 апреля для меня Яндекс 360 превратится в тыкву, если я не буду платить. Главное ограничение – исходящая почта больше не будет отправляться. Я, конечно, уже не помню в точности разговор и рассказываю о нем как мне запомнилось. Во-первых я не уточнил на сколько доменов будут введены санкции, но быстро прикинул в голове цифру около 7-10тыс ежемесячно за все домены, озвучил это менеджеру, и он меня никак не поправил. Исходя из этого я понял, что меня просто разводят на деньги, а т.к. у меня лежал сервер hp360 gen9 дома и у меня никак не доходили руки разместить его в дата-центре, я принял решение, что пора заканчивать с этими облачными сервисами и поднимать свой почтовый сервер.

Информация от Яндекса в справке: https://yandex.ru/support/business/payment/disable-free-version.html

При этом, если зайти на admin.yandex.ru отображается такое уведомление:

Hidden text

А еще один раз столкнулся с такой ошибкой при подготовке статьи:

Hidden text

Забегая вперед скажу, что Яндекс на самом деле запланировал ввод ограничений только на тот домен, где ранее был платный сервис 360. Это значительно уменьшало ежемесячную сумму и возможно даже 1.5 тыс рублей ежемесячно не стоили всех трудов по размещению сервера и развертыванию собственного решения. Ведь за размещение сервера + cisco asa + подсеть /28 в Tier II я теперь плачу чуть меньше 8тыс рублей ежемесячно. Хотя, говоря по правде, свой сервер в ДЦ это свой сервер в ДЦ и куча возможностей (ведь не только почтовый сервер можно запустить)! Факт введения санкций только в отношении одного домена я узнал значительно позже и теперь это меня мало волнует.

Муки выбора решения

Я не являюсь почтовым админом и последний раз разворачивал свой собственный почтовый сервер на линухе лет 12 назад. Хотелось бесплатное решение из коробки. Смотрел в сторону зимбры и пиратской инсталляции эксченджа. Но главные минусы этих продуктов – это монстрообразные штуки, которые мне не понятно как поддерживать в будущем. Случайно мне попалось упоминание Mailu. Концепция отличная – контейнеры с опенсорс продуктами и всё работает из коробки. Единственное смущало, что проект завис в развитии и последний релиз 1.8 был в середине 21 года. А т.к. я немного знаком с контейнерами и кубером, то этот вариант мне казался более перспективным, нежели зимбра. За то время, пока я решал вопросы с размещением сервера вышел релиз 2.0 и после все сомнения были отброшены.

Развертывание

Из реальных требований под развертывание:

  • Белый ip адрес (не попавший в спам базы).

  • PTR запись для вашего ip адреса.

  • Корректно настроенный DNS для домена (использую bind9 на другой виртуалке)
    Linux x64 с возможностью установить docker и docker-compose (использовал oracle linux 9.1).

  • Пара ядер на сервере (выдал 4 для этой виртуалке, но это избыточно).

  • Пара гигов оперативы (выдал 6Гб для этой виртуалке, но это избыточно, т.к. в памяти выше 1.5-1.6 гигов лежит только кэш).

 Более подробная статья по развертыванию тут

Устанавливаем ОС на целевом сервере. На данном этапе я предпочел выделить отдельный раздел для каталога /mailu (размер оценивайте сами, мусора и логов там не будет. Основная нагрузка – почтовые ящики).

  1. Ставим на целевом сервере docker и docker-compose.

  2. Опционально. Для docker-compose я люблю добавлять алиас в .bashrc: alias d='docker-compose'

  3. На сайте формируем docker-compose файл из своих хотелок

  4. На целевом сервере, если это не было сделано ранее создаем каталог /mailu и качаем 2 файла, полученные на предыдущем шаге в этот каталог.

  5. После в этом каталоге запускаем d up -d

  6. И устанавливаем пароль на админскую учетную запись docker-compose -p mailu exec admin flask mailu admin admin mydomain.org PASSWORD

Реально на 5 шаге происходит «магия». За 1 запуск nginx сразу получит все сертификаты от letsencrypt. Все сервисы запустятся и сразу же из коробки будет tls для imap, smtp и pop3. Меня это очень впечатлило.

Минусы системы после развертывания

Антивирус: контейнер с антивирусом не может обновить базы, т.к. возможно российские ip адреса заблокированы. Поэтому толку от такого ClamAV нет. Я его остановил. Как решить эту проблему я не нашел, т.к. было не до этого и я не искал. Если кто знает как завернуть траффик одного контейнера в vpn – подскажите в комментариях.

URI Админки: сделал вывод, что указывать в конфигураторе «Postmaster local part» что-то секретное нет никакого смысла. Путь прослеживается сразу из формы авторизации.

Snappymail: В качестве веб морды выбрал snappymail. Если выбрать отображение по 1000 писем на странице, то вообще не работает. Если по 100, то очень долго и притормаживает из-за долгого выполнения php кода.

Есть косяк в интерфейсе админки. Он меня поставил в ступор. После развертывания и добавления домена веб интерфес подсказывает какие необходимо внести записи на DNS сервере. Но при этом нет полей касаемо DKIM.

Hidden text
Параметры ДНС для только что добавленного домена
Параметры ДНС для только что добавленного домена

Оказалось, что необходимо нажать кнопку «Сгенерировать ключи», чтобы появились поля для настройки DKIM. Мне кажется это как-то не очевидно. Тем более при нажатии на кнопку выскакивает предложение «Вы собираетесь совершить regenerate keys for habr.com. Подтвердить?». Я раза только с третьего решился перегенерировать ключи, т.к. было лень bind9 переконфигурировать. Результат меня удивил – появились ключи DKIM.

Hidden text
ДНС параметры домена после перегенерации ключей.
ДНС параметры домена после перегенерации ключей.

Так же есть проблема с передачей названий каталогов в fetchmail, но только закодированных в модифицированной utf-7 кодировке. Но об этом дальше.

Fetchmail: Собственно основная боль… У меня стояла задача перенести всю почту не потеряв ни единого письма.

Fetchmail ставится отдельным контейнером. Конфигурируется из веб морды основной системы. При этом нет какой-то общей админской части. Т.е. необходимо из под каждой почтовой УЗ настроить сбор писем на удаленном сервере. Так перенести пару-тройку ящиков еще можно, но когда их больше 10 ты будешь страдать.

Собственно, fetchmail в комплекте используется достаточно старый 5-ый релиз. В то время как 6-ой давным-давно вышел. Хотя на результат это никак не влияет. У fetchmail очень мало параметров по забору почты. Либо забирает все непрочитанные и сразу помечает их прочитанными, либо забирает всё без разбора. Из веб морды можно настроить только 2 варианта: забираем непрочитанные и помечаем их прочитанными либо забираем всё и всё удаляем. Задание в планировщике по умолчанию выполняется раз в 10 минут.

Тут начались костыли с тем, что бы забрать всё, не перепомечая ручками все письма в ящике непрочитанными. Пришлось вытащить питоновский скрипт, запускающий fetechmail и крутить его в руках, что бы вмешиваться в передаваемые параметры. Благодаря этому удалось всё забрать из каталога INBOX и положить на собственный сервер, не удаляя на яндексе. Пришел черед экспериментов с такими папками как Черновики и Отправленные. Во-первых оказалось, что если в вебморде вписать несуществующий каталог в почтовом ящике посередине списка существующих каталогов, то процесс оборвётся на несуществующем каталоге. Во-вторых я узнал о существовании модифицированного utf-7 для обозначения кириллических каталогов. Вот так выглядят реальные имена каталогов:

Нежелательная почта

&BB0ENQQ2BDUEOwQwBEIENQQ7BEwEPQQwBE8- &BD8EPgRHBEIEMA-

Отправленные

&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-

Исходящие

&BBgEQQRFBD4ENARPBEkEOAQ1-

Черновики

&BCcENQRABD0EPgQyBDgEOgQ4-

Шаблоны

&BCgEMAQxBDsEPgQ9BEs-

Удаленные

&BCMENAQwBDsENQQ9BD0ESwQ1-

INBOX

INBOX

Как видно папка Отправленные в utf-7 содержит запятую и при добавлении через веб интерфейс это имя разбивается на два разных &BB4EQgQ и BEAEMAQyBDsENQQ9BD0ESwQ1-. Идут попытки синхронизации и Яндекс конечно же с радостью сообщает, что каталога &BB4EQgQ нет, а как мы уже знаем, что при несуществующем каталоге синхронизация останавливается.

Я решил, что одним костылём больше или меньше меня не сильно волнует и вкорячил эти папки в тело скрипта, который в контейнере. Дело сдвинулось с мертвой точки. Каталоги успешно синхронизировались, я открыл веб и интерфейс на своем сервере и не обнаружил писем в катале Sent… Но при этом я обнаружил все отправленные письма в каталоге INBOX. На этом можно было так всё и оставить, т.к. сам факт есть, что письма перенесены, но кривой результат мне не давал покоя. Я в тот момент понял, что ничего не понимаю в почте и на неделю забросил все эти эксперименты.

Собравшись с силами через неделю, я пошел изучать первопричину такого поведения. Оказалось, что fetchmail направляет письма в dovecot по протоколу lmtp. Среди кучи существующих параметров в fetchmail я не нашел ни одного позволяющего указать каталог при передаче письма в dovecot. Возможно это вообще не возможно.

IMAPSYNC

Далее я начал искать альтернативное решение и набрел на статью на хабре.

Реализация imapsync из этой статьи выглядела рабочей, но без должной упаковки в контекст реализации Mailu. Просто для теста развернул код из статьи локально и попробовал воспроизвести. Оказалось, что для моих целей это подходит.

Основные плюсы реализации:

  • Проводится синхронизация всех папок. Для теста попробовал синхронизировать вложенную папку INBOX.test123 и все успешно получилось без костылей.

  • Синхронизация кириллических каталогов производится в английские аналоги (Отправленные -> Sent, Черновики -> Draft и т.п.).

  • Работает достаточно быстро при передаче сообщений. Примерно 20-70Мбит/с я наблюдал.

Основные минусы реализации:

  • Без указания корректных учетных записей и паролей никак. Следовательно процесс идет не автоматизировано для всего домена.

  • Возможны просадки по скорости при получении списка писем. Наблюдал скорость получения списка почты от Яндекса со скоростью 4-8Кбит/с. Следовательно процесс запуска непосредственной синхронизации бывало тупил.

  • Реализацию из статьи надо где-то запускать отдельно.

В этот момент я понял, что хочу написать статью на хабр, что бы у людей было полное представление о том, что надо делать, если захотят повторить, но писать статью на Хабр, со словами: «Смотрите я нашел статью на Хабре и ей воспользовался – она работает!» ну как-то глупо. В условии, что всё оставшееся запускается в контейнерах, а imapsync надо где-то рядом положить. Поэтому было принято решение реализацию imapsync завернуть в контейнер и дать другим людям возможность быстро запускать в рамках docker compose существующей инсталляции Mailu.

Собрал всё в контейнер. Из интересного – обнаружилось, что в скрипте миграции почтового ящика (startimapsync.sh) мешаются комментарии для запуска цельной команды. Пришлось их убрать. Также в html форму добавил стандартный сервер источник imap.yandex.ru, а в качестве стандартного сервера назначения указал imap (dns имя контейнера dovecot). Так же для сервера назначения данные будут передаваться без шифрации. Если необходимо использовать ssl, то для этого доступен отдельный контейнер с тегом 993-port. Контейнер получился достаточно жирным, почти 170Мб, т.к. содержит кучу зависимостей для утилиты imapsync, апач и php.

Так же надо учитывать, что при попытке повесить imapsync на рандомный порт и пытаться работать с ним по http, то могут возникнуть проблемы из-за HSTS. Каждый раз чистить HSTS кеш в браузере для открытия странички – это боль, поэтому надо использовать nginx.

Для добавления в существующий docker-compose файл контейнера imapsync делаем следующее:

cd /mailu
wget https://raw.githubusercontent.com/vajrock/imapsync/main/docker-compose.patch
patch < docker-compose.patch
wget -P /mailu/overrides/nginx/ https://raw.githubusercontent.com/vajrock/imapsync/main/imapsync.conf
d stop front && d up -d front imapsync --no-deps

После этого можно подключиться к <ваш_домен>/imapsync/ и начать процесс переноса ящиков.

Процесс переноса

Зная логин/пароль к своему почтовому ящику далеко не факт, что вы его сможете сходу синхронизировать.

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

Во-вторых, не у всех пользователей оказалась активна галочка на разрешение подключения по imap со стандартным паролем пользователя. Даже на тех почтовых ящиках, что ранее гарантированно использовались в почтовых клиентах. Также не помогло включить imap для всех ящиков, установив галочку «IMAP» в админке домена.

Поэтому выработался такой порядок:

  1. Сброс пароля для пользователя в админке Яндекса.

  2. Авторизация под пользователем в приватной вкладке.

  3. Подтверждаем регистрацию.

  4. Шестеренка -> Все настройки -> Почтовые программы и включаем галочку «Портальный пароль».

  5. В админке Mailu создаем пользователя.

  6. Переходим в imapsync и запускаем синхронизацию.

  7. Можно выполнить пункты 1-5 для другого ящика пока идет процесс переноса текущего
    Проверяем результат и закрываем приватную вкладку.

Послесловие

Эта статья не претендует на звание правильного во всех отношениях руководства к действию. Автор не преследовал цель дискредитировать сервисы Яндекса. За 10 лет успешного пользования сервисами Яндекса у меня не возникало каких-либо критических проблем, а решение было принято попробовать самому реализовать свой почтовый сервер, т.к. нет уверенности, что еще через 10 лет письма со всей исторической перепиской вообще будут доступны (данные на Яндекс Диске у перенесенных пользователей уже были удалены... возможно было уведомление по этому поводу, но я его просто пропустил :( )

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

Артефакты из статьи:

Комментарии (37)