Фильтрация почты через функцию Sieve/Pigeonhole

Попытка отфильтровать почту через функцию Sieve.

Я хотел бы получить адрес электронной почты, указанный внутри тела сообщения, а не в заголовке. Этот адрес (как и в заголовке) после From: поле. После этого копия электронного письма должна быть отправлена ​​на этот адрес. Фильтрованные сообщения также должны иметь Returned mail внутри их предмета.

Это мой код, но не работает...

        require ["body","copy","variables"];

        if header :contains "Subject" "Returned mail"
            {
            if body :content "text" :matches "From: *"
                {
                redirect :copy "${1}";
                }
            }

Можете ли вы помочь мне исправить этот код? Спасибо!!

2 ответа

Решение

Вернитесь к старому доброму procmail

Procmail поддерживает сопоставление в теле сообщения следующим образом:

:0H
* ^Subject: .*Returned mail
{
 :0B
 * ^From: \/.+@.+
 {
  ADDR=$MATCH
  :0 c
  * ADDR ?? ^[a-z0-9_-+.]+@[a-z0-9-+.]+$
  | $ADDR
 }
}

Это охватывает все после, в строке, начинающейся с "From: ", в теле сообщения.

:0B означает, что следующее сопоставление должно быть сделано в теле сообщения

\/ в выражении начинается запись в $MATCH (встроенная переменная)

Совпадение сохраняется в переменной Procmail $ADDR, которая затем становится постоянно доступной при выполнении сценария procmail furturer. В субблоке это доставляет (:0 carbon copys) сообщение по вновь сопоставленному адресу назначения. Но обратите внимание, что на данный момент не безопасно проверить, действительно ли это адрес электронной почты. Это также оставляет уязвимость для удаленного выполнения кода.

ДОЛЖНА БЫТЬ также любая техника защиты X-Loop, примененная вручную, которая не рассматривается в этом примере.

Невозможно извлечь что-либо непосредственно из тела сообщения для дальнейшей обработки. Сито не заполняет переменные, такие как ${1} из спичек тела.

В RFC четко указано, что это НЕ ДОЛЖНО быть возможным.

Однако существует возможность решить эту проблему путем подачи (фильтрации) сообщения в отдельное приложение, как показано ниже, которое помещает желаемую информацию в заголовок.

Представьте, что оригинальное сообщение было:

To: my@second.tld
Subject: Test
From: other@example.tld
Date: Wed, 25 Oct 2017 16:22:05 +0200

Hi guy, here starts the body
This mail contains a important dynamic address

From: important@match.tld

wich has to be matched und processed by sieve

Тогда ваше сито может выглядеть так:

require ["copy","variables","vnd.dovecot.filter"];

if header :contains "Subject" "Returned mail" {
    filter "bleed_from.py";
    if header :matches "Bleeded-From" "*" {
        redirect :copy "${1}";
    }
}

Фильтр-скрипт "bleed_from.py":

#!/usr/bin/python
import re
import email

# Read the mail from stdin
parser = email.FeedParser.FeedParser()
mail = None
for line in sys.stdin.readlines():
    parser.feed(line)
mail = parser.close()

# Grep the From out of the body and add it to the header
ret = re.findall("From: (.*)", mail.get_payload())
mail.add_header("Bleeded-From", ret[0])

# Return the message
print(mail.as_string())

Это очень простое доказательство концепции и работает только для не составных сообщений без специальных символов. В противном случае это приложение будет аварийно завершено. Работа с charsets взорвет границы этого примера.

Другие вопросы по тегам