49dc8bc117
added log messages at each exit point added tests added reject_type option (defer -vs- deny) added named argument parsing
115 lines
2.9 KiB
Perl
115 lines
2.9 KiB
Perl
#!perl -w
|
|
|
|
=head1 NAME
|
|
|
|
check_basicheaders - Make sure both From and Date headers are present, and
|
|
do optional range checking on the Date header.
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Rejects messages that do not have a From or Date header or are completely
|
|
empty.
|
|
|
|
Can also reject messages where the date in the Date header is more than
|
|
some number of the days in the past or future.
|
|
|
|
=head1 CONFIGURATION
|
|
|
|
The following optional parameters exist:
|
|
|
|
=head2 days
|
|
|
|
The number of days in the future or past beyond which to reject messages. When
|
|
unset, messages are not rejected based on the date.
|
|
|
|
check_basicheaders [ days 3 ]
|
|
|
|
=head2 reject_type
|
|
|
|
Whether to issue a permanent or temporary rejection. The default is permanent.
|
|
|
|
check_basicheaders reject_type [ temp | perm ]
|
|
|
|
Switching to a temporary rejection is most useful when testing the plugin. It
|
|
allows an administrator to watch for a test period and make sure no valid mail
|
|
is getting rejected.
|
|
|
|
=head1 AUTHOR
|
|
|
|
2004 - Written by Jim Winstead Jr.
|
|
|
|
2012 - added logging, named arguments, reject_type, tests - Matt Simerson
|
|
|
|
=head1 LICENSE
|
|
|
|
Released to the public domain, 26 March 2004.
|
|
|
|
=cut
|
|
|
|
use Date::Parse qw(str2time);
|
|
|
|
sub register {
|
|
my ($self, $qp, @args) = @_;
|
|
|
|
if ( @args == 1 ) {
|
|
$self->log(LOGWARN, "deprecated arguments. Update your arguments to this plugin");
|
|
$self->{_args}{days} = $args[0];
|
|
}
|
|
elsif ( @args % 2 ) {
|
|
$self->log(LOGWARN, "invalid arguments");
|
|
}
|
|
else {
|
|
$self->{_args} = { @args };
|
|
};
|
|
}
|
|
|
|
sub hook_data_post {
|
|
my ($self, $transaction) = @_;
|
|
|
|
my $deny = $self->{_args}{reject_type} eq 'temp' ? DENYSOFT : DENY;
|
|
|
|
if ( $transaction->data_size == 0 ) {
|
|
$self->log(LOGINFO, "fail: no data");
|
|
return ($deny, "You have to send some data first");
|
|
};
|
|
|
|
my $header = $transaction->header or do {
|
|
$self->log(LOGINFO, "fail: no headers");
|
|
return ($deny, "missing header");
|
|
};
|
|
|
|
if ( ! $header->get('From') ) {
|
|
$self->log(LOGINFO, "fail: no from");
|
|
return ($deny, "We require a valid From header")
|
|
};
|
|
|
|
my $date = $header->get('Date') or do {
|
|
$self->log(LOGINFO, "fail: no date");
|
|
return ($deny, "We require a valid Date header");
|
|
};
|
|
|
|
my $days = $self->{_args}{days};
|
|
if ( ! defined $days ) {
|
|
$self->log(LOGINFO, "pass: no days arg");
|
|
return (DECLINED);
|
|
};
|
|
|
|
my $ts = str2time($date) or do {
|
|
$self->log(LOGINFO, "skip: date not parseable ($date)");
|
|
return (DECLINED);
|
|
};
|
|
|
|
if ( $ts < time - ($days*24*3600) ) {
|
|
$self->log(LOGINFO, "fail: date too old ($date)");
|
|
return ($deny, "The Date in the header is too far in the past")
|
|
};
|
|
|
|
if ( $ts > time + ($days*24*3600) ) {
|
|
$self->log(LOGINFO, "fail: date in future ($date)");
|
|
return ($deny, "The Date in the header is too far in the future")
|
|
};
|
|
|
|
$self->log(LOGINFO, "pass");
|
|
return (DECLINED);
|
|
}
|