I found it's quite convenient to prepare filters in Thunderbird. However there's one minor inconvenience - it does not store filters serverside (yes, I'm using outlook/exchange at work) which makes all your pretty organised workspace bound to the Thunderbird client.
I think this is unacceptable, hence written this small script, which does exactly what I need - converts my thunderbird filter rules into procmail rc recipes. Definitely it contains only those parts of filter syntax I am using so do not expect it be full through-out converter. To convert the rules - locate your filter-set (use locate msgFilterRules.dat or find .thunderbird -name '*msgFilterRules*'to find it) and execute cat path/to/msgFilterRules.dat | ./tbf2pmrc >> .procmailrc
tbf2pmrc:
#!/usr/bin/perl -w
use strict;
my ($name,%condition,%action,%type,%enabled,$an,@rn);
# Action map - actions are reverse sorted when recipe is printed
# Define new actions here with correct priority.
# Priority 2 - move to the folder - stops flow thus should not change
my %am=("Stop execution" => 1,
"Move to folder" => 2,
"Forward" => 3,
"Copy to folder" => 4,
"AddTag" => 10,
"Delete" => 9999);
# TODO: Action 1 - stop execution - save to inbox?
# Use maildit format?
my $MD=1;
while(<STDIN>) {
chomp;
if(/^condition=\"OR (.*)\"/){
my @o;
for my$c(split(' OR ',$1)){
$c=~s/^\((.)(.+)\)/@{[uc($1)]}$2/;
$c=~s/([\[\](){}.+])/\\$1/omg;
$c=~s/\*/.*/omg;
$c=~s/All addresses/(From|To|Cc|Bcc)/;
$c=~s/,(contains|is),/:\.\*/;
push@o,"^$c.*";
}
$condition{$name}=join("|\\\n ",@o);
} elsif(/^condition=\"AND \(([^)]+)\)\"/){
my $g=$1;
$g=~s/(.)(.+)/@{[uc($1)]}$2/;
$g=~s/([\[\](){}.+])/\\$1/omg;
$g=~s/All addresses/(From|To|Cc|Bcc)/;
$g=~s/,(contains|is),/:\.\*/;
$condition{$name}="^$g.*";
} elsif(/^action=\"(.+)\"/) {
$an=$am{$1};
$an=0 unless($an); # throw away undefined actions
} elsif(/^actionValue=\"(.+)\"/){
if(exists($action{$name}->{$an})) {
push(@{$action{$name}->{$an}},$1);
} else {
$action{$name}->{$an}=[$1];
}
} elsif(/^type=\"(.+)\"/){
$type{$name}=$1;
} elsif(/^enabled=\"(.+)\"/){
$enabled{$name}=$1;
push(@rn,$name) if($1 eq 'yes');
} elsif(/^name=\"(.+)\"/){
$name=$1;
}
}
foreach my$n(@rn){
print":0:\n* ".$condition{$n}."\n{\n";
for$an(sort{$b<=>$a}(keys(%{$action{$n}}))) {
last if($an<2); # Action 1 - stop processing rules
if($an == 2 || $an == 4) { # Store mail
for my$d(@{$action{$n}->{$an}}){
my $m=$d;
$m=~s!imap://[^/]+/!!;
$m=~y!/!.!;
print(":0");
print(" c") if($an > 2);
print(":\n");
print(".$m");
print('/') if($MD);
print("\n\n");
}
} elsif($an == 3) { # Forward - stops execution
print(":0:\n");
print("! ".$action{$n}->{$an}->[0]);
print("\n\n");
} elsif($an == 10) { # Add tag
my$t = join('', map
{"-I 'X-Add-tag: $_' "}
@{$action{$n}->{$an}});
print(":0 f:\n");
print("| formail $t\n\n");
} elsif($an == 9999) { # Delete
print(":0:\n/dev/null\n\n");
last; # Not processing any rules if Delete
}
}
print("}\n\n");
}
Link...
Mon Jun 11 03:11:17 2012
Upd.: Sat Feb 9 14:52:57 2013