Postfix. Фильтрация входящих сообщений

Фильтрация входящих сообщений — на самом деле не такая уж нестандартная задача. Вопрос в том какими инструментами воспользоваться. В этом посте будут рассмотрены два решения при помощи php и procmail. Оба ПО доступны в любом дистрибутиве unix. Вопрос целесообразности установки php только ради фильтрации сообщений не рассматривается. Решение принимает администратор конкретной системы. Предлагаемые варианты являются лишь кирпичиками в построении системы фильтрации

PHP

Конфигурация Postfix

В файле master.cf описаны сервисы принимающие участие в доставке сообщений. Создадим свой сервис myhook и прицепим к нему наш скрипт postfix.php

myhook unix - n n - - pipe
 flags=F user=www-data argv=/path/to/postfix.php ${sender} ${size} ${recipient}

Теперь принимающему сервису smtp нужно объяснить, чтоб всю входящюю почту он пропускал через наш скрипт postfix.php

smtp inet n - - - - smtpd
 -o content_filter=myhook:dummy

Если есть необходимость фильтровать почту с localhost’а, то вышесказанное необходимо сделать и для сервиса pickup

pickup fifo n - - 60 1 pickup
 -o content_filter=myhook:dummy

После внесения изменений перечитаем конфиги postfix’а

postfix reload

Фильтр

В папке /path/to/ создадим файл postfix.php и дадим ему права 755 (исполняемый для всех, изменения только владельцу)

touch postfix.php
chmod 755 postfix.php

Данный скрипт должен записать строку «Script successfully ran at ….» в файл postfixtest. Предполагается, что /usr/bin/php — это путь к PHP CLI

#!/usr/bin/php
<?php
$file = fopen("/tmp/postfixtest", "a");
fwrite($file, "Script successfully ran at ".date("Y-m-d H:i:s")."n");
fclose($file);
?>

Тестовый запуск с правами пользователя www-data

su www-data
./postfix.php

Если в postfixtest появилась строка «Script successfully ran at ….», тогда пробуем слать почту. Почту адресат не получит, но на данном этапе важно добиться, чтоб отработал postfix.php. В любом случае смотрим логи /var/log/mail.log

Теперь слегка усложним наш скрипт. В результате входящее сообщение оказывается в файле postfixtest и с его содержимым можно работать

#!/usr/bin/php
<?php
$file = fopen("/tmp/postfixtest", "a");
fwrite($file, "Script successfully ran at ".date("Y-m-d H:i:s")."n");

// read from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
$line = fread($fd, 1024);
$email .= $line;
}
fclose($fd);

fwrite($file, $email);
fclose($file);

?>

И что дальше?

Понятно, что исходя из текущих настроек postfix’а данный скрипт отрабатывает всегда, независимо от того, кто будет получателем, даже если получателя не сущетвует. Это хорошо для академического примера, но абсолютно не приемлимо для продакшена

Фильтруем конкретного пользователя

Вот более реальный пример: фильтровать входящие для получателя me@mydomain.tld и пропускать остальных. Для этого создадим файл access и напишем следующее

me@mydomain.tld FILTER myhook:dummy

Создаем хешированый файл access. На выходе получаем access.db с которым и будет работать postfix

/etc/postfix/postmap access

И последний штрих в main.cf. В директиве smtpd_recipient_restrictions (если нет, то создать) указываем postfix’у пропускать все входящие через access. И если в заголовке To: будет найден me@mydomain.tld, то прогнать его через фильтр myhook:dummy

smtpd_recipient_restrictions = 
 check_recipient_access hash:/etc/postfix/access,
 permit_mynetworks,
 reject_unauth_destination

Перечитать конфиги

postfix reload

Procmail

Procmail читает из своего стандартного входа. Он проверяет конфигурационный файл .procmailrc, который должен находиться в каталоге HOME пользователя (procmail не работает в виртуальными пользователями). В этом файле определяются некоторые правила, которые указывают procmail, какие действия надо предпринять после получения сообщения

В контексте данного поста все письма приходящие на me@mydomain.tld складываются в один файл mbox для дальнейшей обработки

LOGFILE=$HOME/log/procmail.log
VERBOSE=NO
SHELL=/bin/sh
PATH=/bin:/usr/bin:/usr/sbin

:0 h
* ^To.*me@mydomain.tld$
mbox

Подключение procmail к postfix

В случае с php нужно было редактировать master.cf и main.cf. В случае с procmail изменениям подвергается лишь main.cf  в котором должна быть строка

mailbox_command = /usr/bin/procmail -a "$EXTENSION" DEFAULT=/home/$USER/Maildir/

Перечитать конфиги

postfix reload

Александр Черных
системный администратор

Статьи по теме

0