在 Exim 中,通常有两种方法可以在 SMTP 时调用 SpamAssassin
通过spam由Exiscan-ACL提供的条件。 这是我们这里要介绍的机制。
通过SA-Exim,这是由 Marc Merlins 编写的另一个实用程序 (<marc (at) merlins.org>),专门用于在 Exim 中在 SMTP 时间运行 SpamAssassin。 此程序通过 Exim 的local_scan()接口运行,可以直接修补到 Exim 源代码中,也可以通过 Marc 自己的dlopen()插件运行(顺便说一句,该插件包含在 Debian 的exim4-daemon-light和exim4-daemon-heavy软件包中)。
SA-Exim还提供一些其他功能,即灰名单和teergrubing。 但是,由于扫描是在收到邮件数据后发生的,因此这两个功能可能不如在 SMTP 事务的早期阶段那么有用。
SA-Exim可以在以下网址找到:http://marc.merlins.org/linux/exim/sa.html。
Exiscan-ACL的 "spam" 条件通过 SpamAssassin 或 Brightmail 传递消息,如果这些指示消息是垃圾邮件,则触发。 默认情况下,它连接到在spamd上运行的 SpamAssassin 守护进程 (localhost)。 可以通过在 Exim 配置文件 *main* 部分中添加spamd_address设置来更改主机地址和端口。 有关更多信息,请参阅exiscan-acl-spect.txt随补丁包含的文件。
在我们的实现中,我们将拒绝被归类为垃圾邮件的消息。 但是,我们希望将此类消息的副本保存在单独的邮件文件夹中,至少暂时如此。 这样,用户可以定期扫描 误报。
Exim 提供可以应用于接受消息的控制,例如freeze。 Exiscan-ACL 补丁添加了另一个这样的控制,即fakereject。 这会导致以下 SMTP 响应
550-FAKEREJECT id=message-id 550-Your message has been rejected but is being kept for evaluation. 550 If it was a legit message, it may still be delivered to the target recipient(s). |
通过将以下代码段插入到 acl_data 中,可以在我们的实现中包含此功能,accept语句之前
# Invoke SpamAssassin to obtain $spam_score and $spam_report. # Depending on the classification, $acl_m9 is set to "ham" or "spam". # # If the message is classified as spam, pretend to reject it. # warn set acl_m9 = ham spam = mail set acl_m9 = spam control = fakereject logwrite = :reject: Rejected spam (score $spam_score): $spam_report # Add an appropriate X-Spam-Status: header to the message. # warn message = X-Spam-Status: \ ${if eq {$acl_m9}{spam}{Yes}{No}} (score $spam_score)\ ${if def:spam_report {: $spam_report}} logwrite = :main: Classified as $acl_m9 (score $spam_score) |
在这个例子中,$acl_m9最初设置为 "ham"。 然后以用户mail的身份调用 SpamAssassin。 如果消息被归类为垃圾邮件,则$acl_m9设置为 "spam",并且发出上面的FAKEREJECT响应。 最后,将X-Spam-Status标头添加到消息中。 我们的想法是,邮件传递代理或收件人的 邮件用户代理可以使用此标头将垃圾邮件过滤到单独的文件夹中。
默认情况下,SpamAssassin 以冗长、表格状的格式显示其报告,主要适合包含在消息正文中或作为附件。 在我们的例子中,我们需要一个简洁的报告,适用于上面示例中的X-Spam-Statusheader。 为此,我们在其站点特定配置文件中添加以下代码段(/etc/spamassassin/local.cf, /etc/mail/spamassassin/local.cf,或类似的文件)
### Report template clear_report_template report "_TESTSSCORES(, )_" |
此外,内置了 贝叶斯评分功能,默认情况下已启用。 我们通常希望关闭此功能,因为它需要针对每个用户进行训练,因此不适用于系统范围的 SMTP 时间过滤
### Disable Bayesian scoring use_bayes 0 |
要使这些更改生效,您必须重新启动 SpamAssassin 守护进程(spamd)。
假设您有许多用户想要指定他们自己的 SpamAssassin 首选项,例如垃圾邮件阈值、可接受的语言和字符集、白名单/黑名单发件人等等。 或者也许他们真的希望能够利用 SpamAssassin 的原生贝叶斯评分(尽管我不明白为什么[1])。
正如文档前面 用户设置和数据 部分中所讨论的,有一种方法可以实现这一点。 我们需要限制每个传入邮件传递接受的收件人数量为一个。 我们接受调用者发出的第一个 RCPT TO: 命令,然后使用 451 SMTP 响应延迟后续命令。 与 灰名单一样,如果调用者是行为良好的 MTA,它将知道如何解释此响应,并在以后重试。
在 acl_rcpt_to 中,我们在验证收件人地址后,但在任何与从远程主机到本地用户的未经身份验证的传递相关的accept语句之前插入以下语句(即,在任何灰名单检查、信封签名检查等之前)
# Limit the number of recipients in each incoming message to one # to support per-user settings and data (e.g. for SpamAssassin). # # NOTE: Every mail sent to several users at your site will be # delayed for 30 minutes or more per recipient. This # significantly slow down the pace of discussion threads # involving several internal and external parties. # defer message = We only accept one recipient at a time - please try later. condition = $recipients_count |
在 acl_data 中,我们修改上一节中给出的spam条件,以便它将收件人地址的本地部分中指定的用户名传递给 SpamAssassin。
# Invoke SpamAssassin to obtain $spam_score and $spam_report. # Depending on the classification, $acl_m9 is set to "ham" or "spam". # # We pass on the username specified in the recipient address, # i.e. the portion before any '=' or '@' character, converted # to lowercase. Multiple recipients should not occur, since # we previously limited delivery to one recipient at a time. # # If the message is classified as spam, pretend to reject it. # warn set acl_m9 = ham spam = ${lc:${extract{1}{=@}{$recipients}{$value}{mail}}} set acl_m9 = spam control = fakereject logwrite = :reject: Rejected spam (score $spam_score): $spam_report |
请注意,我们没有使用 Exim 的${local_part:...}函数来获取用户名,而是手动提取了任何 "@" 或 "=" 字符之前的部分。 这是因为我们将在我们的 信封签名方案中使用后一个字符。
现在让我们再次看看 SpamAssassin。 首先,您可以选择删除我们之前在其站点范围配置文件中添加的use_bayes 0设置。 无论如何,每个用户现在都能够决定是否覆盖他们自己的此设置。
如果系统上的邮箱直接映射到具有主目录的本地 UNIX 帐户,则您就完成了。 默认情况下,SpamAssassin 守护进程 (spamd) 执行setuid()到我们传递给它的用户名,并将用户数据和设置存储在该用户的主目录中。
如果不是这种情况(例如,如果您的邮件帐户由 Cyrus SASL 或其他服务器管理),您需要告诉 SpamAssassin 在哪里找到每个用户的首选项和数据文件。 此外,spamd 需要继续作为特定的本地用户运行,而不是尝试setuid()到一个不存在的用户。
我们通过指定启动时传递给 spamd 的选项来完成这些操作
在 Debian 系统上,编辑OPTIONS=中的设置/etc/default/spamassassin.
在 RedHat 系统上,编辑SPAMDOPTIONS=中的设置/etc/sysconfig/spamassassin.
其他人,自己解决。
您需要的选项是
-u username- 指定 spamd 将在其下运行的用户(例如mail)
-x- 禁用用户主目录中的配置文件。
--virtual-config-dir=/var/lib/spamassassin/%u- 指定按用户设置和数据的存储位置。 "%u" 被调用用户名替换。 spamd 必须能够创建或修改此目录
# mkdir /var/lib/spamassassin # chown -R mail:mail /var/lib/spamassassin |
不用说,进行这些更改后,您需要重新启动 spamd。
[1] | 虽然贝叶斯训练确实特定于每个用户,但应该注意的是,IMHO,SpamAssassin 的贝叶斯分类器无论如何都不是那么出色。 特别是,我发现自垃圾邮件发送者已经学会通过在他们的邮件中(例如,在 HTML 消息的元数据中)播种随机字典单词或故事来击败此类系统的情况以来,情况就是如此。 |