Регистрация...

Eserv Forum / E3 / Eserv 3 Mail Server Support / Встроить в очередь обработки почты вызов внешнего приложения

recent wikipost // (v7)
Продукты и услуги Скачать Документация Купить Поддержка Форумы Партнёрам Статьи О компании
Новости
12.10.2009
Переезд завершен
Требуется: встроить в очередь обработки почты запуск внешнего приложения с параметрами. Т.е. как "почтовый робот", но в самом конце, когда уже произведены все возможные проверки типа на спам и вирус. Прямо перед тем, как положить письмо в ящик пользователю, надо письмо отдать ещё на одну проверочку при помощи самописанной программы. Задача навязана "сверху" и отказаться не могу.
Смысл дополнительной проверки вкратце таков: по почте постоянно долбят эксплойтами определённый круг лиц. Антиспам (Popfile) на это дело реагирует даже более успешно чем антивирусы. А защищать юзеров как-то надо. Посовещавшись решили пойти по такому пути: выдёргиваем письмо в конце всех фильтров Eserv-а и отдаём внешней программе. Прога проверяет заголовки письма — ну там IP-шники источника и др. (я не уведомлён о подробностях). В случае определения подозрительности письма — письмо упаковывается ещё в один контейнер с текстом о потенциальной угрозе и возвращается назад в поток фильтров Eserv-а (это в идеале). А Eserv уже заканчивает всё это покладанием в целевой ящик.
По факту нам сейчас доступно просто выдёргивание письма из потока через "почтовый робот". Т.е. вместо каждого из конкретных получателей прописан робот с одной и той-же строкой запуска внешней программы. А поскольку никаких записей от антиспама и др. в таком письме нет, то программа после обработки просто кладёт "проверенное" письмо в Inbox-папку юзеру.
В идеале я представляю это так: есть текстовый файл-список с eMail-адресами в локальных доменах. Тоссер в конце очереди штатных фильтров заглядывет в этот список и при совпадении адреса запускает внешнее приложение типа
"cmd.exe /c ..\robots\SendTest.bat {ROBOTFILENAME} {MAILFROM} {RCPTTO}"...
Возможно даже, дабы обойтись одним файлом-списком для этого дела, строку-команду можно вписывать в этот-же файл каждому адресату построчно. (ну мало-ли — вдруг для разных получателей разные проверки придумают делать).
Соответственно и понимание адреса проверки должно подразумевать множественность, т.е. user12@mydomen.ru и user1*@mydomen.* обрабатываются одинаково. Во всяком случае имеющийся "почтовый робот" это понимает. НО! "почтовые роботы" у нас используются весьма и весьма для разного и не хочется случайно наступить на грабли случайного пересечения адресов для разных задач...
 
Комментарии к версии 1 (30.04.2013 05:18) [~pavlad] eaa51ca4
Комментарии к версии 2 (30.04.2013 05:23) [~pavlad] 12f91c0f
Комментарии к версии 3 (30.04.2013 05:25) [~pavlad] 63a4e414
Комментарии к версии 4 (30.04.2013 05:52) [~pavlad] dd64cdd3
Комментарии к версии 5 (30.04.2013 05:53) [~pavlad] f384cbce
Комментарии к версии 6 (30.04.2013 05:56) [~pavlad] bb8b7770
Комментарии к этой версии (30.04.2013 06:02) [~pavlad] bd8f44f7
АвторДатаТекстtags
ac30.04.2013 09:00
Если непосредственно перед доставкой, то вызов робота должен быть в acSMTP\conf\smtp\Delivery.rules.txt , но там как раз "штатные" роботы и вызываются, с выбором по RCPTTO
RCPTTO SMTP[ToEmailRobots] IsInFile | EvalRules: smtp\delivery\RunRobot | \EOF

pavlad пишет: Тоссер в конце очереди штатных фильтров заглядывет в этот список и при совпадении адреса запускает внешнее приложение

И как раз так он и работает, если под совпадением адреса имеется в виду совпадение адреса получателя (RCPTTO).

Если нужен отдельный дополнительный список, то добавьте туда аналогичную строку со ссылкой на другой файл...
wikipost
pavlad02.05.2013 12:10
Т.е. в acSMTP\conf\smtp\Delivery.rules.txt дублирую строчку про робота, например так:

RCPTTO SMTP[ToEmailRobots2] IsInFile | EvalRules: smtp\delivery\RunRobot | \EOF

И помещаю её следом за оригинальной
А в \CONF\lists\smtp\ делаю файл ToEmailRobots2.txt по образцу ToEmailRobots.txt (список естественно другой)

Получаем: если адресат попадает в список ToEmailRobots.txt (стандартный робот), то правило "штатного" робота срабатывает.
Если адрес получателя не попадает в список ToEmailRobots.txt, то письмо остаётся в Spool и далее вообще ничего не происходит.

Похоже что-то ещё надо править.
wikipost
pig03.05.2013 09:34
А параметр ToEmailRobots2 в Eserv3.ini создали? Хотя при таких правках можно с параметрами не заморачиваться, а прямо путь к файлу списка указывать.
wikipost
pavlad07.05.2013 07:43
Однозначно возвращаемся к первоначальному формулированию моей проблемы: "...как почтовый робот...". Т.е. нужно организовать вызов через "cmd.exe /c .."
Но это должен быть НЕ "почтовый робот" и не его клон. Т.к. (как я уже об этом писал) при попадании в робота — письмо лишается части служебных полей (например X-Spam-Status), не сохраняется в архив штатным образом, при использовании символа * в имени робота не производится валидация наличия локального ящика. Письмо просто вырезается из очереди, будто его и не было.
Требуется сделать дополнительную обработку внешней программой именно по окончании всех обработок собственно почтовым сервером. Т.е. непосредственно перед покладанием в ящик к юзеру. После всех проверок и фильтров Eserv. В идеале конечно чтобы только приходящую снаружи так проверять. Т.е. сразу исключать FromLocalUsers.
wikipost
ac07.05.2013 11:23
Письмо не лишается этих полей при передаче роботу, оно просто еще на тот момент не записывалось никуда с этими полями (всё время до конечной доставки эти поля являются просто переменными в программе — они доступны для обработчиков в правилах, но не для внешних программ, имеющих дело с файлами). Можно перед передачей письма роботу промежуточно записать его в файл в том же виде, в котором оно пойдёт на доставку (в INBOX) — с помощью команды CopyFileWithRcptsTo:. Примеры см. в acSMTP\conf\smtp\delivery\Local.rules.txt , где собственно и выполняется финальная локальная доставка.

pavlad пишет: В идеале конечно чтобы только приходящую снаружи так проверять.
Локальность отправителя можно проверять командой IsLanClient, пример см. в HELO.rules.txt.
wikipost
pig07.05.2013 15:14
Дурацкий вопрос: это внешнее приложение самописное? Если да, то можно посмотреть в сторону MContent на предмет втаскивания алгоритма в него.
wikipost
pavlad08.05.2013 11:30
Приложение-то самописное, да вот алгоритм мне отказываются сообщать. Не положено-с... Вот такой чёрный ящик, на вход письмо и на выходе типа оно-же, но иногда с правкой. Всё — что от меня (от сервера) требуется — это указать физическое месторасположение файла для проверки и куда положить после оной.
wikipost
pig08.05.2013 14:57
Если получатели таких писем только локальные, то можно встроиться в правило conf\smtp\delivery\Local.rules.txt — примерно так:
" {FIELD3 S@}\{RCPTTO GetUserFromEmail}\INBOX\{FMAILFROM}!{RANDOM-ID}.eml" DUP STR@ CopyFileWithCurrentRcptTo RCPTTO ..\CONF\lists\smtp\SpecialRcpts.txt IsInFile | DUP STR@ 2DUP "{''}путь\к\приложению{''} {''}{s}{''} {''}{s}{''}" DUP STR@ StartAppWait DROP STRFREE STRFREE SMTP[ArchiveLocalMail] >FLAG | CopyFileWithCurrentRcptTo: "{SMTP[ArchiveDir]}\{FMAILFROM}!{CurrentThreadNumber}!{uMCNT @}.eml" EvalRules: smtp\delivery\Robots RCPTTO DelRcpt

В этом коде ковыряется копия, положенная в почтовый ящик адресата, архивная копия, если делается, то без ковыряния. И ещё предполагается, что приложение умеет перезаписывать исходный файл. Иначе придётся два имени генерировать.
wikipost
pavlad13.05.2013 12:41
pig пишет: путь\к\приложению

это например ..\robots\ или ..\robots\test.exe или e:\eserv3\robots\ ?

А если без указания собственно исполняемого файла, то где тогда его указывать. И в каком месте передаются параметры для работы? Пока-что цепочка обработки упорно заканчивается покладанием в Spool.

Формат SpecialRcpts.txt я так понимаю просто список eMail получателей?
wikipost
pig13.05.2013 14:07
ред: 13.05.2013 14:08
pavlad пишет: Формат SpecialRcpts.txt я так понимаю просто список eMail получателей?

Да.

pavlad пишет: А если без указания собственно исполняемого файла

А как без него? Тут должна быть правильная командная строка запуска приложения, с ключами, если нужны, с правильным позиционированием входного и выходного путей. И с правильным путём к EXE того приложения, которое надо вызвать. Или оно как-то совсем экзотически запускается?

pavlad пишет: Пока-что цепочка обработки упорно заканчивается покладанием в Spool.

Это в каком варианте конфига?

Я выше не уточнил: приведённый кусок кода встраивается в ELSE-часть файла правила, после строки вызова MContent и вместо всего, что далее следует до [THEN]
wikipost
pavlad14.05.2013 04:34
ред: 14.05.2013 04:38
pig пишет: Я выше не уточнил: приведённый кусок кода встраивается в ELSE-часть...

Т.е. у меня этот фрагмент выглядит так:
[ELSE]
    \ Если используется MContentEx, то выполняем его обработчик
    SMTP[UseMcontent] >FLAG | MContent[Pass2] >FLAG | EvalRules: smtp\delivery\Local.MContent \EOF

    CopyFileWithCurrentRcptTo:"{FIELD3 S@}\{RCPTTO GetUserFromEmail}\INBOX\{FMAILFROM}!{RANDOM-ID}.eml" DUP STR@ CopyFileWithCurrentRcptTo
    RCPTTO ..\CONF\lists\smtp\SpecialRcpts.txt IsInFile
| DUP STR@ 2DUP "{}..\robots\TestRobot.cmd {} {}{s}{} {}{s}{}" DUP STR@ StartAppWait DROP STRFREE
    STRFREE
    SMTP[ArchiveLocalMail] >FLAG | CopyFileWithCurrentRcptTo: "{SMTP[ArchiveDir]}\{FMAILFROM}!{CurrentThreadNumber}!{uMCNT @}.eml"
    EvalRules: smtp\delivery\Robots
    RCPTTO DelRcpt
[THEN]
wikipost
pavlad14.05.2013 04:45
pavlad пишет: Пока-что цепочка обработки упорно заканчивается покладанием в Spool.

Хотя неправ несколько — если адрес попадает в робота, то письмо нормально перемещается в temp для отдачи роботу.
wikipost
pig14.05.2013 06:41
ред: 14.05.2013 06:47
pavlad пишет: CopyFileWithCurrentRcptTo:

Этого слова я не писал.

Если надо запускать батник, то это делается по-другому: cmd.exe /c ..\robots\TestRobot.cmd ... и так далее
А в батник имя файла можно и один раз передать, коли на то пошло. Там внутри параметры можно как угодно тасовать, хоть десять раз %1 написать.

Кстати, совсем по уму строка должна выглядеть примерно так:
RCPTTO IsInFile: ..\CONF\lists\smtp\SpecialRcpts.txt | DUP STR@ MakeFullName "..\robots\TestRobot.cmd {''}{s}{''}" DUP STR@ StartAppWait DROP STRFREE

Честнее не относительный, а полный путь отдавать приложению. И имя файла списка я неверно там поставил, на нём всё должно было ломаться.
wikipost
pavlad14.05.2013 09:44
ред: 14.05.2013 09:57
pig пишет: pavlad пишет: CopyFileWithCurrentRcptTo:
Этого слова я не писал.
Ну это я получилось домыслил неправильно.

Итого получился работающий фрагмент таков:
[ELSE]
    \ Если используется MContentEx, то выполняем его обработчик
    SMTP[UseMcontent] >FLAG | MContent[Pass2] >FLAG | EvalRules: smtp\delivery\Local.MContent \EOF

" {FIELD3 S@}{RCPTTO GetUserFromEmail}\INBOX\{FMAILFROM}!{RANDOM-ID}.eml" DUP STR@ CopyFileWithCurrentRcptTo
RCPTTO IsInFile: ..\CONF\lists\smtp\SpecialRcpts.txt
| DUP STR@ MakeFullName "..\robots\TestRobot.cmd {}{s}{}" DUP STR@ StartAppWait DROP STRFREE
    STRFREE
    SMTP[ArchiveLocalMail] >FLAG | CopyFileWithCurrentRcptTo: "{SMTP[ArchiveDir]}\{FMAILFROM}!{CurrentThreadNumber}!{uMCNT @}.eml"
    EvalRules: smtp\delivery\Robots
    RCPTTO DelRcpt
[THEN]


Из строчки с ..." {FIELD3 S@}\{RCPTTO... убрал \ , а то в итоговом имени выводится двойной.

Сейчас вроде всё работает почти как надо — роботы сами по себе, вызов дополнительной обработки сам по себе. А "почти" — это потому, что фильтр обходится спамными письмами. Т.е. если X-Spam-Status: Yes..., то письмо до этого правила не доходит.
wikipost
pig14.05.2013 11:33
Спамные тоже надо ковырять? Тогда аналогично придётся. IF-часть:
"{FIELD3 S@}\{RCPTTO GetUserFromEmail}\spam\" STR@ IsDirectory SMTP[AutoCreateSpamFolders] >FLAG OR [IF] " {FIELD3 S@}\{RCPTTO GetUserFromEmail}\spam\{FMAILFROM}!{RANDOM-ID}.eml" [ELSE] " {FIELD3 S@}\{RCPTTO GetUserFromEmail}\INBOX\{FMAILFROM}!{RANDOM-ID}.eml" [THEN] DUP STR@ CopyFileWithCurrentRcptTo RCPTTO IsInFile: ..\CONF\lists\smtp\SpecialRcpts.txt | DUP STR@ MakeFullName "..\robots\TestRobot.cmd {''}{s}{''}" DUP STR@ StartAppWait DROP STRFREE STRFREE EvalRules: smtp\delivery\SpamRobots RCPTTO DelRcpt
wikipost
pavlad15.05.2013 06:09
ред: 15.05.2013 06:22
Огромное спасибо за помощь. Доп.фильтрация работает практически как задумывалось. Вроде ничего не теряется и не зависает.
Но обнаружилось ещё одна небольшая неувязочка: "указание" на обработку письма выдаётся внешнему обработчику когда оно лежит уже в ящике юзера. В отличие от обработчика роботов, где письмо отдаётся в {Dirs[Temp]}.
Т.е. чисто технически возможна ситуация когда письмо покладено в папку юзеру — начинается процесс анализа внешней программой — и в этот-же момент идёт запрос от клиента. Что будет с письмом? Eserv отдаст письмо юзеру или заблокирует до окончания списка Local.rules? У заказчика данной доработки есть определённые сомнения.
wikipost
ac15.05.2013 12:18
Если внешний робот открывает файл не в монопольном, а shared-режиме, то Eserv не заметит, что файл еще кем-то используется, и нормально отдаст клиенту. Если файл при обработке блокируется, то соответственно это письмо Eserv выдать не сможет. Дожидаться разблокировки не будет, просто пропустит его обработку.
wikipost
Работает на Eserv/5.05567 (10.02.2020)