
У нас есть регулярное выражение header_checks, переданное процессу «очистки», но оно не обрабатывает заголовок как единый заголовок, если он находится в нескольких строках.
header_check (передача значения заголовка в FILTER):
/^X-OurHeader:\s+(.*?)/ FILTER $1
мастер.cf:
cleanup_service. unix n - y - 0 cleanup
-o header_checks=regexp:/etc/postfix/header_check
Пример многострочного заголовка, где происходит сбой:
X-OurHeader: a_special_filter_command:my.sub.domain
b.mail.whatever.com
Исходный полный заголовок до разбиения на несколько строк выглядит так:
X-OurHeader: a_special_filter_command:my.sub.domainb.mail.whatever.com
Результат, переданный в FILTER, будет следующим: a_special_filter_command:my.sub.domain
и отсутствует оставшееся имя хоста во второй строке b.mailwhatever.com
.
Если я изменю header_check на это, то он будет захватывать следующую строку:
/^X-OurHeader:\s+([\s\S]*)/ FILTER $1
Группа захвата $1 затем содержит вторую строку, но в захваченном тексте все еще есть пробел (и, предположительно, новая строка), так что это не работает. Это выглядит так:
X-OurHeader: a_special_filter_command:my.sub.domain b.mail.whatever.com
Просматривая логи при первом подходе, мы видим
postfix/cleanup[123456]: 27429A1FE8: filter: header X-OurHeader: a_special_filter_command:my.sub.domain? b.mail.whatever.com
Есть ли альтернативный подход, который кто-нибудь мог бы предложить? Конечная цель заключается в том, что мы помечаем заголовок специальными значениями cmd:hostname, которые необходимо отправить в FILTER, но хотим поддержать разбиение значения hdr на несколько строк для длинного заголовка, чтобы соответствовать стандарту «длина ДОЛЖНА быть < 78».
решение1
Если вы знаете или можете гарантировать, что существует только определенное количество вариаций, добавьте дополнительные выражения, чтобы отлавливать их по отдельности /..:(.*) (.*)$/ -> /..:$1$2/
— постфикс продолжит со следующего выражения, если пробела нет, поэтому сохраняйте простоту шаблонов, помещая сложное совпадение первым.
Если нет, но все еще в пределах возможностей регулярных выражений, возможно, есть способцепочка множественных поисков. Я не могу собрать все воедино, но если это доступно в вашем дистрибутиве и вообще работает, документация должна быть полезна, начните с руководства header_checks
и DATABASE_README
файла.
pipemap:{pcre:/extract/category.pcre,pcre:/map/category/to/filter/command.pcre}
Основная идея: сначала получите общее направление (например, MYFILTER: $1
), и только затем вносите необходимые изменения, чтобы сделать его допустимой постфиксной командой, тщательно следя за тем, чтобы все входные данные приводили к допустимому выводу ( MYFILTER: (valid1|valid2) -> FILTER host:port
плюс резервная строка MYFILTER:
-> FILTER: default:port
).
Если это не удается, то обычно, когда вам нужно сделать что-то слишком мощное для регулярных выражений и header_checks, вы переходите к полноте по Тьюрингу:
Достаточно динамичный поиск. Например, если вам нравится SQL, это должно дать вам что-то не настолько менее читаемое/поддерживаемое. Остерегайтесь непреднамеренных логических результатов от множественных поисков
header_checks = sqlite:/path/to/definition.conf pcre:/remaining/simpler/rules.pcre
Демон milter/policy. Они могут даже вызывать внешние двоичные файлы, вообще не перенаправляя сообщение. В зависимости от интерфейса вашей текущей идеи следующего FILTER в очереди, это может быть более или менее удобно.
Я также считаю, что есть способы заставить постфикс работать правильнотранспортданное сообщение через несколько экземпляров header_checks, если это необходимо, но я бы не рекомендовал этот маршрут, он не очень хорошо сочетается с другими (более или менее динамичными) решениями по маршрутизации.