125 lines
3.7 KiB
Plaintext
125 lines
3.7 KiB
Plaintext
|
use MIME::Parser;
|
||
|
use MIME::Entity;
|
||
|
|
||
|
sub register {
|
||
|
my ($self, $qp, @args) = @_;
|
||
|
|
||
|
$self->log(LOGERROR, "Bad parameters for the disclaimer plugin")
|
||
|
if @_ % 2;
|
||
|
|
||
|
%{$self->{_args}} = @args;
|
||
|
}
|
||
|
|
||
|
sub read_disclaimer {
|
||
|
my ($self, $disclaimer_file) = @_;
|
||
|
my $disclaimer_dir = $self->{_args}->{disclaimer_dir} || "/service/qpsmtpd/config/";
|
||
|
return () unless open DISCLAIMER, "<$disclaimer_dir/$disclaimer_file";
|
||
|
my @lines = <DISCLAIMER>;
|
||
|
chomp @lines;
|
||
|
close DISCLAIMER;
|
||
|
return @lines;
|
||
|
}
|
||
|
|
||
|
sub hook_data_post {
|
||
|
my ($self, $transaction) = @_;
|
||
|
|
||
|
if ( $transaction->header->get('X-Qpsmtp-Disclaimer') ) {
|
||
|
$self->log(LOGNOTICE, "Message already has disclaimer attached");
|
||
|
return DECLINED;
|
||
|
}
|
||
|
|
||
|
$self->qp->version =~ m/([\.\d]+).*/;
|
||
|
my $versionnum = $1;
|
||
|
|
||
|
my @rcpt_hosts = ($self->qp->config("me"), $self->qp->config("rcpthosts"));
|
||
|
my $fromhost = $transaction->sender->host;
|
||
|
unless ( $self->{_args}->{tag_all} ) {
|
||
|
my $fromlocal = 0;
|
||
|
|
||
|
for my $allowed (@rcpt_hosts) {
|
||
|
$allowed =~ s/^\s*(\S+)/$1/;
|
||
|
($fromlocal = 1, last) if (($fromhost eq lc $allowed) or (substr($allowed,0,1) eq "." and
|
||
|
$fromhost =~ m/\Q$allowed\E$/i));
|
||
|
}
|
||
|
|
||
|
if (($versionnum >= 0.26) and ($fromlocal == 0)) {
|
||
|
my $more_rcpt_hosts = $self->qp->config('morercpthosts', 'map');
|
||
|
$fromlocal = 1 if exists $more_rcpt_hosts->{$fromhost};
|
||
|
}
|
||
|
|
||
|
unless ($fromlocal) {
|
||
|
$self->log(LOGDEBUG, "Not from local domain");
|
||
|
return DECLINED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
my $specific = 0;
|
||
|
my @lines;
|
||
|
if ( @lines = $self->read_disclaimer("disclaimer_$fromhost") ) {
|
||
|
$self->log(LOGDEBUG, "Found disclaimer for domain: $fromhost");
|
||
|
$specific = 1;
|
||
|
} elsif ( @lines = $self->read_disclaimer("disclaimer") ) {
|
||
|
$self->log(LOGDEBUG, "Found general disclaimer");
|
||
|
} else {
|
||
|
$self->log(LOGERROR, "No disclaimer found for domain: $fromhost");
|
||
|
return DECLINED;
|
||
|
}
|
||
|
|
||
|
unless ( $self->{_args}->{tag_all} ) {
|
||
|
my $toexternal=0;
|
||
|
foreach my $rcpt ( $transaction->recipients ) {
|
||
|
my $local = 0;
|
||
|
my $host = $rcpt->host;
|
||
|
|
||
|
($toexternal = 1, last) if ( $specific && $host ne $fromhost);
|
||
|
|
||
|
for my $allowed (@rcpt_hosts) {
|
||
|
$allowed =~ s/^\s*(\S+)/$1/;
|
||
|
($local = 1, last) if (($host eq lc $allowed) or (substr($allowed,0,1) eq "." and
|
||
|
$host =~ m/\Q$allowed\E$/i));
|
||
|
}
|
||
|
|
||
|
if (($versionnum >= 0.26) and ($local == 0)) {
|
||
|
my $more_rcpt_hosts = $self->qp->config('morercpthosts', 'map');
|
||
|
$local = 1 if exists $more_rcpt_hosts->{$host};
|
||
|
}
|
||
|
|
||
|
($toexternal = 1, last) unless $local;
|
||
|
}
|
||
|
|
||
|
unless ($toexternal) {
|
||
|
$self->log(LOGDEBUG, "Not to any external domain");
|
||
|
return DECLINED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
my $parser = new MIME::Parser;
|
||
|
$parser->output_under( $self->spool_dir() );
|
||
|
$parser->extract_uuencode(1);
|
||
|
my $ent = $parser->parse_open( $transaction->body_filename() );
|
||
|
|
||
|
$ent->make_multipart( 'mixed', Force => 1 ) if $ent->mime_type ne 'multipart/mixed';
|
||
|
$ent->attach( Data => join("\n", @lines),
|
||
|
Encoding => $self->{_args}->{mime_encoding} || '-SUGGEST',
|
||
|
Filename => $self->{_args}->{mime_filename} || 'disclaimer.txt',
|
||
|
Type => $self->{_args}->{mime_type} || 'text/plain');
|
||
|
if ($ent->parts <= 2) {
|
||
|
$transaction->header->empty();
|
||
|
$transaction->header($ent->head());
|
||
|
}
|
||
|
$transaction->header->replace( 'X-Qpsmtp-Disclaimer', $fromhost );
|
||
|
$self->log(LOGNOTICE, "Attached disclaimer for domain: $fromhost");
|
||
|
|
||
|
open BFN, ">" . $transaction->body_filename();
|
||
|
$ent->print(\*BFN);
|
||
|
close BFN;
|
||
|
$transaction->body_resetpos();
|
||
|
|
||
|
$ent->purge();
|
||
|
rmdir( $parser->output_dir );
|
||
|
|
||
|
return DECLINED;
|
||
|
}
|
||
|
|
||
|
# vi: ft=perl ts=4
|