B<minc> B<-d>
-B<minc> B<-h>
+B<minc> B<-r>
=head1 DESCRIPTION
Dry run; do not actually incorporate the mail, but log and report to
stdout/stderr as normal.
+=item B<-r>
+
+Rebuild `mhpath +`/.folders from scratch, processing no mail.
+
=back
=cut
my $help;
my $maxmsgs;
my $norun;
+my $rebuild_dot_folders;
GetOptions(
'd' => \$dumpfilters,
'h|help' => \$help,
'm=i' => \$maxmsgs,
'n' => \$norun,
+ 'r' => \$rebuild_dot_folders,
) or pod2usage();
$help and pod2usage(-exitstatus=>0, -verbose=>1);
@ARGV == 0 or pod2usage();
Where B<minc> logs what it does, unless in -n mode.
-=item `mhpath +`/logs/dryrun.log
-
-Where B<minc> logs what it would do; used in -n mode.
-
=item `mhpath +`/.minc.context
B<minc> uses this file for context (i.e. current folder) instead of
our $SCAN_P_FOLDER = 0.1;
our $SCAN_P_MESSAGE = 0.0625;
our $SCAN_P_FROM = 0.175;
+our @folder_sort_list = (qr/^inbox$/);
+our $folder_sorter = sub { sort_by_list(@_, @folder_sort_list) };
my $mh;
-my $logfile;
$mh = `mhpath +`;
chomp($mh);
-if ($run) {
- $logfile = $mh . '/logs/minc.log';
-} else {
- $logfile = $mh . '/logs/dryrun.log';
-}
+my $logfile = $mh . '/logs/minc.log';
$ENV{"MHCONTEXT"} = $mh . '/.minc.context';
# Logging
sub mylog {
+ $run or return;
+
my $timestamp = strftime('%b %e %H:%M:%S', localtime);
my $msg;
foreach my $part (@_) {
###############################################################################
# Utility procedures
+sub sort_by_list {
+ my $a = shift;
+ my $b = shift;
+
+ for my $i (@_) {
+ my $am = $a =~ $i;
+ my $bm = $b =~ $i;
+ if ($am) {
+ if ($bm) {
+ last;
+ }
+ return -1;
+ } elsif ($bm) {
+ return 1;
+ }
+ }
+
+ return $a cmp $b;
+}
+
sub mkfolder {
my $folder = shift;
my $target;
my $header;
my $contents;
my $pair;
- my $match;
+ my $regexp;
my $expression;
my $result;
if ($header =~ /$MAGIC_TO_REGEX/i) {
foreach $contents (@{$headers{lc($header)}}) {
foreach $pair (@filter) {
- ($match, $expression) = @$pair;
- if ($contents =~ /$match/i) {
+ ($regexp, $expression) = @$pair;
+ if ($contents =~ $regexp) {
if (eval "\$result = \"$expression\"") {
return $result;
}
# Walk the list of message headers matching the filter's
# specified header.
foreach $contents (@{$headers{lc($header)}}) {
- # Walk the filter's list of match/expression pairs.
+ # Walk the filter's list of regexp/expression pairs.
foreach $pair (@filter) {
- ($match, $expression) = @$pair;
- if ($contents =~ /$match/i) {
+ ($regexp, $expression) = @$pair;
+ if ($contents =~ $regexp) {
if (eval "\$result = \"$expression\"") {
return $result;
}
$spam++;
} else {
$saved++;
- my $from = [@{$headers{'from'}}]->[-1];
- my $subject = [@{$headers{'subject'}}]->[-1];
+ my $from = '';
+ my $subject = '';
+ # Sometimes these headers are missing...
+ eval { $from = [@{$headers{'from'}}]->[-1] };
+ eval { $subject = [@{$headers{'subject'}}]->[-1] };
for ($from, $subject) {
tr/\x00-\x1f\x80-\xff/ /;
}
return %folders;
}
-sub update_folders {
+sub build_dot_folders {
my $folders = shift;
- my ($fh, $fn);
+ my $fh = shift;
+ my $fn;
- if (open($fh, "$mh/.folders")) {
+ if (defined($fh)) {
while (<$fh>) {
chomp;
$folders->{$_}++;
}
- } elsif (not $!{ENOENT}) {
- # For ENOENT, we go ahead and create it, else we error and
- # don't clobber it.
- warn("open($mh/.folders): $!");
- return;
}
eval { ($fh, $fn) = tempfile("$mh/.folders.XXXXX") };
return;
}
- print($fh "inbox\n");
- for my $folder (sort(keys(%$folders))) {
- $folder eq 'inbox' and next;
+ for my $folder (sort { $folder_sorter->($a,$b) } keys(%$folders)) {
print($fh "$folder\n");
}
rename($fn, "$mh/.folders") or warn("rename($fn, $mh/.folders): $!");
}
+sub create_dot_folders {
+ if (-f "$HOME/.minc") {
+ require "$HOME/.minc";
+ }
+
+ my %folders;
+ open(my $fh, '-|', 'folders', '-fast', '-recur')
+ or die("open(folders|): $!");
+ build_dot_folders(\%folders, $fh);
+ return 0;
+}
+
+sub update_dot_folders {
+ my $folders = shift;
+ my $fh;
+
+ if (not open($fh, "$mh/.folders") and not $!{ENOENT}) {
+ # For ENOENT, we go ahead and create it, else we error and
+ # don't clobber it.
+ warn("open($mh/.folders): $!");
+ return;
+ }
+
+ build_dot_folders($folders, $fh);
+}
+
\f
MAIN: {
my $st;
exit;
}
+ $rebuild_dot_folders and exit(create_dot_folders);
+
chdir("$MAILDIR/new") or die("chdir($MAILDIR/new): $!");
my %folders = filter_mail(map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
}
getfiles('.'));
- $run and update_folders(\%folders);
+ $run and update_dot_folders(\%folders);
@SPAM and (exec('scan', '+SPAM', @SPAM) or die);
}