Support for RFC 1893 - Enhanced Mail System Status Codes
Patch by Hanno Hecker <hah@uu-x.de>. Adds the RFC 1893 status codes to the messages which are returned to the sending client. git-svn-id: https://svn.perl.org/qpsmtpd/branches/0.3x@602 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
5c2c8455d5
commit
1d0f889d3c
621
lib/Qpsmtpd/DSN.pm
Normal file
621
lib/Qpsmtpd/DSN.pm
Normal file
@ -0,0 +1,621 @@
|
|||||||
|
#
|
||||||
|
# Enhanced Mail System Status Codes - RFC 1893
|
||||||
|
#
|
||||||
|
package Qpsmtpd::DSN;
|
||||||
|
use strict;
|
||||||
|
use Qpsmtpd::Constants;
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Qpsmtpd::DSN - Enhanced Mail System Status Codes - RFC 1893
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
The B<Qpsmtpd::DSN> implements the I<Enhanced Mail System Status Codes> from
|
||||||
|
RFC 1893.
|
||||||
|
|
||||||
|
=head1 USAGE
|
||||||
|
|
||||||
|
Any B<qpsmtpd> plugin can access these status codes. All sub routines are used
|
||||||
|
the same way:
|
||||||
|
use Qpsmtpd::DSN;
|
||||||
|
...;
|
||||||
|
return Qpsmtpd::DSN->relaying_denied();
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
return Qpsmtpd::DSN->relaying_denied("Relaying from $ip denied");
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
return Qpsmtpd::DSN->relaying_denied(DENY,"Relaying from $ip denied");
|
||||||
|
|
||||||
|
If no status message was given, it will use the predefined one from the
|
||||||
|
RFC. If the first argument is numeric, it will use this as a return code,
|
||||||
|
else the default return code is used. See below which default return code
|
||||||
|
is used in the different functions.
|
||||||
|
|
||||||
|
The first example will return
|
||||||
|
I<(DENY, "Relaying denied");>
|
||||||
|
the others
|
||||||
|
I<(DENY, "Relaying from $ip denied");>
|
||||||
|
which will be returned to qpsmtpd.
|
||||||
|
|
||||||
|
In those sub routines which don't start with I<addr_, sys_, net_, proto_,
|
||||||
|
media_, sec_> I've added a default message which describes the status better
|
||||||
|
than the RFC message.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
my @rfc1893 = (
|
||||||
|
[
|
||||||
|
"Other or Undefined Status", # x.0.x
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other address status.", # x.1.0
|
||||||
|
"Bad destination mailbox address.", # x.1.1
|
||||||
|
"Bad destination system address.", # x.1.2
|
||||||
|
"Bad destination mailbox address syntax.", # x.1.3
|
||||||
|
"Destination mailbox address ambiguous.", # x.1.4
|
||||||
|
"Destination address valid.", # x.1.5
|
||||||
|
"Destination mailbox has moved, No forwarding address.", # x.1.6
|
||||||
|
"Bad sender's mailbox address syntax.", # x.1.7
|
||||||
|
"Bad sender's system address.", # x.1.8
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other or undefined mailbox status.", # x.2.0
|
||||||
|
"Mailbox disabled, not accepting messages.", # x.2.1
|
||||||
|
"Mailbox full.", # x.2.2
|
||||||
|
"Message length exceeds administrative limit.", # x.2.3
|
||||||
|
"Mailing list expansion problem.", # x.2.4
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other or undefined mail system status.", # x.3.0
|
||||||
|
"Mail system full.", # x.3.1
|
||||||
|
"System not accepting network messages.", # x.3.2
|
||||||
|
"System not capable of selected features.", # x.3.3
|
||||||
|
"Message too big for system.", # x.3.4
|
||||||
|
"System incorrectly configured.", # x.3.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other or undefined network or routing status.", # x.4.0
|
||||||
|
"No answer from host.", # x.4.1
|
||||||
|
"Bad connection.", # x.4.2
|
||||||
|
"Directory server failure.", # x.4.3
|
||||||
|
"Unable to route.", # x.4.4
|
||||||
|
"Mail system congestion.", # x.4.5
|
||||||
|
"Routing loop detected.", # x.4.6
|
||||||
|
"Delivery time expired.", # x.4.7
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other or undefined protocol status.", # x.5.0
|
||||||
|
"Invalid command.", # x.5.1
|
||||||
|
"Syntax error.", # x.5.2
|
||||||
|
"Too many recipients.", # x.5.3
|
||||||
|
"Invalid command arguments.", # x.5.4
|
||||||
|
"Wrong protocol version.", # x.5.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other or undefined media error.", # x.6.0
|
||||||
|
"Media not supported.", # x.6.1
|
||||||
|
"Conversion required and prohibited.", # x.6.2
|
||||||
|
"Conversion required but not supported.", # x.6.3
|
||||||
|
"Conversion with loss performed.", # x.6.4
|
||||||
|
"Conversion Failed.", # x.6.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Other or undefined security status.", # x.7.0
|
||||||
|
"Delivery not authorized, message refused.", # x.7.1
|
||||||
|
"Mailing list expansion prohibited.", # x.7.2
|
||||||
|
"Security conversion required but not possible.", # x.7.3
|
||||||
|
"Security features not supported.", # x.7.4
|
||||||
|
"Cryptographic failure.", # x.7.5
|
||||||
|
"Cryptographic algorithm not supported.", # x.7.6
|
||||||
|
"Message integrity failure.", # x.7.7
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
sub _status {
|
||||||
|
my $return = shift;
|
||||||
|
my $const = Qpsmtpd::Constants::return_code($return);
|
||||||
|
if ($const =~ /^DENYSOFT/) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
elsif ($const =~ /^DENY/) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
elsif ($const eq 'OK' or $const eq 'DONE') {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else { # err .... no :)
|
||||||
|
return 4; # just 2,4,5 are allowed.. temp error by default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _dsn {
|
||||||
|
my ($self,$return,$reason,$default,$subject,$detail) = @_;
|
||||||
|
if (!defined $return) {
|
||||||
|
$return = $default;
|
||||||
|
}
|
||||||
|
elsif ($return !~ /^\d+$/) {
|
||||||
|
$reason = $return;
|
||||||
|
$return = $default;
|
||||||
|
}
|
||||||
|
my $msg = $rfc1893[$subject][$detail];
|
||||||
|
unless (defined $msg) {
|
||||||
|
$detail = 0;
|
||||||
|
$msg = $rfc1893[$subject][$detail];
|
||||||
|
unless (defined $msg) {
|
||||||
|
$subject = 0;
|
||||||
|
$msg = $rfc1893[$subject][$detail];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my $class = &_status($return);
|
||||||
|
if (defined $reason) {
|
||||||
|
$msg = $reason;
|
||||||
|
}
|
||||||
|
return ($return, "$msg (#$class.$subject.$detail)");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub unspecified { shift->_dsn(shift,shift,DENYSOFT,0,0); }
|
||||||
|
|
||||||
|
=head1 ADDRESS STATUS
|
||||||
|
|
||||||
|
=over 9
|
||||||
|
|
||||||
|
=item addr_unspecified
|
||||||
|
|
||||||
|
X.1.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_unspecified { shift->_dsn(shift,shift,DENYSOFT,1,0); }
|
||||||
|
|
||||||
|
=item no_such_user, addr_bad_dest_mbox
|
||||||
|
|
||||||
|
X.1.1
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub no_such_user { shift->_dsn(shift,(shift||"No such user"),DENY,1,1); }
|
||||||
|
sub addr_bad_dest_mbox { shift->_dsn(shift,shift,DENY,1,1); }
|
||||||
|
|
||||||
|
=item addr_bad_dest_system
|
||||||
|
|
||||||
|
X.1.2
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_bad_dest_system { shift->_dsn(shift,shift,DENY,1,2); }
|
||||||
|
|
||||||
|
=item addr_bad_dest_syntax
|
||||||
|
|
||||||
|
X.1.3
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_bad_dest_syntax { shift->_dsn(shift,shift,DENY,1,3); }
|
||||||
|
|
||||||
|
=item addr_dest_ambigous
|
||||||
|
|
||||||
|
X.1.4
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_dest_ambigous { shift->_dsn(shift,shift,DENYSOFT,1,4); }
|
||||||
|
|
||||||
|
=item addr_rcpt_ok
|
||||||
|
|
||||||
|
X.1.5
|
||||||
|
default: OK
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
# XXX: do we need this? Maybe in all address verifying plugins?
|
||||||
|
sub addr_rcpt_ok { shift->_dsn(shift,shift,OK,1,5); }
|
||||||
|
|
||||||
|
=item addr_mbox_moved
|
||||||
|
|
||||||
|
X.1.6
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_mbox_moved { shift->_dsn(shift,shift,DENY,1,6); }
|
||||||
|
|
||||||
|
=item addr_bad_from_syntax
|
||||||
|
|
||||||
|
X.1.7
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_bad_from_syntax { shift->_dsn(shift,shift,DENY,1,7); }
|
||||||
|
|
||||||
|
=item addr_bad_from_system
|
||||||
|
|
||||||
|
X.1.8
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addr_bad_from_system { shift->_dsn(shift,shift,DENY,1,8); }
|
||||||
|
|
||||||
|
=head1 MAILBOX STATUS
|
||||||
|
|
||||||
|
=over 5
|
||||||
|
|
||||||
|
=item mbox_unspecified
|
||||||
|
|
||||||
|
X.2.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub mbox_unspecified { shift->_dsn(shift,shift,DENYSOFT,2,0); }
|
||||||
|
|
||||||
|
=item mbox_disabled
|
||||||
|
|
||||||
|
X.2.1
|
||||||
|
default: DENY ...but RFC says:
|
||||||
|
The mailbox exists, but is not accepting messages. This may
|
||||||
|
be a permanent error if the mailbox will never be re-enabled
|
||||||
|
or a transient error if the mailbox is only temporarily
|
||||||
|
disabled.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub mbox_disabled { shift->_dsn(shift,shift,DENY,2,1); }
|
||||||
|
|
||||||
|
=item mbox_full
|
||||||
|
|
||||||
|
X.2.2
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub mbox_full { shift->_dsn(shift,shift,DENYSOFT,2,2); }
|
||||||
|
|
||||||
|
=item mbox_msg_too_long
|
||||||
|
|
||||||
|
X.2.3
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub mbox_msg_too_long { shift->_dsn(shift,shift,DENY,2,3); }
|
||||||
|
|
||||||
|
=item mbox_list_expansion_problem
|
||||||
|
|
||||||
|
X.2.4
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub mbox_list_expansion_problem { shift->_dsn(shift,shift,DENYSOFT,2,4); }
|
||||||
|
|
||||||
|
=head1 MAIL SYSTEM STATUS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item sys_unspecified
|
||||||
|
|
||||||
|
X.3.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sys_unspecified { shift->_dsn(shift,shift,DENYSOFT,3,0); }
|
||||||
|
|
||||||
|
=item sys_disk_full
|
||||||
|
|
||||||
|
X.3.1
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sys_disk_full { shift->_dsn(shift,shift,DENYSOFT,3,1); }
|
||||||
|
|
||||||
|
=item sys_not_accepting_mail
|
||||||
|
|
||||||
|
X.3.2
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sys_not_accepting_mail { shift->_dsn(shift,shift,DENYSOFT,3,2); }
|
||||||
|
|
||||||
|
=item sys_not_supported
|
||||||
|
|
||||||
|
X.3.3
|
||||||
|
default: DENYSOFT
|
||||||
|
Selected features specified for the message are not
|
||||||
|
supported by the destination system. This can occur in
|
||||||
|
gateways when features from one domain cannot be mapped onto
|
||||||
|
the supported feature in another.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sys_not_supported { shift->_dsn(shift,shift,DENYSOFT,3,3); }
|
||||||
|
|
||||||
|
=item sys_msg_too_big
|
||||||
|
|
||||||
|
X.3.4
|
||||||
|
default DENY
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sys_msg_too_big { shift->_dsn(shift,shift,DENY,3,4); }
|
||||||
|
|
||||||
|
=head1 NETWORK AND ROUTING STATUS
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item net_unspecified
|
||||||
|
|
||||||
|
X.4.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub net_unspecified { shift->_dsn(shift,shift,DENYSOFT,4,0); }
|
||||||
|
|
||||||
|
# not useful # sub net_no_answer { shift->_dsn(shift,shift,4,1); }
|
||||||
|
# not useful # sub net_bad_connection { shift->_dsn(shift,shift,4,2); }
|
||||||
|
|
||||||
|
=item net_directory_server_failed, temp_resolver_failed
|
||||||
|
|
||||||
|
X.4.3
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub temp_resolver_failed {
|
||||||
|
shift->_dsn(shift,
|
||||||
|
(shift || "Temporary address resolution failure"),
|
||||||
|
DENYSOFT,4,3);
|
||||||
|
}
|
||||||
|
sub net_directory_server_failed { shift->_dsn(shift,shift,DENYSOFT,4,3); }
|
||||||
|
|
||||||
|
# not useful # sub net_unable_to_route { shift->_dsn(shift,shift,4,4); }
|
||||||
|
|
||||||
|
=item net_system_congested
|
||||||
|
|
||||||
|
X.4.5
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub net_system_congested { shift->_dsn(shift,shift,DENYSOFT,4,5); }
|
||||||
|
|
||||||
|
=item net_routing_loop, too_many_hops
|
||||||
|
|
||||||
|
X.4.6
|
||||||
|
default: DENY, but RFC says:
|
||||||
|
A routing loop caused the message to be forwarded too many
|
||||||
|
times, either because of incorrect routing tables or a user
|
||||||
|
forwarding loop. This is useful only as a persistent
|
||||||
|
transient error.
|
||||||
|
|
||||||
|
Why do we want to DENYSOFT something like this?
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub net_routing_loop { shift->_dsn(shift,shift,DENY,4,6); }
|
||||||
|
sub too_many_hops { shift->_dsn(shift,(shift || "Too many hops"),DENY,4,6,); }
|
||||||
|
# not useful # sub delivery_time_expired { shift->_dsn(shift,shift,4,7); }
|
||||||
|
|
||||||
|
=head1 MAIL DELIVERY PROTOCOL STATUS
|
||||||
|
|
||||||
|
=over 6
|
||||||
|
|
||||||
|
=item proto_unspecified
|
||||||
|
|
||||||
|
X.5.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub proto_unspecified { shift->_dsn(shift,shift,DENYSOFT,5,0); }
|
||||||
|
|
||||||
|
=item proto_invalid_command
|
||||||
|
|
||||||
|
X.5.1
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub proto_invalid_command { shift->_dsn(shift,shift,DENY,5,1); }
|
||||||
|
|
||||||
|
=item proto_syntax_error
|
||||||
|
|
||||||
|
X.5.2
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub proto_syntax_error { shift->_dsn(shift,shift,DENY,5,2); }
|
||||||
|
|
||||||
|
=item proto_rcpt_list_too_long, too_many_rcpts
|
||||||
|
|
||||||
|
X.5.3
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub proto_rcpt_list_too_long { shift->_dsn(shift,shift,DENYSOFT,5,3); }
|
||||||
|
sub too_many_rcpts { shift->_dsn(shift,shift,DENYSOFT,5,3); }
|
||||||
|
|
||||||
|
=item proto_invalid_cmd_args
|
||||||
|
|
||||||
|
X.5.4
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub proto_invalid_cmd_args { shift->_dsn(shift,shift,DENY,5,4); }
|
||||||
|
|
||||||
|
=item proto_wrong_version
|
||||||
|
|
||||||
|
X.5.5
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub proto_wrong_version { shift->_dsn(shift,shift,DENYSOFT,5,5); }
|
||||||
|
|
||||||
|
=head1 MESSAGE CONTENT OR MESSAGE MEDIA STATUS
|
||||||
|
|
||||||
|
=over 5
|
||||||
|
|
||||||
|
=item media_unspecified
|
||||||
|
|
||||||
|
X.6.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub media_unspecified { shift->_dsn(shift,shift,DENYSOFT,6,0); }
|
||||||
|
|
||||||
|
=item media_unsupported
|
||||||
|
|
||||||
|
X.6.1
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub media_unsupported { shift->_dsn(shift,shift,DENY,6,1); }
|
||||||
|
|
||||||
|
=item media_conv_prohibited
|
||||||
|
|
||||||
|
X.6.2
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub media_conv_prohibited { shift->_dsn(shift,shift,DENY,6,2); }
|
||||||
|
|
||||||
|
=item media_conv_unsupported
|
||||||
|
|
||||||
|
X.6.3
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub media_conv_unsupported { shift->_dsn(shift,shift,DENYSOFT,6,3); }
|
||||||
|
|
||||||
|
=item media_conv_lossy
|
||||||
|
|
||||||
|
X.6.4
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub media_conv_lossy { shift->_dsn(shift,shift,DENYSOFT,6,4); }
|
||||||
|
|
||||||
|
=head1 SECURITY OR POLICY STATUS
|
||||||
|
|
||||||
|
=over 8
|
||||||
|
|
||||||
|
=item sec_unspecified
|
||||||
|
|
||||||
|
X.7.0
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_unspecified { shift->_dsn(shift,shift,DENYSOFT,7,0); }
|
||||||
|
|
||||||
|
=item sec_sender_unauthorized, bad_sender_ip, relaying_denied
|
||||||
|
|
||||||
|
X.7.1
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_sender_unauthorized { shift->_dsn(shift,shift,DENY,7,1); }
|
||||||
|
sub bad_sender_ip {
|
||||||
|
shift->_dsn(shift,(shift || "Bad sender's IP"),DENY,7,1,);
|
||||||
|
}
|
||||||
|
sub relaying_denied {
|
||||||
|
shift->_dsn(shift,(shift || "Relaying denied"),DENY,7,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
=item sec_list_dest_prohibited
|
||||||
|
|
||||||
|
X.7.2
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_list_dest_prohibited { shift->_dsn(shift,shift,DENY,7,2); }
|
||||||
|
|
||||||
|
=item sec_conv_failed
|
||||||
|
|
||||||
|
X.7.3
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_conv_failed { shift->_dsn(shift,shift,DENY,7,3); }
|
||||||
|
|
||||||
|
=item sec_feature_unsupported
|
||||||
|
|
||||||
|
X.7.4
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_feature_unsupported { shift->_dsn(shift,shift,DENY,7,4); }
|
||||||
|
|
||||||
|
=item sec_crypto_failure
|
||||||
|
|
||||||
|
X.7.5
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_crypto_failure { shift->_dsn(shift,shift,DENY,7,5); }
|
||||||
|
|
||||||
|
=item sec_crypto_algorithm_unsupported
|
||||||
|
|
||||||
|
X.7.6
|
||||||
|
default: DENYSOFT
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_crypto_algorithm_unsupported { shift->_dsn(shift,shift,DENYSOFT,7,6); }
|
||||||
|
|
||||||
|
=item sec_msg_integrity_failure
|
||||||
|
|
||||||
|
X.7.7
|
||||||
|
default: DENY
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub sec_msg_integrity_failure { shift->_dsn(shift,shift,DENY,7,7); }
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
# vim: st=4 sw=4 expandtab
|
@ -1,4 +1,5 @@
|
|||||||
# this plugin checks the badrcptto config (like badmailfrom for rcpt address)
|
# this plugin checks the badrcptto config (like badmailfrom for rcpt address)
|
||||||
|
use Qpsmtpd::DSN;
|
||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $recipient) = @_;
|
my ($self, $transaction, $recipient) = @_;
|
||||||
@ -9,9 +10,9 @@ sub hook_rcpt {
|
|||||||
for my $bad (@badrcptto) {
|
for my $bad (@badrcptto) {
|
||||||
$bad = lc $bad;
|
$bad = lc $bad;
|
||||||
$bad =~ s/^\s*(\S+)/$1/;
|
$bad =~ s/^\s*(\S+)/$1/;
|
||||||
return (DENY, "mail to $bad not accepted here")
|
return Qpsmtpd::DSN->no_such_user("mail to $bad not accepted here")
|
||||||
if $bad eq $from;
|
if $bad eq $from;
|
||||||
return (DENY, "mail to $bad not accepted here")
|
return Qpsmtpd::DSN->no_such_user("mail to $bad not accepted here")
|
||||||
if substr($bad,0,1) eq '@' && $bad eq "\@$host";
|
if substr($bad,0,1) eq '@' && $bad eq "\@$host";
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return (DECLINED);
|
||||||
|
@ -25,8 +25,9 @@ Written by Keith C. Ivey
|
|||||||
Released to the public domain, 17 June 2005.
|
Released to the public domain, 17 June 2005.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
use Qpsmtpd::DSN;
|
||||||
|
|
||||||
sub register {
|
sub init {
|
||||||
my ($self, $qp, @args) = @_;
|
my ($self, $qp, @args) = @_;
|
||||||
|
|
||||||
$self->{_max_hops} = $args[0] || 100;
|
$self->{_max_hops} = $args[0] || 100;
|
||||||
@ -45,7 +46,8 @@ sub hook_data_post {
|
|||||||
$transaction->header->get('Delivered-To');
|
$transaction->header->get('Delivered-To');
|
||||||
|
|
||||||
if ( $hops >= $self->{_max_hops} ) {
|
if ( $hops >= $self->{_max_hops} ) {
|
||||||
return DENY, "Too many hops. This message is looping.";
|
# default of too_many_hops is DENY, see comment in POD of Qpsmtpd::DSN
|
||||||
|
return Qpsmtpd::DSN->too_many_hops();
|
||||||
}
|
}
|
||||||
|
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#
|
#
|
||||||
# It should be configured to be run _LAST_!
|
# It should be configured to be run _LAST_!
|
||||||
#
|
#
|
||||||
|
use Qpsmtpd::DSN;
|
||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $recipient) = @_;
|
my ($self, $transaction, $recipient) = @_;
|
||||||
@ -30,6 +31,8 @@ sub hook_rcpt {
|
|||||||
return (OK);
|
return (OK);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (DENY);
|
# default of relaying_denied is obviously DENY,
|
||||||
|
# we use the default "Relaying denied" message...
|
||||||
|
return Qpsmtpd::DSN->relaying_denied();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use Qpsmtpd::DSN;
|
||||||
use Net::DNS qw(mx);
|
use Net::DNS qw(mx);
|
||||||
use Socket;
|
use Socket;
|
||||||
|
|
||||||
@ -17,15 +18,21 @@ sub hook_mail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sender->format ne "<>"
|
if ($sender ne "<>"
|
||||||
and $self->qp->config("require_resolvable_fromhost")
|
and $self->qp->config("require_resolvable_fromhost")
|
||||||
and !$self->check_dns($sender->host)
|
and !$self->check_dns($sender->host)) {
|
||||||
and return (DENYSOFT,
|
if ($sender->host) {
|
||||||
($sender->host
|
# default of temp_resolver_failed is DENYSOFT
|
||||||
? "Could not resolve ". $sender->host
|
return Qpsmtpd::DSN->temp_resolver_failed("Could not resolve " . $sender->host);
|
||||||
: "FQDN required in the envelope sender"));
|
}
|
||||||
|
else {
|
||||||
return DECLINED;
|
# default of addr_bad_from_system is DENY, we use DENYSOFT here to
|
||||||
|
# get the same behaviour as without Qpsmtpd::DSN...
|
||||||
|
return Qpsmtpd::DSN->addr_bad_from_system(DENYSOFT,
|
||||||
|
"FQDN required in the envelope sender");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DECLINED;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ Make the "subject munge string" configurable
|
|||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
|
||||||
|
use Qpsmtpd::DSN;
|
||||||
use Socket qw(:DEFAULT :crlf);
|
use Socket qw(:DEFAULT :crlf);
|
||||||
use IO::Handle;
|
use IO::Handle;
|
||||||
|
|
||||||
@ -225,7 +226,8 @@ sub check_spam_reject {
|
|||||||
my $score = $self->get_spam_score($transaction) or return DECLINED;
|
my $score = $self->get_spam_score($transaction) or return DECLINED;
|
||||||
$self->log(LOGDEBUG, "check_spam_reject: score=$score");
|
$self->log(LOGDEBUG, "check_spam_reject: score=$score");
|
||||||
|
|
||||||
return (DENY, "spam score exceeded threshold")
|
# default of media_unsupported is DENY, so just change the message
|
||||||
|
return Qpsmtpd::DSN->media_unsupported("spam score exceeded threshold")
|
||||||
if $score >= $self->{_args}->{reject_threshold};
|
if $score >= $self->{_args}->{reject_threshold};
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "check_spam_reject: passed");
|
$self->log(LOGDEBUG, "check_spam_reject: passed");
|
||||||
|
Loading…
Reference in New Issue
Block a user