#!/usr/bin/perl # # maildir-scan-headers - grep a set of mail files for patterns, and list # all headers specified. sub usage { die "usage: maildir-scan-headers [-h headers] [--headers headers] [-re regexp] [-i] [-raw] [-sort] fileordir1 fileordir2 ... \n"; } my $expect_attachment = 0; my $wanted = ''; my $regexp = ''; my $sort = 0; my $casei = 0; my $raw = 0; my @files = (); use Getopt::Long qw(:config no_ignore_case); GetOptions( "headers|h=s" => \$wanted, "re=s" => \$regexp, "casei|i" => \$casei, "raw" => \$raw, "sort" => \$sort, 'help' => \&usage, '<>' => sub { push (@files, $_[0]); } ); $wanted =~ s/[ ,\|;:]+/\|/gs; if ($regexp) { $wanted = qr{${regexp}}; } elsif ($casei) { $wanted = qr{(?:$wanted)}i; } else { $wanted = qr{(?:$wanted)}; } foreach my $file (@files) { if (-d $file) { use File::Find; File::Find::find (sub { -f $_ and do_file ($File::Find::name); }, $file); } else { do_file ($file); } } sub do_file { my $file = shift; return if ($file =~ /\/\,\d/); # MH deleted mail open (IN, "<$file") or warn "cannot read $file\n"; my $hdrs = ''; while () { if (/^$/) { last; } if ($expect_attachment && !$raw && /X-Spam-Flag: YES/) { while () { /^Content-Description: original message before SpamAssassin/ and last; } $_ = ; $_ = ; $_ = ; $hdrs = ''; next; } $hdrs .= $_; } close IN; $hdrs =~ s/\n([ \t])/\\n$1/gs; # folding $hdrs =~ s/\t/\\t/gs; # tabs $hdrs =~ s/\|/[pipe]/gs; # pipe chars my @ok = ($hdrs =~ /^(${wanted}:.*)$/gom); if ($sort) { @ok = sort @ok; } $hdrs = join ("|", @ok); return unless $hdrs =~ /\S/; print "$file $hdrs\n"; }