[О блоге] [наверх] [пред] [2021-09-02 14:20:19+03:00] [b3aacd1afbe290cc93ecef73e0575f5443b9a24f]
Темы: [dns][mail]

MTA/MDA/MRA/MUA

Писал тут быстренько письмо с разъяснением что это за аббревиатуры
касающиеся почтовых систем. Думаю что можно и в блог вставить.

          ------------------------ >8 ------------------------

Если бы наша компания была сейчас в 70-х, то у нас бы был один большой
мейнфрейм, а у нас у каждого бы просто обычный терминал (не эмулятор, а
настоящий, физический :-), типа VT100). Чисто физически он буквально бы
был соединён типа длинным кабелем до COM-порта. Как в Unix-like системах
в терминале есть Alt-F1/F2/... терминалы, то вот их было бы просто с
сотню, до каждого рабочего места.

Почта уже существовала и тогда и она просто лежала в виде
сконкатенированных сообщений в /var/mail/$USERNAME файле. Набираешь:
    mail -s "my subject" colleague <<EOF
    тут всякий текст для отправки
    EOF
и соответствующий mailbox файл lock-ается и в него append-ится
сообщение. Набираешь просто mail[x] и попадаешь в программу
чтения/работы с почтой. Сами почтовые сообщения состоят из заголовка
(key-value строчки) и дальше тела. Позже, из-за того что не только на
английском люди пишут, не только текст, но и вложения могут делать, то
появилось расширение в виде MIME (multipurpose internet mail extensions),
которое добавляет дополнительные заголовки указывающие на какие части
разбито сообщение, как каждая часть закодирована и всё такое прочее. Но
это тут не суть совсем.

Но у компании есть филиал в Владивостоке. Со своим мейнфреймом. Быстро
сделали такую штуку как UUCP: Unix-to-Unix CoPy. Относительно простая
система в которой ты можешь набрать что-то типа:
    uucp my-file vladivostok!matveev
Эта команда на "vladivostok" систему добавит в очередь отправку "my-file"
файла пользователю "matveev". UUCP демон время от времени соединяется по
модему с другой Unix системой и обменивается накопившимися пакетами.
Кроме "uucp" (cp файлов) есть команда "uux" (unix-to-unix execute)
которая позволяет выполнить удалённые команды. И через эту команду
происходила отправка почты буквально просто вызовом на удалённой системе
"rmail" команды подавая ей на вход сообщение. Буквально просто
запускалась программа удалённо, а не локально. Но почта точно так же
просто клалась в /var/mail/matveev там.

Кроме Unix систем была масса других со своими протоколами, форматами и
прочим. IBM PC ещё не появился, как и Apple. Да и даже с их появлением у
них долго не было никакой почты или чего-то подобного, кроме
коммерческих проприетарных enterprise систем типа Lotus Notes каких-нибудь.

А потом ещё появился Интернет, для которого только в середине 80-х был
вообще изобретён BSD TCP/IP стэк (BSD сокеты). И вот начиная с этого
времени начали Unix системы "дружить" с Интернетом и вообще задумываться
об унификации и стандартизации всего и вся (тут и RFC появились, как
сущность). Был изобретён довольно простой SMTP протокол (simple mail
transfer protocol). В ОС добавлялся MTA (mail transfer agent) который
общался с другими MTA (на других системах) по SMTP протоколу. В общем
случае, SMTP сессия выглядит так:

    S: 220 smtp.example.com ESMTP Postfix
    C: HELO relay.example.com
    S: 250 smtp.example.com, I am glad to meet you
    C: MAIL FROM:<bob@example.com>
    S: 250 Ok
    C: RCPT TO:<alice@example.com>
    S: 250 Ok
    C: RCPT TO:<theboss@example.com>
    S: 250 Ok
    C: DATA
    S: 354 End data with <CR><LF>.<CR><LF>
    C: From: "Bob Example" <bob@example.com>
    C: To: Alice Example <alice@example.com>
    C: Cc: theboss@example.com
    C: Date: Tue, 15 Jan 2008 16:02:43 -0500
    C: Subject: Test message
    C:
    C: Hello Alice.
    C: This is a test message with 5 header fields and 4 lines in the message body.
    C: Your friend,
    C: Bob
    C: .
    S: 250 Ok: queued as 12345
    C: QUIT
    S: 221 Bye

То есть, буквально просто сообщается от кого, кому надо отправить
сообщение, DATA, после которой идёт тело сообщения. Теперь, когда ты
набираешь mail/mailx/whatever и отсылаешь сообщение, то оно не
перекладывается в /var/mail, а отправляется локальному MTA серверу. Это
может происходить просто вызовом команды "sendmail RECIPIENT" и
скармливанию почтового сообщения в stdin ей. Это может происходить
подключением к localhost:25 и использованию SMTP протокола. Кроме того,
есть ещё и LMTP протокол (lightweight MTP), который является просто
подмножеством SMTP исключительно для работы в пределах localhost. Это
всё удобно тем (с точки зрения программиста/администратора), что MTA
достаточно уметь общаться по одному протоколу и просто перекладывать
сообщения в /var/mail файлы соответствующие.

На полном серьёзе, до сих пор так всё и осталось, даже вчера на твоей
системе, но когда ты сделал git-send-email, то он по умолчанию запустил
sendmail команду которая (конкретика MTA-специфична) в локальный MTA
отправило сообщение. Локальный MTA сохранил на диск в очередь исходящих
сообщений. Твой MTA видит что сообщения для stargrave@stargrave.org. Он
делает запрос в DNS с вопросом о том, кто отвечает за доставку почты для
данного домена:

    % drill stargrave.org MX
    stargrave.org.  21600   IN      MX      10 mailfake0.stargrave.org.
    stargrave.org.  21600   IN      MX      20 mailfake1.stargrave.org.
    stargrave.org.  21600   IN      MX      30 mail2.stargrave.org.
    stargrave.org.  21600   IN      MX      40 mailfake2.stargrave.org.

и видит что четыре "сервера" (адреса) за это ответственны. В итоге он
подключится к mail2.stargrave.org по SMTP протоколу и как в примере выше
отправит письмо, указав что оно для stargrave@stargrave.org пользователя.
Если бы за почту для домена stargrave.org отвечал какой-нибудь Google,
то в MX записях DNS-а были бы серверы GMail указаны.

То есть, это буквально децентрализованная система очередей. Ты локально
в очередь добавил -- из DNS-а взяли данные о целевой системе,
соединились, по довольно простому текстовому протоколу отправили
сообщение, которое на целевой системе будет положено в очередь
доставленных сообщений (mailbox пользователя).

Всем известные популярные MTA это:

* Sendmail (не стоит путать команду "sendmail" и систему Sendmail)).
  sendmail команда это просто некий API. А Sendmail система была
  де-факто очень долго за счёт того, что она могла общаться и связывать
  воедино не только Интернет-почту (SMTP), но и UUCP старый и ещё с
  десяток других совершенно разных сетей. Но она сложно конфигурируется,
  славна дырами и сейчас просто бессмысленна, хотя и стоит из коробки в
  BSD системах
* Exim -- по умолчанию стоит в большинстве GNU/Linux систем. Одна из
  самых простых, но при этом не самых производительных систем, ибо
  только один процесс за всё отвечает. Но для 99% организаций и людей
  это не проблема. Хорошая штука
* Postfix -- MTA состоящий из кучи privilege separated процессов и
  славен как пример очень безопасного подхода к написанию софту. Очень
  производительный. Я всю жизнь использовал только его. Он тоже просто в
  настройке. Например дома я установил себе новый сервер/компьютер,
  поставил Postfix: чтобы мне сделать так, чтобы он мог отправлять почту
  в Интернет, то мне достаточно добавить *ровно* одну строчку с
  указанием где находится мой почтовый relay -- на этом всё, почтовая
  система полностью готова к работе
* qmail -- творение Бернштейна, но уже вроде бы мёртвое, ибо он его
  давно забросил. Когда-то это был вроде лучший MTA из существующих,
  пока не появился Postfix (Exim, кстати, самый "молодой")
* OpenBSD пилят свой OpenSMTP, но он год назад даже мои задачи бы не
  удовлетворил

В MTA дьявольское количество настроек -- и всё только из-за колоссальной
гибкости на любой вкус и на любое пожелание. Простому Unix пользователю
достаточно 0.01% от всего что эти MTA умеют. Вот когда ты отправил
письмо на stargrave.org, предполагая прям буквально мою систему, мой
компьютер (хотел было написать "мой ноутбук" :-)), то, так как мы в РФ,
то с IPv6 у нас пока не очень хорошо и мой компьютер не находится в
Интернете постоянно. Поэтому используется relay в виде mail2.stargrave.org,
который у себя забуферизирует корреспонденцию. Но мой компьютер и мой
сервер общаются для отправки/получения почты не по SMTP, а по NNCP моему
-- в Postfix можно использовать кучу разных транспортов и методов
доставки (совершенно не обязательно иметь TCP/IP связанность). Некоторым
доменам я вообще всегда даю отлуп (vk.com, mosreg.ru, и т.д.). За
некоторые домены, типа lists.cypherpunks.ru, отвечает не мой компьютер,
а прям сам mail2.stargrave.org сервер, а другие домены он должен
отправлять (relay) в очередь на мой компьютер. Какие-то особые адреса
(типа адреса папы и мамы) отправляются на gmail.com сразу, делая
forward. Доставка почты для lists.cypherpunks.ru идёт не в почтовый
ящик, а вызывая программу менеджера почтовых рассылок, скармливая ей
сообщения. Сообщения на comment@blog.stargrave.org адрес отправляются в
мою Go-программу добавления комментариев в блог. У меня есть проверка
заголовков входящий сообщений, посылающая в жопу всех у кого не указана
тема письма. Есть настройка в отдельном файле заставляющая хранить
абсолютно всю проходящую корреспонденцию (архив всей почты)... кроме
определённых адресов (типа мониторингов сервера). Сам
mail2.stargrave.org только принимает почту, но отправляет через
mail3.stargrave.org MTA. Кроме того, он ещё и пропускает почту через
фильтры добавляющие DKIM подпись в заголовки писем. Входящую почту
пропускает через greylisting системы и системы проверки SPF. А на моём
локальном компьютере есть маршрутизация вида: если почта идёт от
@arbeit.ru, то использовать наш рабочий relay по SMTP, а в противном
случае по NNCP использовать мой mail2.stargrave.org relay. И ещё есть
всякие фишки и настройки для почтовых рассылок. И я один единственный
простой Unix-guy -- но вот даже для меня MTA довольно много чего должен
уметь делать, поэтому они такие богатые настройками и возможностями.

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

Но задачи у людей при приёме писем немного усложнились, с появлением
Интернета. Теперь мне не достаточно складывать всю корреспонденцию в
один ящик. Мне хочется для определённых почтовых рассылок положить в
другие ящики, какие-то письма (например явный спам) сразу удалять или
класть в "spam" почтовый ящик. Я хочу ещё и копии сохранять в архиве. Но
при этом игнорируя сообщения мониторинга и рабочую почту (её в отдельный
архив). И так далее и тому подобное. Можно конечно было бы усложнять MTA
добавляя возможности по подобным настройкам и хотелкам, зачастую
динамическим (например когда я в отпуске, то работал бы автоответчик
предупреждающий о том что я только через неделю посмотрю ваше входящее
письмо), но народ придумал отдельный компонент в виде MDA (mail delivery
agent). Из известных есть procmail, maildrop, Dovecot, Cyrus, Courier и
много других. MTA просто говорится в конфиге как надо и какой MDA
вызвать для приходящей корреспонденции. MDA не всегда явно присутствует:
часто его задачи выполняет и MTA (ведь положить в /var/mail это тоже
вполне себе уже такой маленький минималистичный MDA) и MRA программы (о
них ниже).

А вообще даже есть целый язык для скриптования MDA:
https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)
который в некоторых системах можно использовать удалённо загружая на
сервер: то есть ты прям типа из почтовой программы можешь написать это
Sieve скрипты и загрузить на почтовый сервер чтобы там всякая
автоматизация происходила.

А в 90-х до всяких дешёвых простых не-Unix компьютеров (IBM PC, Apple и
прочее) дошли модемы и дошёл софт позволяющий работать с почтой. Но так
как они не были подключены постоянно к Интернету, да и иметь свой домен
не много кто мог себе позволить, или иметь где-то доступ на Unix систему,
то появился сервис по хранению почты на сторонних серверах. Вместо
предоставления удалённого доступа до этих Unix-ов и использования "mail"
программы прямо на них, придумали отдельные примитивные протоколы
скачивания почты: POP3 и IMAP4 позже. По сути это протоколы доступа к
/var/mail/$USERNAME почтовому ящику. POP3 буквально позволял просто
получить кол-во сообщений, их список, получить сообщение по номеру,
удалить его. IMAP4 много чего умеет делать, типа получения только
заголовков (ведь тело может быть большим), типа хранения в разных
"директориях" (создание под-ящиков) и всего такого прочего. Программы
получающие корреспонденцию с подобных систем по этим протоколам
называются MRA (mail retrieval agent). Это например fetchmail и fdm.

Подчеркну, что из коробки MRA в Unix системах не ставится. Это тема для
бедных, у кого нет под рукой вообще никакой полноценной доступной в
Интернете Unix системы. Я понимаю что таких большинство, но это уже
костыли. Теперь, если используются подобные третьи лица для хранения
почты, то запускается MRA, который получает корреспонденцию и отправляет
в локальный MTA, который, в свою очередь, отправляет в MDA для
раскладывания всего по полочкам как тебе надо. Можно сказать что вместо
прямой SMTP↔SMTP связи между твоей системой и удалённой, происходит
polling-связь по MRA-протоколу копирующего всё в локальный MTA.

Почтовая программа с которой работает пользователь называется MUA: mail
user agent. Штатно она умеет только работать буквально только с
сообщениями и почтовыми ящиками. Отправка, приём -- всё это задачи MTA,
MRA, MDA. Но многие популярные MUA заимели и собственные SMTP-клиенты,
MRA-клиенты и даже MDA. Ведь пользователь под DOS/Apple (речь про
классическую MacOS, а не современную Unix-like) просто не могли
технически запускать у себя демонов разношёрстных -- там приходилось всё
засовывать в одну программу. И какой-нибудь Thunderbird самостоятельно
может (зависит от настроек) связаться по SMTP с relay сервером для
отправки, самостоятельно связаться с IMAP4 для скачивания почты,
самостоятельно иметь собственные правила разбора и обработки писем и
раскладывания по почтовым ящикам. Mutt аналогично. Как правило они менее
гибкие чем full featured MTA+MDA+MRA, но в 99% случаев достаточны для
использования конечным единственным пользователем.

git-send-email в последних версиях тоже заимел возможность связываться
напрямую по SMTP с указанным тобой MTA. Во всяких Windows же нет
локального MTA в принципе, как возможно и в macOS по умолчанию, поэтому
локально просто некуда ничего отправлять и нужно или поднимать что-то
простое типа ssmtp (MTA который просто играет роль прокси) или
связываться по SMTP с удалённым relay-ем (личный GMail.com, рабочий
почтовый сервер, и т.д.). https://wiki.archlinux.org/title/SSMTP

Судя по всему, в macOS из коробки поставляется Postfix MTA. В принципе
это вопрос 5-6 строчек в его конфиге на рабочем компьютере чтобы этот
Postfix связывался с нашим mail.arbeit.ru почтовиком для отправки
корреспонденции под твоей учётной записью.

Почему ты не можешь отправить напрямую, как вчера твой домашний
компьютер это пытался делать? Всё исключительно из-за спаммеров. И
возможно из-за вирусописателей, которые заражали Windows-ы и с каждой
машины отправляли тонны писем. Ты возможно обратил внимание в SMTP
протоколе что никакой аутентификации, никакой авторизации или чего-то
подобного в нём не было. Поэтому MTA серверы стали требовать чтобы IP
адрес с которого ты соединяешься, совпадал с доменом о котором ты
сообщаешь в HELO SMTP приветствии и чтобы DNS PTR запись для этого
IP-адреса совпадала тоже с этим доменом. Далеко не все провайдеры
позволяют прописать DNS PTR запись для IP адреса простым домашним
пользователям. Ростелеком -- пидоры например. NetByNet -- лапочки, без
проблем это делающие. Конечно если речь про статический IP адрес. Для
динамических это невозможно. Но если бы у тебя была статика с нужной
PTR-записью, то без проблем твой компьютер мог бы отправить на мой
mail2.stargrave.org почту. Точнее он то отправлял, но мой mail2. из-за
отсутствия PTR-записи должен был послать в жопу.

Вот как-то так всё устроено. Выглядит сложно. Софт сложный. Но всё из-за
колоссальнейшей гибкости, широчайшего круга задач и настоящей
децентрализации. Но вообще у тех кто использует Git (не через
web-интерфейс Github-а, грубо говоря), кто сидит под Unix-like системой,
предполагается что имеется работающая почтовая система (локальный MTA,
хотя бы просто отправляющий почту в relay вышестоящий).

    [оставить комментарий]