l i n u x - u s e r s - g r o u p - o f - d a v i s
Next Meeting:
July 7: Social gathering
Next Installfest:
Latest News:
Jun. 14: June LUGOD meeting cancelled
Page last updated:
2010 Oct 23 18:29

The following is an archive of a post made to our 'vox-tech mailing list' by one of its subscribers.

Report this post as spam:

(Enter your email address)
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


   def self.header_accessor name,field
      class_eval <<-"end;"
         def #{name}
            header["#{field}"] || ""

   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?
   def involves? pattern
         not [from,to,cc].grep(pattern).empty?

   def ignore mailbox
      saveread ".ignored-summer"

   alias_method :internal_save, :save
   def saveto mailbox
      internal_save "#{ENV['HOME']}/Maildir/#{mailbox}/"
   alias_method :save, :saveto

   def saveread mailbox
      pipe "#{ENV['HOME']}/bin/maildir-deliverread #{ENV['HOME']}/Maildir/#{mailbox}/"

   def discard
      pipe "true"

   def main


   RFilter::DeliveryAgent.process(STDIN,nil) { |agent| agent.main }
rescue RFilter::DeliveryAgent::DeliverySuccess

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"

      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"

      if message.to_s.length < 1048576
         filter "spamassassin"

      if spam =~ /^Yes/
         saveread ".util.probably-spam"

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"

How are you rewriting headers in procmail? Is this done by piping, or in-process?
vox-tech mailing list

LUGOD Group on LinkedIn
Sign up for LUGOD event announcements
Your email address:
LUGOD Group on Facebook
'Like' LUGOD on Facebook:

Hosting provided by:
Sunset Systems
Sunset Systems offers preconfigured Linux systems, remote system administration and custom software development.

LUGOD: Linux Users' Group of Davis
PO Box 2082, Davis, CA 95617
Contact Us

LUGOD is a 501(c)7 non-profit organization
based in Davis, California
and serving the Sacramento area.
"Linux" is a trademark of Linus Torvalds.

Sponsored in part by:
Appahost Applications
For a significant contribution towards our projector, and a generous donation to allow us to continue meeting at the Davis Library.