我们有一个 header_checks 正则表达式传递给“清理”过程,但如果标题有多行,它就不会将其作为单个标题进行处理。
header_check(将 header 的值传递给 FILTER):
/^X-OurHeader:\s+(.*?)/ FILTER $1
master.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
是否有人会建议采用其他方法?最终目标是我们用需要发送到 FILTER 的特殊 cmd:hostname 值标记标头,但希望支持将 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 的多个实例来检查给定的消息,但我不推荐那种路由,因为它不能很好地与其他(或多或少动态的)路由决策混合。