File: //usr/share/perl5/vendor_perl/Amavis/In/Message/PerRecip.pm
package Amavis::In::Message::PerRecip;
use strict;
use re 'taint';
BEGIN {
require Exporter;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
$VERSION = '2.412';
@ISA = qw(Exporter);
}
use Amavis::Conf qw(:platform);
use Amavis::Util qw(setting_by_given_contents_category_all
setting_by_given_contents_category cmp_ccat);
sub new # NOTE: this class is a list, not a hash
{ my $class = $_[0]; bless [(undef) x 42], $class }
# subs to set or access individual elements of a n-tuple by name
sub recip_addr # unquoted recipient envelope e-mail address
{ @_<2 ? shift->[0] : ($_[0]->[0] = $_[1]) }
sub recip_addr_smtp # SMTP-encoded recipient envelope e-mail address in <>
{ @_<2 ? shift->[1] : ($_[0]->[1] = $_[1]) }
sub recip_addr_modified # recip. addr. with possible addr. extension inserted
{ @_<2 ? shift->[2] : ($_[0]->[2] = $_[1]) }
sub recip_is_local # recip_addr matches @local_domains_maps
{ @_<2 ? shift->[3] : ($_[0]->[3] = $_[1]) }
sub recip_maddr_id # maddr.id field from SQL corresponding to recip_addr_smtp
{ @_<2 ? shift->[4] : ($_[0]->[4] = $_[1]) }
sub recip_maddr_id_orig # maddr.id field from SQL corresponding to dsn_orcpt
{ @_<2 ? shift->[5] : ($_[0]->[5] = $_[1]) }
sub recip_penpals_related # mail_id of a previous correspondence
{ @_<2 ? shift->[6] : ($_[0]->[6] = $_[1]) }
sub recip_penpals_age # penpals age in seconds if SQL or Redis is enabled
{ @_<2 ? shift->[7] : ($_[0]->[7] = $_[1]) }
sub recip_penpals_score # penpals score (info, also added to spam_level)
{ @_<2 ? shift->[8] : ($_[0]->[8] = $_[1]) }
sub dsn_notify # ESMTP RCPT command NOTIFY option (DSN-RFC 3461, listref)
{ @_<2 ? shift->[9] : ($_[0]->[9] = $_[1]) }
sub dsn_orcpt # ESMTP RCPT command ORCPT option (decoded: RFC 3461, RFC 6533)
{ @_<2 ? shift->[10] : ($_[0]->[10] = $_[1]) }
sub dsn_suppress_reason # if defined disable sending DSN and supply a reason
{ @_<2 ? shift->[11] : ($_[0]->[11] = $_[1]) }
sub recip_destiny # D_REJECT, D_BOUNCE, D_DISCARD, D_PASS
{ @_<2 ? shift->[12] : ($_[0]->[12] = $_[1]) }
sub recip_done # false: not done, true: done (1: faked, 2: truly sent)
{ @_<2 ? shift->[13] : ($_[0]->[13] = $_[1]) }
sub recip_smtp_response # RFC 5321 response (3-digit + enhanced resp + text)
{ @_<2 ? shift->[14] : ($_[0]->[14] = $_[1]) }
sub recip_remote_mta_smtp_response # smtp response as issued by remote MTA
{ @_<2 ? shift->[15] : ($_[0]->[15] = $_[1]) }
sub recip_remote_mta # remote MTA that issued the smtp response
{ @_<2 ? shift->[16] : ($_[0]->[16] = $_[1]) }
sub recip_tagged # message was tagged by address extension or Subject or X-Spam
{ @_<2 ? shift->[17] : ($_[0]->[17] = $_[1]) }
sub recip_mbxname # mailbox name or file when known (local:, bsmtp: or sql:)
{ @_<2 ? shift->[18] : ($_[0]->[18] = $_[1]) }
sub recip_whitelisted_sender # recip considers this sender whitelisted
{ @_<2 ? shift->[19] : ($_[0]->[19] = $_[1]) }
sub recip_blacklisted_sender # recip considers this sender blacklisted
{ @_<2 ? shift->[20] : ($_[0]->[20] = $_[1]) }
sub bypass_virus_checks # boolean: virus checks to be bypassed for this recip
{ @_<2 ? shift->[21] : ($_[0]->[21] = $_[1]) }
sub bypass_banned_checks # bool: ban checks are to be bypassed for this recip
{ @_<2 ? shift->[22] : ($_[0]->[22] = $_[1]) }
sub bypass_spam_checks # boolean: spam checks are to be bypassed for this recip
{ @_<2 ? shift->[23] : ($_[0]->[23] = $_[1]) }
sub banned_parts # banned part descriptions (ref to a list of banned parts)
{ @_<2 ? shift->[24] : ($_[0]->[24] = $_[1]) }
sub banned_parts_as_attr # banned part descriptions - newer syntax (listref)
{ @_<2 ? shift->[25] : ($_[0]->[25] = $_[1]) }
sub banning_rule_key # matching banned rules (lookup table keys) (ref to list)
{ @_<2 ? shift->[26] : ($_[0]->[26] = $_[1]) }
sub banning_rule_comment #comments (or whole expr) from banning_rule_key regexp
{ @_<2 ? shift->[27] : ($_[0]->[27] = $_[1]) }
sub banning_reason_short # just one banned part leaf name with a rule comment
{ @_<2 ? shift->[28] : ($_[0]->[28] = $_[1]) }
sub banning_rule_rhs # a right-hand side of matching rules (a ref to a list)
{ @_<2 ? shift->[29] : ($_[0]->[29] = $_[1]) }
sub mail_body_mangle # mail body is being modified (and how) (e.g. defanged)
{ @_<2 ? shift->[30] : ($_[0]->[30] = $_[1]) }
sub contents_category # sorted listref of "major,minor" strings(category types)
{ @_<2 ? shift->[31] : ($_[0]->[31] = $_[1]) }
sub blocking_ccat # category type most responsible for blocking msg, or undef
{ @_<2 ? shift->[32] : ($_[0]->[32] = $_[1]) }
sub user_id # listref of recipient IDs from a lookup, e.g. SQL field users.id
{ @_<2 ? shift->[33] : ($_[0]->[33] = $_[1]) }
sub user_policy_id # recipient's policy ID, e.g. SQL field users.policy_id
{ @_<2 ? shift->[34] : ($_[0]->[34] = $_[1]) }
sub courier_control_file # path to control file containing this recipient
{ @_<2 ? shift->[35] : ($_[0]->[35] = $_[1]) }
sub courier_recip_index # index of recipient within control file
{ @_<2 ? shift->[36] : ($_[0]->[36] = $_[1]) }
sub delivery_method # delivery method, or empty for implicit delivery (milter)
{ @_<2 ? shift->[37] : ($_[0]->[37] = $_[1]) }
sub spam_level # spam score as returned by spam scanners, ham near 0, spam 5
{ @_<2 ? shift->[38] : ($_[0]->[38] = $_[1]) }
sub spam_tests # a listref of r/o stringrefs, each: t1=score1,t2=score2,..
{ @_<2 ? shift->[39] : ($_[0]->[39] = $_[1]) }
# per-recipient spam info - when undefined consult a per-message counterpart
sub spam_report # SA terse report of tests hit (for header section reports)
{ @_<2 ? shift->[40] : ($_[0]->[40] = $_[1]) }
sub spam_summary # SA summary of tests hit for standard body reports
{ @_<2 ? shift->[41] : ($_[0]->[41] = $_[1]) }
sub recip_final_addr { # return recip_addr_modified if set, else recip_addr
my $self = shift;
my $newaddr = $self->recip_addr_modified;
defined $newaddr ? $newaddr : $self->recip_addr;
}
# The contents_category list is a sorted list of strings, each of the form
# "major" or "major,minor", where major and minor are numbers, representing
# major and minor category type. Sort order is descending by numeric values,
# major first, and subordered by a minor value. When an entry "major,minor"
# is added, an entry "major" is added automatically (minor implied to be 0).
# A string "major" means the same as "major,0". See CC_* constants for major
# category types. Minor category types semantics is specific to each major
# category, higher number represent more important finding than a lower number.
# add new findings to the contents_category list
#
sub add_contents_category {
my($self, $major,$minor) = @_;
my $aref = $self->contents_category || [];
# major category is always inserted, but "$major,$minor" only if minor>0
if (defined $minor && $minor > 0) { # straight insertion of "$major,$minor"
my $el = sprintf("%d,%d",$major,$minor); my $j=0;
for (@$aref) { if (cmp_ccat($_,$el) <= 0) { last } else { $j++ } };
if ($j > $#{$aref}) { push(@$aref,$el) } # append
elsif (cmp_ccat($aref->[$j],$el) != 0) { splice(@$aref,$j,0,$el) }
}
# straight insertion of "$major" into an ordered array (descending order)
my $el = sprintf("%d",$major); my $j=0;
for (@$aref) { if (cmp_ccat($_,$el) <= 0) { last } else { $j++ } };
if ($j > $#{$aref}) { push(@$aref,$el) } # append
elsif (cmp_ccat($aref->[$j],$el) != 0)
{ splice(@$aref,$j,0,$el) } # insert at index $j
$self->contents_category($aref);
}
# is the "$major,$minor" category in the list?
#
sub is_in_contents_category {
my($self, $major,$minor) = @_;
my $el = sprintf('%d,%d', $major,$minor);
my $aref = $self->contents_category;
!defined($aref) ? undef : scalar(grep(cmp_ccat($_,$el) == 0, @$aref));
}
# get a setting corresponding to the most important contents category;
# i.e. the highest entry from the category list for which a corresponding entry
# in the associative array of settings exists determines returned setting;
#
sub setting_by_main_contents_category {
my($self, @settings_href_list) = @_;
return undef if !@settings_href_list;
my $aref = $self->contents_category;
setting_by_given_contents_category($aref, @settings_href_list);
}
# get a list of settings corresponding to all relevant contents categories,
# sorted from the most important to the least important entry; entries which
# have no corresponding setting are not included in the list
#
sub setting_by_main_contents_category_all {
my($self, @settings_href_list) = @_;
return undef if !@settings_href_list;
my $aref = $self->contents_category;
setting_by_given_contents_category_all($aref, @settings_href_list);
}
sub setting_by_blocking_contents_category {
my($self, @settings_href_list) = @_;
my $blocking_ccat = $self->blocking_ccat;
!defined($blocking_ccat) ? undef
: setting_by_given_contents_category($blocking_ccat, @settings_href_list);
}
sub setting_by_contents_category {
my($self, @settings_href_list) = @_;
my $blocking_ccat = $self->blocking_ccat;
!defined($blocking_ccat)
? $self->setting_by_main_contents_category(@settings_href_list)
: setting_by_given_contents_category($blocking_ccat, @settings_href_list);
}
1;