[vox-tech] procmail question

Chanoch (Ken) Bloom kbloom at gmail.com
Sat Oct 23 18:01:35 PDT 2010


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 at bar.com/ || \
            /From:.*bar at foo.com/ || \
            /From:.*baz at bar.com/ || \
            /From:.*@some.domain.org/ || \
            /Mailing-List: list some-other-mailinglist at yahoogroups.com; / || \
            /From:.*afinal at 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 at studygroup.com/
      discard if from =~ /Walgreens at 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 at somedomain.com/)
        saveto ".somefolder"
      end

      saveto ".lists.linux" if listid =~ /.*vox.*lugod/

      if from =~ /messages at 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 at aclweb.org/ or from =~ /portal at aclweb.org/
        #Can't use sub! because the original string is frozen.
        message.header.subject=subject.sub('[na_members at aclweb.org] ','')
        saveto ".lists.ACL"
     end




How are you rewriting headers in procmail? Is this done by piping, or
in-process?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.lugod.org/pipermail/vox-tech/attachments/20101023/df18b884/attachment.html 


More information about the vox-tech mailing list