Reputation: 43
Trying to filter mails through a Sieve function.
I would like to fetch an e-mail address indicated inside the body of the message, and not in the header. This address is (like the one in the header) after a From:
field. After that, a copy of the email should be sent to this address. Messages filtered must also have Returned mail
inside their subject.
This is my code, but not working...
require ["body","copy","variables"];
if header :contains "Subject" "Returned mail"
{
if body :content "text" :matches "From: *"
{
redirect :copy "${1}";
}
}
Can you please help me to fix that code ? Thank's !!
Upvotes: 1
Views: 805
Reputation: 498
There is no way to grep things directly out of the message body for further processing.
Sieve does not populate variables like ${1}
from body matches.
The RFC states clearly that this MUST NOT be possible.
There is however a possibility to solve this issue by feeding (filtering) the message through a separate application like as follows which puts the desired information into the header.
Imagine the original message was:
To: [email protected]
Subject: Test
From: [email protected]
Date: Wed, 25 Oct 2017 16:22:05 +0200
Hi guy, here starts the body
This mail contains a important dynamic address
From: [email protected]
wich has to be matched und processed by sieve
Then your sieve could look like this:
require ["copy","variables","vnd.dovecot.filter"];
if header :contains "Subject" "Returned mail" {
filter "bleed_from.py";
if header :matches "Bleeded-From" "*" {
redirect :copy "${1}";
}
}
The filter-script "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())
This is a very over-simplified proof of concept and works only for non-multipart messages without special characters. Otherwise this application will crash. Dealing with charsets would blow the margins of this example.
Upvotes: 1
Reputation: 498
Switch back to good old procmail
Procmail does support matching within the message body like this:
:0H
* ^Subject: .*Returned mail
{
:0B
* ^From: \/.+@.+
{
ADDR=$MATCH
:0 c
* ADDR ?? ^[a-z0-9_-+.]+@[a-z0-9-+.]+$
| $ADDR
}
}
This covers everything after, in the line beginning with "From: ", in the message body.
:0B
means the next matching has to be done on the message body
\/
in the expression starts the record to $MATCH (build-in variable)
The match is stored in the Procmail variable $ADDR wich then is permanently accessible within the furturer procmail script execution.
In the subblock it delivers (:0 c
arbon copys) the message to the newly matched destination address. But note that at this point it is not safely checked if it really is an email address. This leaves also maybe a vulnurability for a remote code execution.
There MUST BE also any X-Loop protection techniq applied manually wich is not covered by this example
Upvotes: 2