Можно ли немного подчистить эту фильтрацию procmail?

Можно ли немного подчистить эту фильтрацию procmail?

У меня есть этот фильтр 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/

Вы, возможно, поняли, я стараюсь помечать заголовки писем тегом X-ClamAV: Yes, $MATCHили X-ClamAV: Virus Freeв зависимости от результата clamdscan и помещать его в $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/

(Я изменил тег, чтобы иметь возможность фильтровать с помощью AddHeader из clamav-filter)

ПРАВКА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"

Возможно, также было бы полезно удалить последний токен «FOUND» MATCHперед записью его в заголовок.

: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/

Связанный контент