Files
zira-etc/mail/spamassassin/SaveHits.pm
2021-05-24 22:18:33 +03:00

121 lines
3.3 KiB
Perl

# <@LICENSE>
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to you under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# </@LICENSE>
# Author: Steve Freegard <steve.freegard@fsl.com>
package Mail::SpamAssassin::Plugin::SaveHits;
my $VERSION = 0.1;
use strict;
use Mail::SpamAssassin::Plugin;
use Digest::SHA1 qw{sha1_hex};
use File::Path;
use File::Basename;
use vars qw(@ISA);
@ISA = qw(Mail::SpamAssassin::Plugin);
sub dbg {
Mail::SpamAssassin::Plugin::dbg ("SaveHits: @_");
}
sub new {
my ($class, $mailsa) = @_;
$class = ref($class) || $class;
my $self = $class->SUPER::new($mailsa);
bless ($self, $class);
return $self;
}
sub parse_config {
my ($self,$params) = @_;
return 0 unless ($params->{key} =~ /^savehits_(\S+)$/i);
my $key = $1;
if($key =~ /^rule$/i) {
my(@split) = split(/\s+/,$params->{value});
foreach my $rule (@split) {
$self->{main}->{conf}->{'savehits_rules'}->{$rule} = 1 if $rule;
dbg("Added rule $rule to save list");
}
}
if($key =~ /^dir$/i) {
$self->{main}->{conf}->{$params->{key}} = $params->{value};
}
$self->inhibit_further_callbacks();
return 1;
}
sub check_end {
my ($self, $params) = @_;
my ($pms) = $params->{permsgstatus};
my ($saverules) = $self->{main}->{conf}->{'savehits_rules'};
my ($savedir) = $self->{main}->{conf}->{'savehits_dir'};
return 0 if not $savedir;
my ($msg) = $pms->get_message();
my ($pristine) = $msg->get_pristine();
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
my ($date) = sprintf("%d%02d%02d",$year+1900,$mon+1,$mday);
my(@hits) = split(',',($pms->get_names_of_tests_hit.','.$pms->get_names_of_subtests_hit));
my(%rules);
map { $rules{$_}++ } @hits;
foreach my $rule (keys %rules) {
if(defined($saverules->{$rule})) {
dbg("Got hit: $rule");
my $hash = sha1_hex($pristine);
my $filename = "$savedir/msgs/$date/$hash";
my $linkname = "$savedir/rules/$rule/$date/$hash";
# Untaint
$filename =~ /^([\/-\@\w.]+)$/;
$filename = $1;
$linkname =~ /^([\/-\@\w.]+)$/;
$linkname = $1;
eval { mkpath(dirname($filename)); };
if ($@) {
dbg("error: $@");
return 0;
}
eval { mkpath(dirname($linkname)); };
if ($@) {
dbg("error: $@");
return 0;
}
if (! -f $filename) {
dbg("Saving message to $filename");
eval { open(FILE, ">$filename"); };
if ($@) {
dbg("error: $@");
return 0;
}
print FILE $pristine;
close(FILE);
}
if ((! -f $linkname) && (-f $filename)) {
dbg("Creating symlink $linkname to $filename");
eval { symlink($filename, $linkname); };
if ($@) {
dbg("error: $@");
return 0;
}
}
}
}
return 1;
}
1;