我有这个 procmail 过滤器,它似乎可以工作,但我真的不为它感到自豪。我确信我们可以通过嵌套部分进行更多的优化和清理,但我无法实现任何功能结果。
:0
* !^X-ClamAV
VIRUS=|/usr/bin/clamdscan --no-summary --stdout -
:0fw
* !^X-ClamAV
* VIRUS ?? .*: \/.* FOUND
| formail -a "X-ClamAV: Yes, $MATCH"
:0Efw
* !^X-ClamAV
| formail -a "X-ClamAV: Virus Free"
:0
* ^X-ClamAV: Yes
$MAILDIR/.virus/
您可能已经明白了,我尝试根据 clamdscan 的结果用X-ClamAV: Yes, $MATCH
或标记电子邮件标题X-ClamAV: Virus Free
,如果结果为阳性,则将其放置在 $MAILDIR /.virus/ 中。就这样。
编辑:
也许这样更好:
:0
* !^X-Virus-Status
VIRUS=|/usr/bin/clamdscan --no-summary --stdout -
:0
* !^X-Virus-Status
* VIRUS ?? .*: \/.* FOUND
{
:0fhw
| formail -a "X-Virus-Status: Infected, $MATCH"
}
:0Efw
| formail -a "X-Virus-Status: Virus Free"
:0
* ^X-Virus-Status: Infected
$MAILDIR/.virus/
(我更改了标签以便能够使用 clamav-filter 的 AddHeader 进行过滤)
编辑2:
但我犯了一个错误,没有解释清楚,或者根本没有解释,事实上,电子邮件可以在 procmail(clamav-milter)之前被标记,因此已经包含X-Virus-Status: Infected
。在这种情况下,重复扫描是没有意义的,但你必须将电子邮件放在其中.virus
。这就是为什么我需要把
:0
* ^X-Virus-Status: Infected
$MAILDIR/.virus/
脱离大括号
但我的解决方案似乎不太好(procmail: Skipped "--no-summary --stdout -"
):
:0
* !^X-Virus-Status
{
VIRUS=|/usr/bin/clamdscan --no-summary --stdout -
:0
* VIRUS ?? .*: \/.* FOUND
{
VIRUSNAME=`echo "$MATCH" | sed 's/ FOUND$//'`
:0fhw
| formail -a "X-Virus-Status: Infected ($VIRUSNAME)"
}
:0Efw
| formail -a "X-Virus-Status: Virus Free"
}
:0
* ^X-Virus-Status: Infected
$MAILDIR/.virus/
我不想覆盖X-Virus-Status
。
.virus
如果没有标记 -> 扫描 -> 标记(是否感染) ->如果感染则输入.virus
如果已经标记 ->如果感染则输入
换句话说(也许更清楚):
1) tagged X-Virus-Status?
yes: go 2)
no: scan -> infected?
yes: tag infected
no: tag non infected
2) tagged X-Virus-Status: Infected?
yes: put in .virus
no: go 3)
3) continue procmail filters
编辑3:
我在 EDIT2 中尝试的解决方案与 @tripleee 提出的相同,效果很好。问题在于未读取参数的过滤器。
我更换了
VIRUS=|/usr/bin/clamdscan --no-summary --stdout -
经过
VIRUS=`/usr/bin/clamdscan --no-summary --stdout -`
现在似乎已经好了。
答案1
简要说明一下风格,这里不需要括号。
:0fhw
* !^X-Virus-Status
* VIRUS ?? .*: \/.* FOUND
| formail -a "X-Virus-Status: Infected, $MATCH"
标志fhw
适用于操作,并且只有条件匹配时才会采取行动。
另一方面,当这些条件成立时,我可能会用括号括起你想要采取的所有行动。
作为修复语法错误的另一种方法,请尝试在 VIRUS 赋值周围使用反引号。也可以使用=|
赋值语法,但如果第一种方法不适合您,请尝试另一种方法。对我来说,这种方法很好用。
:0
* !^X-Virus-Status
{ VIRUS=`clamdscan --no-summary --stdout -` }
:0
* !^X-Virus-Status
* VIRUS ?? .*: \/.* FOUND
{
:0fhw
| formail -a "X-Virus-Status: Infected, $MATCH"
:0
$MAILDIR/.virus/
}
:0Efw
| formail -a "X-Virus-Status: Virus Free"
MATCH
在将最后一个“FOUND”标记写入标题之前,删除它也许也很有用。
:0
* !^X-Virus-Status
* VIRUS ?? .*: \/.* FOUND
{
VIRUSNAME=`echo "$MATCH" | sed 's/ FOUND$//'`
:0fhw
| formail -a "X-Virus-Status: Infected, $VIRUSNAME"
(我一直在努力想出一个不需要外部过程来修剪字符串末端的解决方案。也许可以通过巧妙地使用评分来实现这样的效果,但对于这个简单的配方来说,这可能有点小题大做。)
最后,我不确定你是否想覆盖它,X-Virus-Status
即使它已经存在。:0E
当其中一个或两个条件为假时,你的意愿就会发生。也许你的意思是这个;
:0
* !^X-Virus-Status
{
VIRUS=`clamdscan --no-summary --stdout -`
:0
* VIRUS ?? .*: \/.* FOUND
{
VIRUSNAME=`echo "$MATCH" | sed 's/ FOUND$//'`
:0fhw
| formail -a "X-Virus-Status: Infected, $VIRUSNAME"
:0
$MAILDIR/.virus/
}
:0Efw
| formail -a "X-Virus-Status: Virus Free"
}
换句话说,仅当X-Virus-Status:
标题中不存在病毒时才在此处采取这些操作;如果 Clamscan 的结果表明没有病毒,则添加标题“无病毒”。
我拿出了/usr/bin
;可能最好确保你的PATH
路径是理智的,而不是硬编码所有路径,但当然,最终取决于你。
对于你更新的问题,我猜你想要的逻辑是
:0
* !^X-Virus-Status
{
VIRUS=`clamdscan --no-summary --stdout -`
:0
* VIRUS ?? .*: \/.* FOUND
{
VIRUSNAME=`echo "$MATCH" | sed 's/ FOUND$//'`
:0fhw
| formail -a "X-Virus-Status: Infected, $VIRUSNAME"
}
:0Efw
| formail -a "X-Virus-Status: Virus Free"
}
:0
* ^X-Virus-Status: Infected
$MAILDIR/.virus/