Re: [vox-tech] procmail question
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [vox-tech] procmail question
On Sat, 2010-10-23 at 14:07 -0700, Tony Cratz wrote:
On 10/21/2010 11:21 AM, Ken Bloom wrote:
> That's why I suggested GNU mailutils. It has a "sieve" command that
> looks like it's a standalone filter (procmail replacement).
I would like to come back to this and ask a question just
in case I did not see what I should have.
Do you know if Sieve can rewrite headers. For example can I
change the To: header, or the Subject: header.
A quick googling suggests it doesn't know how to do it in-process, but you could use the GNU mailutils pipe extension to do such things (in conjunction with a program like formail or reformail, or of course a spam filter like spamassassin). You can look in /usr/lib/mailutils/ to see what extensions are available, and you can write your own as a shared library.
And if the
answer is yeas, then can I take the new message and send it
to my SMTP server (such as Sendmail) to redeliver the message
to the new list?
Maildrop was also mention, I only took a quick and dirty look
at it. Can it also solve the above questions?
I don't actually use Sieve for my email. I suggested it because it was a standard.
I've used maildrop in the past (rewriting headers, and running spam filters with its xfilter command), and my mail filters looked like (for example)
if (/Mailing-List: list some.mailinglist.org; contact/:h || \
/From:.*foo@bar.com/ || \
/From:.*bar@foo.com/ || \
/From:.*baz@bar.com/ || \
/From:.*@some.domain.org/ || \
/Mailing-List: list some-other-mailinglist@yahoogroups.com; / || \
/From:.*afinal@email.org/ )
{
to $MAILBOX/.util.probably-spam
}
# spam filtering
if ($SIZE < 1048576)
{
xfilter 'spamassassin'
}
if (/^X-Spam-Status: Yes/)
{
xfilter 'reformail -I"Status: RO"'
to '| $HOME/bin/maildir-deliverread $MAILBOX/.util.probably-spam'
}
I didn't like this (I didn't find it concise enough), and the backslashes as line continuations and mandatory braces annoyed me. (I was always forgetting them when I made changes, and it would break my email for days on end.)
So I changed to a solution in Ruby. I tried Perl first, but Perl performs variable interpolation with the @ sigil, so you can't put email addresses in a regular expression in Perl without escaping them. You'll notice that I don't bother to escape the period metacharacter in my regular expressions. Though technically, it can match any character, that possibility for false positives doesn't seem to matter much.
First, here's the skeleton that you need to write your own version. (You'll probably want to redefine the saveread function so that it doesn't depend on an external script.)
#!/usr/bin/env ruby
require 'rfilter/delivery_agent'
class RFilter::DeliveryAgent
def myfilter
#RULES GO IN HERE
end
#SUPPORT CODE FOLLOWS
def self.header_accessor name,field
class_eval <<-"end;"
def #{name}
header["#{field}"] || ""
end
end;
end
header_accessor :from, "From"
header_accessor :to, "To"
header_accessor :listid, "List-Id"
header_accessor :spam, "X-Spam-Status"
header_accessor :subject, "Subject"
header_accessor :msgid, "Message-id"
header_accessor :cc, "CC"
def isto? pattern
not [to,cc].grep(pattern).empty?
end
def involves? pattern
not [from,to,cc].grep(pattern).empty?
end
def ignore mailbox
saveread ".ignored-summer"
end
alias_method :internal_save, :save
def saveto mailbox
internal_save "#{ENV['HOME']}/Maildir/#{mailbox}/"
end
alias_method :save, :saveto
def saveread mailbox
pipe "#{ENV['HOME']}/bin/maildir-deliverread #{ENV['HOME']}/Maildir/#{mailbox}/"
end
def discard
pipe "true"
end
def main
myfilter
end
end
begin
RFilter::DeliveryAgent.process(STDIN,nil) { |agent| agent.main }
rescue RFilter::DeliveryAgent::DeliverySuccess
end
Then you can write really concise rules that look like this. (Any call to a save function or discard function stops the filter right there.)
discard if from =~ /noreply@studygroup.com/
discard if from =~ /Walgreens@email.walgreens.com/
saveto ".computer" if header["Return-Path"] =~ /cat-in-the-hat/
saveto ".computer" if header["Return-Path"] =~ /little-cat-a/
saveto ".computer" if from =~ /cat-in-the-hat/
saveto ".computer" if from =~ /little-cat-a/
#this is on multiple lines only because the test is so long that
#it would have wrapped badly otherwise
if involves?(/someparticularperson@somedomain.com/)
saveto ".somefolder"
end
saveto ".lists.linux" if listid =~ /.*vox.*lugod/
if from =~ /messages@frumster.com/
saveto ".shidduchim" if subject =~ /sent you a message/i
saveto ".shidduchim" if subject =~ /I want to communicate with you/i
saveread ".shidduchim"
end
if message.to_s.length < 1048576
filter "spamassassin"
end
if spam =~ /^Yes/
saveread ".util.probably-spam"
end
You can even modify headers in process:
if from =~ /acl@aclweb.org/ or from =~ /portal@aclweb.org/
#Can't use sub! because the original string is frozen.
message.header.subject=subject.sub('[na_members@aclweb.org] ','')
saveto ".lists.ACL"
end
How are you rewriting headers in procmail? Is this done by piping, or in-process?
_______________________________________________
vox-tech mailing list
vox-tech@lists.lugod.org
http://lists.lugod.org/mailman/listinfo/vox-tech
|