Thank you for reading this post, don't forget to subscribe!
Конфигурация Postfix
В файле master.cf описаны сервисы принимающие участие в доставке сообщений. Создадим свой сервис myhook и прицепим к нему наш скрипт postfix.php
1 2 |
myhook unix - n n - - pipe flags=F user=www-data argv=/path/to/postfix.php ${sender} ${size} ${recipient} |
Теперь принимающему сервису smtp нужно объяснить, чтоб всю входящюю почту он пропускал через наш скрипт postfix.php
1 2 |
smtp inet n - - - - smtpd -o content_filter=myhook:dummy |
Если есть необходимость фильтровать почту с localhost’а, то вышесказанное необходимо сделать и для сервиса pickup
1 2 |
pickup fifo n - - 60 1 pickup -o content_filter=myhook:dummy |
После внесения изменений перечитаем конфиги postfix’а
1 |
postfix reload |
Фильтр
В папке /path/to/ создадим файл postfix.php и дадим ему права 755 (исполняемый для всех, изменения только владельцу)
1 2 |
touch postfix.php chmod 755 postfix.php |
Данный скрипт должен записать строку «Script successfully ran at ….» в файл postfixtest. Предполагается, что /usr/bin/php — это путь к PHP CLI
1 2 3 4 5 6 |
#!/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
1 2 |
su www-data ./postfix.php |
Если в postfixtest появилась строка «Script successfully ran at ….», тогда пробуем слать почту. Почту адресат не получит, но на данном этапе важно добиться, чтоб отработал postfix.php. В любом случае смотрим логи /var/log/mail.log
Теперь слегка усложним наш скрипт. В результате входящее сообщение оказывается в файле postfixtest и с его содержимым можно работать
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#!/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 и напишем следующее
1 |
me@mydomain.tld FILTER myhook:dummy |
Создаем хешированый файл access. На выходе получаем access.db с которым и будет работать postfix
1 |
/etc/postfix/postmap access |
И последний штрих в main.cf. В директиве smtpd_recipient_restrictions (если нет, то создать) указываем postfix’у пропускать все входящие через access. И если в заголовке To: будет найден me@mydomain.tld, то прогнать его через фильтр myhook:dummy
1 2 3 4 |
smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/access, permit_mynetworks, reject_unauth_destination |
Перечитать конфиги
1 |
postfix reload |
Procmail
Procmail читает из своего стандартного входа. Он проверяет конфигурационный файл .procmailrc, который должен находиться в каталоге HOME пользователя (procmail не работает в виртуальными пользователями). В этом файле определяются некоторые правила, которые указывают procmail, какие действия надо предпринять после получения сообщения
В контексте данного поста все письма приходящие на me@mydomain.tld складываются в один файл mbox для дальнейшей обработки
1 2 3 4 5 6 7 8 9 |
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 в котором должна быть строка
1 2 |
mailbox_command = /usr/bin/procmail -a "$EXTENSION" DEFAULT=/home/$USER/Maildir/ |
Перечитать конфиги
1 |
postfix reload |