100200300400500600
  
 
 

Mail

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");
}
Mon Jun 11 03:11:17 2012 Upd.: Sat Feb 9 14:52:57 2013
 
 
© ruff 2011