diff options
Diffstat (limited to 'lib/PublicInbox/WatchMaildir.pm')
-rw-r--r-- | lib/PublicInbox/WatchMaildir.pm | 95 |
1 files changed, 16 insertions, 79 deletions
diff --git a/lib/PublicInbox/WatchMaildir.pm b/lib/PublicInbox/WatchMaildir.pm index a3fab428..7ee29da5 100644 --- a/lib/PublicInbox/WatchMaildir.pm +++ b/lib/PublicInbox/WatchMaildir.pm @@ -7,13 +7,14 @@ package PublicInbox::WatchMaildir; use strict; use warnings; use PublicInbox::MIME; -use Email::MIME::ContentType; -$Email::MIME::ContentType::STRICT_PARAMS = 0; # user input is imperfect use PublicInbox::Git; use PublicInbox::Import; use PublicInbox::MDA; use PublicInbox::Spawn qw(spawn); +use PublicInbox::InboxWritable; use File::Temp qw//; +use PublicInbox::Filter::Base; +*REJECT = *PublicInbox::Filter::Base::REJECT; sub new { my ($class, $config) = @_; @@ -52,6 +53,10 @@ sub new { $spamcheck = undef; } } + + # need to make all inboxes writable for spam removal: + $config->each_inbox(sub { PublicInbox::InboxWritable->new($_[0]) }); + foreach $k (keys %$config) { $k =~ /\Apublicinbox\.([^\.]+)\.watch\z/ or next; my $name = $1; @@ -93,18 +98,6 @@ sub _done_for_now { my ($self) = @_; my $importers = $self->{importers}; foreach my $im (values %$importers) { - $im->done if $im->{nchg}; - } - - my $opendirs = $self->{opendirs}; - - # spamdir scanning means every importer remains open - my $spamdir = $self->{spamdir}; - return if defined($spamdir) && $opendirs->{$spamdir}; - - foreach my $im (values %$importers) { - # not done if we're scanning - next if $opendirs->{$im->{git}->{git_dir}}; $im->done; } } @@ -127,15 +120,14 @@ sub _remove_spam { # path must be marked as (S)een $path =~ /:2,[A-R]*S[T-Za-z]*\z/ or return; my $mime = _path_to_mime($path) or return; - _force_mid($mime); $self->{config}->each_inbox(sub { my ($ibx) = @_; eval { my $im = _importer_for($self, $ibx); $im->remove($mime, 'spam'); - if (my $scrub = _scrubber_for($ibx)) { + if (my $scrub = $ibx->filter) { my $scrubbed = $scrub->scrub($mime) or return; - $scrubbed == 100 and return; + $scrubbed == REJECT() and return; $im->remove($scrubbed, 'spam'); } }; @@ -146,36 +138,9 @@ sub _remove_spam { }) } -# used to hash the relevant portions of a message when there are conflicts -sub _hash_mime2 { - my ($mime) = @_; - require Digest::SHA; - my $dig = Digest::SHA->new('SHA-1'); - $dig->add($mime->header_obj->header_raw('Subject')); - $dig->add($mime->body_raw); - $dig->hexdigest; -} - -sub _force_mid { - my ($mime) = @_; - # probably a bad idea, but we inject a Message-Id if - # one is missing, here.. - my $mid = $mime->header_obj->header_raw('Message-Id'); - if (!defined $mid || $mid =~ /\A\s*\z/) { - $mid = '<' . _hash_mime2($mime) . '@generated>'; - $mime->header_set('Message-Id', $mid); - } -} - sub _try_path { my ($self, $path) = @_; - my @p = split(m!/+!, $path); - return if $p[-1] !~ /\A[a-zA-Z0-9][\w:,=\.]+\z/; - if ($p[-1] =~ /:2,([A-Z]+)\z/i) { - my $flags = $1; - return if $flags =~ /[DT]/; # no [D]rafts or [T]rashed mail - } - return unless -f $path; + return unless PublicInbox::InboxWritable::is_maildir_path($path); if ($path !~ $self->{mdre}) { warn "unrecognized path: $path\n"; return; @@ -190,19 +155,17 @@ sub _try_path { } my $im = _importer_for($self, $inbox); my $mime = _path_to_mime($path) or return; - $mime->header_set($_) foreach @PublicInbox::MDA::BAD_HEADERS; my $wm = $inbox->{-watchheader}; if ($wm) { my $v = $mime->header_obj->header_raw($wm->[0]); return unless ($v && $v =~ $wm->[1]); } - if (my $scrub = _scrubber_for($inbox)) { + if (my $scrub = $inbox->filter) { my $ret = $scrub->scrub($mime) or return; - $ret == 100 and return; + $ret == REJECT() and return; $mime = $ret; } - _force_mid($mime); $im->add($mime, $self->{spamcheck}); } @@ -290,41 +253,15 @@ sub _path_to_mime { } sub _importer_for { - my ($self, $inbox) = @_; - my $im = $inbox->{-import} ||= eval { - my $git = $inbox->git; - my $name = $inbox->{name}; - my $addr = $inbox->{-primary_address}; - PublicInbox::Import->new($git, $name, $addr, $inbox); - }; - + my ($self, $ibx) = @_; my $importers = $self->{importers}; + my $im = $importers->{"$ibx"} ||= $ibx->importer(0); if (scalar(keys(%$importers)) > 2) { - delete $importers->{"$im"}; + delete $importers->{"$ibx"}; _done_for_now($self); } - $importers->{"$im"} = $im; -} - -sub _scrubber_for { - my ($inbox) = @_; - my $f = $inbox->{filter}; - if ($f && $f =~ /::/) { - my @args = (-inbox => $inbox); - # basic line splitting, only - # Perhaps we can have proper quote splitting one day... - ($f, @args) = split(/\s+/, $f) if $f =~ /\s+/; - - eval "require $f"; - if ($@) { - warn $@; - } else { - # e.g: PublicInbox::Filter::Vger->new(@args) - return $f->new(@args); - } - } - undef; + $importers->{"$ibx"} = $im; } sub _spamcheck_cb { |