如何配置Exim仅对入站邮件执行SpamAssassin扫描?
问题分析与解决
思路正确性
你的思路是正确的:通过区分入站/出站邮件,或者识别邮件列表发出的邮件来跳过SpamAssassin扫描,既避免了邮件列表群发时重复扫描的资源浪费,又能通过SPF验证拦截伪造Return-Path的垃圾邮件,方向没问题。
两个尝试的问题解析
1. eq{$received_protocol}{SMTP}无效的原因
Exim中,本地邮件列表软件发出的邮件也可能使用SMTP协议(比如通过本地SMTP端口提交),仅靠received_protocol为SMTP无法区分外部入站邮件和本地出站邮件。正确的区分逻辑应该结合邮件来源:
- 外部入站邮件:
sender_host_address是外部IP,非本地地址(127.0.0.1/::1/内部网段) - 本地出站邮件:
sender_host_address为本地地址,或received_protocol为local(若邮件列表通过sendmail命令直接提交)
2. Return-Path条件写法的问题
你的条件存在三个关键错误:
- 变量引用错误:
header_return_path:是错误的变量名,Return-Path属于信封发件人,并非邮件头字段,应该使用Exim内置变量$return_path获取。 - 存在性判断语法错误:判断变量是否存在的正确写法是
def:return_path,不需要末尾的冒号。 - 正则匹配冗余:
^.*@list\.example\.com$可以简化为@list\.example\.com$,只需匹配域名后缀即可,无需额外匹配前缀内容。
修正后的条件写法:
accept condition = ${if match{$return_path}{\N@list\.example\.com$\N}{1}{0}}
推荐的完整配置调整
在所有SpamAssassin相关规则最前面添加以下规则,直接跳过邮件列表发出的邮件扫描:
# 跳过邮件列表发出的邮件的SpamAssassin检查 accept condition = ${if match{$return_path}{\N@list\.example\.com$\N}{1}{0}} # 以下是原有的SpamAssassin规则... # Bypass SpamAssassin checks if the message is too large (4 million). warn condition = ${if >={$message_size}{4000000}{1}} add_header = X-Spam-Note: SpamAssassin run bypassed due to message size add_header = Subject: [L] $h_Subject: # ...后续原有规则保持不变
如果你想基于邮件来源区分入站/出站,也可以用以下规则替代上述accept规则,仅对外部入站邮件执行扫描:
# 仅对外部入站邮件执行SpamAssassin扫描,跳过本地/内部邮件 accept condition = ${if eq{$sender_host_address}{127.0.0.1}{1}{0}} accept condition = ${if eq{$sender_host_address}{::1}{1}{0}} accept condition = ${if isin{$sender_host_address}{192.168.0.0/16}{1}{0}} # 替换为你的内部网段
内容的提问来源于stack exchange,提问作者Perdu
相关产品推荐
相关产品推荐

