Background
Возникла такая ситуация: возможностей MDA
virtual в
postfix с некоторых пор стало на хватать. У него возможность есть только одна: доставить письмо в ящик, чьи параметры он берёт из
virtual_* в
main.cf. Решил заменить на более умный MDA —
maildrop и часть сво
2000
его скрипта перенести на его язык.
Задача MDA
От MDA мне надо, чтобы
- он в завсисимости от того, спам это или нет, доставил почту в отдельный каталог.
- через extention в формате записи user extention@domain понимал, в какой каталог нужно доставить письмо.
сам скрипт пока не готов, сдесь пример перезда.
Текущая конфигурация
Так как я пока не успел описать её в
../ПочтоваяСистема, вкратце скажу здесь. Настройки почти целиком взяты с
http://www.opennet.ru/base/net/postfix_openldap.txt.html. Добавлены свои restrictions и таблицы в
virtual_mailbox_maps,
virtual_uid_maps,
virtual_gid_maps,
virtual_mailbox_domains для получения данных пользователя из
Open-Xchange 1. В итоге, в данных
Open-Xchage у меня находятся реальные пользователи, в дереве, взятого из статьи виртуальные —
alias'ы, служебные пользователи, например которым нужен только smtp.
Цель
В итоге, мне надо, чтобы почту для реальных ( из
open-xchange) пользователей мне проверяли на спам, раскидывали по каталогам — то есть здесь нужен
maildrop. Почту служебных пользователей пусть обслуживает postfix MDA
virtual.
Недостаток здесь только один — maildrop отказывается автоматом создавать несуществующий mailbox для пользователя. Да и каталог тоже. Проблему с каталогом можно решить через exeption и последующим соазданием в
maildroprc, тогда как с ящиком сложнее — если
madilrop не сможет сделалеть в него chdir, никакие
maildroprc и
maildropfilter обрабатываться не будут.
Решение
Maildrop
Если глянуть на дефолтный
master.cf,
maildrop запускается через
pipe. В принципе и верно:
maildrop в
delivery режиме 2 ждёт на stdin письма, которые он доставляет потом куда надо. На stdin ему передаёт письмо
pipe. Кому доставить для
maildrop указывается через
макрос pipe – ${recipient}.
Кроме ${recipient} maildrop понимает также и несколько других макросов (все они описаны в man 8 pipe). Один из них – ${extention}, который нам нужен будет для явного указания imap каталога для доставки
Авторизация в maildrop
В текущем (на 05.10.2005 14:16)
сизифе maildrop получает свои данные через
courier-authdaemon.
strace показал, что он подключается к /var/lib/courier-authlib/socket, куда пишет PRE . login <user>\n. и уже оттуда
madilrop получает «USERNAME=<user>\nGID=<gid>\nHOME=/hom»... в случае успеха, либо FAILED в противном случае.
Поэтому, для работы
maildrop через
ldap необходимо настроить
authdaemon. Ну и
достаточно прописать в
ldap правильные параметры.
Данные, что прописываются в статье 3 для работы maildrop с ldap не годяться!
Настройка Authdaemon рассматривается уже в другой статье :)
Работа maildrop и virtual с базой
Текущая
ldap-ячейка для работы
virtual и
courier-imap выглядит:
dn: mail=spam@comp-mir.ru,mailDomain=comp-mir.ru,ou=domains,ou=mail,dc=comp-mir,dc=ru
objectClass: top
objectClass: mailAccount
objectClass: posixAccount
mail: spam@comp-mir.ru
maildrop: comp-mir.ru/spam/
cn: Spam
uidNumber: 2100
homeDirectory: /var/spool/domains/
gidNumber: 2000
uid: бред
virtual получает maildrop-каталог из
maildrop: comp-mir.ru/spam/
virtual_mailbox_maps = ldap:ldapmaildrops
ldapmaildrops_server_host = 127.0.0.1
ldapmaildrops_search_base = ou=domains,ou=mail,dc=comp-mir,dc=ru
ldapmaildrops_query_filter = (mail=%s)
ldapmaildrops_result_attribute = maildrop
4
maildrop через
authdaemon получает
homeDirectory и
maildrop.
postfix транспорт
virtual затем соединяет данные из
virtual_mailbox_base и
maildrop атрибута и получает итоговый каталог: /var/spool/mail/domains/comp-mir.ru/spam/.
maildrop (
не authdaemon!) соединяет $HOME и $MAILDROP и получает тот же каталог, предварительно (
внимание) изменяя текущий каталог на домашний ($HOME).
В результате этого самого chdir для
maildrop'а требуется, чтобы домашний каталог (атрибут
homeDirectory) имел права пользоватея, указанные в
uidNumber и
gidNumber, тогда как общий каталог /var/spool/domains/ такими правами не обладает — там хоязин вообще root.
Значит для
mailrop'а требуется
homeDirectory: /var/spool/domains/comp-mir.ru/spam
maildrop: ./
Такую запись неверно обработает
virtual, так как он в конфигурации по статье
3 берёт все каталоги относительно
virtual_mailbox_base, который является константой. То есть в итоге мы получим
virtual_mailbox_base maildrop =
virtual_mailbox_base. Но мы хотим эти записи перекинуть для транпорта
maildrop, так что это не важно. Тут важно только то, что постпенно перейти не получится — для работы системы придётся вносить сразу несколько изменений.
Но в конфигурации
Open-Xchange мы имеем полноценных пользователей, которых хоть сейчас засовывай в
pam. То есть им можно в
homeDirectory указать
реальный домашний каталог, а атрибут
maildrop оставить равным «./», так как пока прикручивать это дело к
pam я не расчитываю :) Что я с успехом и проделал.
Делаем maildrop -d user-in-ldap < mailfile, если не получается, то с strace'ом. Иправляем. И так до тех пор, пока вручную
maildrop не доставит письмо куда надо.
Встраивание maildrop как транспорт в postfix
Для начала надо добавить ещё один транспорт: раскоментировать строку с ним в
master.cf. Или прописать самому
maildrop unix – n n – – pipe
flags=DRhu user=mail argv=/usr/bin/maildrop -d ${recipient}
Делаем финт ушами: прописываем для какого-нибудь ящика в
transport_maps транспортом maildrop. И проверяем, доло или нет. С конфигурацией с opennet
3 отдельная таблица для
maildrop письмо должно дайти. Как минимум должен ругнуться сам
maildrop, а не
postfix, что де пользователи не найдены.
Если
postfix ругается на отсутсвие поьзователя в таблице virtual, значит
postfix не считает себя final destination'ом для этого ящика. Потому что
postfix сначала проверет, к какому классу относится данный адрес (virual, relay, local, default) по таблицам
local_recipient_maps и
mydestination,
relay_domains,
virtual_alias_maps/virtual_mailbox_maps и только в случае наличия там ящика перенаправляет на выбранный транспорт.
Я решил задачу следущим образом: так как у меня уже домен comp-mir.ru принадлежит классу virtual, то указывать его в
mydestination или
relay смысла не имело — домен надо было целиком перекинуть в этот класс, что на активном сервере без проблем сделать тяжеловато. И я сделал просто: добавил в
virtual_mailbox_domains = ldap:ldapdomains, ldap:oxdomains. Почта на ящик прошла.
Чтобы не добавлять транспорт для каждого ящика я сделал ещё один финт ушами: добавил к
transport_maps в конец ещё одну lookup таблицу, в которой было указано:
server_host = 127.0.0.1
search_base = ou=Users,ou=Ox Objects,dc=comp-mir,dc=ru
query_filter = (mail=%s)
scope = one
result_attribute = maildrop
result_format = maildrop
4
В результате чего мне
postmap -q <user@domain> ldap:<наша таблица> мне для любого <user@domain>, что находится в этой таблице выдавал maildrop.
По русски это звучит так: для всех пользователей
Open-Xchange траспортом сделать
maildrop
Теперь осталось только написать в /etc/courier-imap/maildroprc скрипт, что хотя бы будет путём xfilter (
man 7 maildropfilter) прогонять почту через spamc, затем if(/X-Spam-Tag: YES/:h) делать to $DEFAULT/.Junk.
1 Про интеграцию
Open-Xchange и
postfix ещё надо написать. А времени нет :(
2 Из
man 1 maildrop:
maildrop runs in delivery mode when no filename is specified on the command line.
ключь -d указывает, куда доставить.
3
http://www.opennet.ru/base/net/postfix_openldap.txt.html
4 если вы уже обратили внимание, то настройки lookup таблиц можно указывать в main.cf, предваряя их "<имя таблицы>_", как сделано в ldap:ldapmaildrops, либо указать ldap:/path/file, и в нём без всяких преф
1000
иксов писать параметры, что указаны в мане.