Содержание: как заставить postfix в составе Zimbra нормально принимать почту на псевдо-адреса в файле /etc/aliases или его аналоге.
Понадобилось мне обработать дополнительно письма, приходящие на конкретный адрес. Это было частью весьма эротичной (в смысле - поебаться с ней пришлось конкретно) задачи: письмо, отправленное на несколько абонентов "Мегафона", разбить на отдельные сообщения. То есть, "Мегафон" позволяет отправлять емайлы на "адреса" вида номер_телефона@sms.megafondv.ru (для Дальнего Востока). Но из строк to:/cc:/bcc: обрабатывается только последний адрес получателя, все остальные молча игнорируются. "Мегафон" предлагает услугу, что-то вроде пакетной рассылки смс таким способом, но за приличные таньга.
Проблема только в том, что если не удастся отправить своевременно короткие сообщения именно этим нескольким конкретным получателям, то "Мегафон" в нашей области может сдохнуть через несколько часов после наступления необходимости в такой отправке - диспетчер энергосистемы должен таким способом проинформировать начальство о серьезных сбоях вроде взрыва Фукусимы или пожаре на входном городском трансформаторе.
Тем не менее, такая общественно-полезная рассылка меньше чем на десяток корпоративных номеров всё равно осталась платной услугой, и мы решили её не покупать.
Вместо этого было решено воспользоваться возможностью, которую предоставляет postfix - пересылкой входящих писем не только на другие адреса, но так же и в файлы и в конвейер для какой-нибудь команды.
Полученное таким образом сообщение можно будет обработать каким-нибудь парсером и, например, превратить в несколько сообщений, по одному на каждый мегафоновский псевдо-адрес.
Очевидно, решение простое:
1) прописываем в
либо для команды:
2) разрешаем постфиксу отправлять почту в файлы и командам:
3) запускаем newaliases для обновления хэшированной таблицы псевдонимов и делаем postfix reload.
И радуемся жизни. Так просто? А вот хрен там!
Начнем с того, что вписать последний параметр в main.cf не получилось - после перезапуска всей зимбры или хотя бы zmmtactl restart знак "+" исчезал. Вот просто брал и исчезал, словно я его и не ставил.
Чтобы он не исчезал, надо внести изменения в конфигурацию зимбры:
Теперь он будет появляться в нужной строке даже если его убрать. Сам по себе этот параметр не особенно критичен для моей задачи, но пусть будет.
Готово? Нет, не готово: postfix продолжает ругаться на неправильное имя получателя что для робота, что для бобота. Копаем дальше.
Во-первых, находим в master.cf.in (именно cf.in, а не просто .cf - в .in файлах зимбра хранит шаблоны, из которых при каждом запуске формирует настоящие файлы. То есть, если внести изменения в master.cf, то они исчезнут при перезапуске зимбры) ищем строки:
Понадобилось мне обработать дополнительно письма, приходящие на конкретный адрес. Это было частью весьма эротичной (в смысле - поебаться с ней пришлось конкретно) задачи: письмо, отправленное на несколько абонентов "Мегафона", разбить на отдельные сообщения. То есть, "Мегафон" позволяет отправлять емайлы на "адреса" вида номер_телефона@sms.megafondv.ru (для Дальнего Востока). Но из строк to:/cc:/bcc: обрабатывается только последний адрес получателя, все остальные молча игнорируются. "Мегафон" предлагает услугу, что-то вроде пакетной рассылки смс таким способом, но за приличные таньга.
Проблема только в том, что если не удастся отправить своевременно короткие сообщения именно этим нескольким конкретным получателям, то "Мегафон" в нашей области может сдохнуть через несколько часов после наступления необходимости в такой отправке - диспетчер энергосистемы должен таким способом проинформировать начальство о серьезных сбоях вроде взрыва Фукусимы или пожаре на входном городском трансформаторе.
Тем не менее, такая общественно-полезная рассылка меньше чем на десяток корпоративных номеров всё равно осталась платной услугой, и мы решили её не покупать.
Вместо этого было решено воспользоваться возможностью, которую предоставляет postfix - пересылкой входящих писем не только на другие адреса, но так же и в файлы и в конвейер для какой-нибудь команды.
Полученное таким образом сообщение можно будет обработать каким-нибудь парсером и, например, превратить в несколько сообщений, по одному на каждый мегафоновский псевдо-адрес.
Очевидно, решение простое:
1) прописываем в
/etc/aliases
псевдонимы либо для файла:
псевдоним: "полный путь к файлу"
robot: "/tmp/robomail"
либо для команды:
псевдоним: "|полный путь к команде"
bobot: "|/usr/local/sbin/mailtest.sh"
2) разрешаем постфиксу отправлять почту в файлы и командам:
[postfix/conf/main.cf]
# разрешаем отправлять почту только на команды и файлы, описанные псевдонимами
allow_mail_to_files=alias
allow_mail_to_commands=alias
recipient_delimiter = +
3) запускаем newaliases для обновления хэшированной таблицы псевдонимов и делаем postfix reload.
И радуемся жизни. Так просто? А вот хрен там!
NB! Дальше после всех манипуляций с zmprov обязательно выполнятьzmmtactl restart
, чтобы обновить настройки агента доставки сообщений в конфигах.
Там, где действия надо выполнять от имени пользователя zimbra, я явно указываюsudo su - zimbra
.
Разумеется, никто не запрещает открыть несколько сеансов от разных пользователей и переключаться между ними. Я всё это вообще проделывал в одном сеансе, открыв в byobu/tmux несколько "окон" - от имени зимбры, от своего имени и от рута.
Начнем с того, что вписать последний параметр в main.cf не получилось - после перезапуска всей зимбры или хотя бы zmmtactl restart знак "+" исчезал. Вот просто брал и исчезал, словно я его и не ставил.
Чтобы он не исчезал, надо внести изменения в конфигурацию зимбры:
$ sudo su - zimbra
$ zmprov mcf zimbraMtaRecipientDelimiter +
Теперь он будет появляться в нужной строке даже если его убрать. Сам по себе этот параметр не особенно критичен для моей задачи, но пусть будет.
Готово? Нет, не готово: postfix продолжает ругаться на неправильное имя получателя что для робота, что для бобота. Копаем дальше.
Во-первых, находим в master.cf.in (именно cf.in, а не просто .cf - в .in файлах зимбра хранит шаблоны, из которых при каждом запуске формирует настоящие файлы. То есть, если внести изменения в master.cf, то они исчезнут при перезапуске зимбры) ищем строки:
-o mynetworks_style=host
-o mynetworks=127.0.0.0/8,[::1]/128
Во всяком случае, у меня они выглядели именно так. Меняем их:
# -o mynetworks_style=host
-o mynetworks=127.0.0.0/8,IP-вашего-почтового-сервера/32,[::1]/128
То есть, указали, что список "мои сети" это именно список сетей, а не узлов, и добавили в этот список сеть из одного узла - почтового сервера. Я не очень понимаю, зачем это надо, но у меня без этого не заработало.
Ну что, поехали? Нет, не поехали. Осталось еще немного поплясать с бубном. Ну, или дать в бубен разработчикам зимбры за то, что не предусмотрели более удобного способа для таких настроек.
$ sudo su - zimbra
$ zmprov gacf|grep zimbraMtaM
zimbraMtaMaxMessageSize: 10485760
zimbraMtaMyDestination: localhost
Я ленив, и предпочитаю, чтобы комп искал нужное мне, поэтому выдалось две настройки - максимальный размер сообщения (настраивается через GUI, аналог
main.cf://message_size_limit
) и аналог параметра main.cf://MyDestination
(в файле /opt/zimbra/conf/zmconfigd.cf
есть полный список соответствия параметров конфигурации зимбры и параметров отдельных ее составляющих, например, того же постфикса, желающие могут посмотреть)Вот последний параметр нам надо изменить, добавив в него FQDN нашего сервера. Может прокатит и с не нашим - не проверял.
$ sudo su - zimbra
$ zmprov mcf zimbraMtaMyDestination "FQDN.вашего.сервера.ru localhost"
$ zmprov gacf|grep zimbraMtaM
zimbraMtaMaxMessageSize: 10485760
zimbraMtaMyDestination: FQDN.вашего.сервера.ru localhost
(в некоторых источниках, например http://forums.zimbra.com/administrators/9986-urgent-etc-alias-configuration-after-upgrade.html рекомендуют вместо FQDN писать просто слово LOCAL:
$ sudo su - zimbra
$ zmprov mcf zimbraMtaMyDestination "LOCAL localhost"
Но у меня это не сработало.)
А вот теперь можно проверять...
(протоколы ручного SMTP, содержимое логов и доставленных сообщений приведено частично, только моменты, необходимые для объяснений)
telnet мой-сервер 25
...
mail from:tester
250 2.1.0 Ok #у меня разрешен из локалки прием почти от не FQ имен
rcpt to: robot
504 5.5.2 <robot>: Recipient address rejected: need fully-qualified address
rcpt to: bobot
504 5.5.2 <bobot>: Recipient address rejected: need fully-qualified address
# опаньки! а где ж взять FQA для этих алиасов? попробуем указать наш домен
rcpt to:robot@мой-домен
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as 84A2F921A3A
Уфф, заработало! Эй, а почему файл не создался?
$ grep robot /var/log/mail.log|tail
...
...postfix/error[7844]: 41DCA921A3A: to=<robot@мой-домен>, relay=none, delay=0.05, delays=0.01/0.03/0/0.01, dsn=5.0.0, status=bounced (мой-домен)
Печально: сообщение отброшено, поскольку в мой-домен и в самом деле нет такого пользователя. А вот теперь вернемся немного назад и вспомним, что выше настраивали параметр
zimbraMtaMyDestination
. А что, если...Снова телнет до сервера, повторяем то же самое, но в качестве адресов получателей пишем:
rcpt to: robot@FQDN-моего-сервера
250 2.1.5 Ok
rcpt to: bobot@FQDN-моего-сервера
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test robot-bobot
.
250 2.0.0 Ok: queued as A1790922241
$ grep -E "robot|bobot" /var/log/mail.log|tail
...
...postfix/smtp[24605]: A1790922241: to=<bobot@FQDN-моего-сервера>, relay=127.0.0.1[127.0.0.1]:10026, delay=44, delays=43/0/0.01/0.16, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10030): 250 2.0.0 Ok: queued as E862F922246)
postfix/smtp[24605]: A1790922241: to=<robot@FQDN-моего-сервера>, relay=127.0.0.1[127.0.0.1]:10026, delay=44, delays=43/0/0.01/0.16, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10030): 250 2.0.0 Ok: queued as E862F922246)
postfix/smtp[19265]: E862F922246: to=<bobot@FQDN-моего-сервера>, relay=127.0.0.1[127.0.0.1]:10032, delay=0.26, delays=0.05/0/0/0.21, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 2D2B7922241)
postfix/smtp[19265]: E862F922246: to=<robot@FQDN-моего-сервера>, relay=127.0.0.1[127.0.0.1]:10032, delay=0.26, delays=0.05/0/0/0.21, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 2D2B7922241)
...
postfix/local[29251]: 2F2049226EF: to=<robot@FQDN-моего-сервера>, relay=local, delay=0.09, delays=0.01/0.05/0/0.03, dsn=2.0.0, status=sent (delivered to file: /tmp/robomail)
postfix/local[29250]: 2F2049226EF: to=<bobot@FQDN-моего-сервера>, relay=local, delay=0.09, delays=0.01/0.05/0/0.03, dsn=2.0.0, status=sent (delivered to command: /usr/local/sbin/mailtest.sh)
Видно, что оба файла - собственно файл-получатель и результат работы команды-получателя - содержат одно и то же.
$ cat /usr/local/sbin/mailtest.sh
#!/bin/sh
# Этот скрипт выполняется при отправке сообщения на bobot@FQDN-моего-сервера
# Для проверки работоспособности просто сохраняем переданный stdin в файл
tee /tmp/testmail.log
exit 0
$ cat /tmp/robomail
...
X-Original-To: robot@FQDN-моего-сервера
Delivered-To: robot@FQDN-моего-сервера
...
Received: ... with SMTP id A1790922241;
...
From: tester@FQDN-моего-сервера
test robot-bobot
$ cat /tmp/testmail.log
...
X-Original-To: bobot@FQDN-моего-сервера
Delivered-To: bobot@FQDN-моего-сервера
...
Received: ... with SMTP id A1790922241;
...
From: tester@FQDN-моего-сервера
test robot-bobot
Отличие между командой и файлом в том, что команде передается одно конкретное сообщение, тогда как сообщения, предназначенные для файла-получателя, дописываются в конец и файл может неконтролируемо расти, если не предусмотреть средств его очистки.Вот теперь всё. Остальное - парсинг полученных файлов и их дальнейшая обработка - выходят за рамки данной статьи, интересующиеся могут продолжить изыскания.
Дополнительные материалы:
Обработка входящей почты на PHP
http://habrahabr.ru/post/126448/
Postfix Configuration Parameters
Postfix main.cf file format http://www.postfix.org/postconf.5.html#mydestination
Комментариев нет:
Отправить комментарий
Пожалуйста, воздержитесь от грубостей и персональных нападок.
Я не против матерщины, но она должна быть уместной и использоваться для выражения эмоций, а не в качестве основного средства выражения мыслей.