Hide Show 22 lines of Pod
our
@ISA
=
qw(Mail::SpamAssassin::Plugin)
;
sub
new {
my
$class
=
shift
;
my
$mailsaobject
=
shift
;
$class
=
ref
(
$class
) ||
$class
;
my
$self
=
$class
->SUPER::new(
$mailsaobject
);
bless
(
$self
,
$class
);
$self
->register_eval_rule (
"check_for_spf_pass"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_neutral"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_none"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_fail"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_softfail"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_permerror"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_temperror"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_pass"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_neutral"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_none"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_fail"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_softfail"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_permerror"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_helo_temperror"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_welcomelist_from"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_spf_whitelist_from"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_def_spf_welcomelist_from"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_for_def_spf_whitelist_from"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->register_eval_rule (
"check_spf_skipped_noenvfrom"
,
$Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS
);
$self
->set_config(
$mailsaobject
->{conf});
return
$self
;
}
sub
set_config {
my
(
$self
,
$conf
) =
@_
;
my
@cmds
;
Hide Show 48 lines of Pod
push
(
@cmds
, {
setting
=>
'welcomelist_from_spf'
,
aliases
=> [
'whitelist_from_spf'
],
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST
});
push
(
@cmds
, {
setting
=>
'def_welcomelist_from_spf'
,
aliases
=> [
'def_whitelist_from_spf'
],
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST
});
push
(
@cmds
, {
setting
=>
'unwelcomelist_from_spf'
,
aliases
=> [
'unwhitelist_from_spf'
],
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST
,
code
=>
sub
{
my
(
$self
,
$key
,
$value
,
$line
) =
@_
;
unless
(
defined
$value
&&
$value
!~ /^$/) {
return
$Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE
;
}
unless
(
$value
=~ /^(?:\S+(?:\s+\S+)*)$/) {
return
$Mail::SpamAssassin::Conf::INVALID_VALUE
;
}
$self
->{parser}->remove_from_addrlist(
'welcomelist_from_spf'
,
split
(/\s+/,
$value
));
$self
->{parser}->remove_from_addrlist(
'def_welcomelist_from_spf'
,
split
(/\s+/,
$value
));
}
});
Hide Show 15 lines of Pod
push
(
@cmds
, {
setting
=>
'spf_timeout'
,
is_admin
=> 1,
default
=> 5,
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_DURATION
});
Hide Show 15 lines of Pod
push
(
@cmds
, {
setting
=>
'ignore_received_spf_header'
,
is_admin
=> 1,
default
=> 0,
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_BOOL
,
});
Hide Show 16 lines of Pod
push
(
@cmds
, {
setting
=>
'use_newest_received_spf_header'
,
is_admin
=> 1,
default
=> 0,
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_BOOL
,
});
push
(
@cmds
, {
setting
=>
'do_not_use_mail_spf'
,
is_admin
=> 1,
default
=> 0,
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_BOOL
,
});
push
(
@cmds
, {
setting
=>
'do_not_use_mail_spf_query'
,
is_admin
=> 1,
default
=> 1,
type
=>
$Mail::SpamAssassin::Conf::CONF_TYPE_BOOL
,
});
$conf
->{parser}->register_commands(\
@cmds
);
}
Hide Show 6 lines of Pod
sub
has_check_for_spf_errors { 1 }
Hide Show 6 lines of Pod
sub
has_check_spf_skipped_noenvfrom { 1 }
sub
parsed_metadata {
my
(
$self
,
$opts
) =
@_
;
$self
->_get_sender(
$opts
->{permsgstatus});
return
1;
}
sub
check_for_spf_pass {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
return
$scanner
->{spf_pass} ? 1 : 0;
}
sub
check_for_spf_neutral {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
return
$scanner
->{spf_neutral} ? 1 : 0;
}
sub
check_for_spf_none {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
return
$scanner
->{spf_none} ? 1 : 0;
}
sub
check_for_spf_fail {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
if
(
$scanner
->{spf_failure_comment}) {
$scanner
->test_log (
$scanner
->{spf_failure_comment});
}
return
$scanner
->{spf_fail} ? 1 : 0;
}
sub
check_for_spf_softfail {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
return
$scanner
->{spf_softfail} ? 1 : 0;
}
sub
check_for_spf_permerror {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
return
$scanner
->{spf_permerror} ? 1 : 0;
}
sub
check_for_spf_temperror {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
return
$scanner
->{spf_temperror} ? 1 : 0;
}
sub
check_for_spf_helo_pass {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
return
$scanner
->{spf_helo_pass} ? 1 : 0;
}
sub
check_for_spf_helo_neutral {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
return
$scanner
->{spf_helo_neutral} ? 1 : 0;
}
sub
check_for_spf_helo_none {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
return
$scanner
->{spf_helo_none} ? 1 : 0;
}
sub
check_for_spf_helo_fail {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
if
(
$scanner
->{spf_helo_failure_comment}) {
$scanner
->test_log (
$scanner
->{spf_helo_failure_comment});
}
return
$scanner
->{spf_helo_fail} ? 1 : 0;
}
sub
check_for_spf_helo_softfail {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
return
$scanner
->{spf_helo_softfail} ? 1 : 0;
}
sub
check_for_spf_helo_permerror {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
return
$scanner
->{spf_helo_permerror} ? 1 : 0;
}
sub
check_for_spf_helo_temperror {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 1)
unless
$scanner
->{spf_helo_checked};
return
$scanner
->{spf_helo_temperror} ? 1 : 0;
}
Hide Show 10 lines of Pod
sub
check_spf_skipped_noenvfrom {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf (
$scanner
, 0)
unless
$scanner
->{spf_checked};
if
(!
exists
$scanner
->{spf_sender}) {
return
1;
}
else
{
return
0;
}
}
sub
check_for_spf_welcomelist_from {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_spf_welcomelist(
$scanner
)
unless
$scanner
->{spf_welcomelist_from_checked};
return
$scanner
->{spf_welcomelist_from} ? 1 : 0;
}
*check_for_spf_whitelist_from
= \
&check_for_spf_welcomelist_from
;
sub
check_for_def_spf_welcomelist_from {
my
(
$self
,
$scanner
) =
@_
;
$self
->_check_def_spf_welcomelist(
$scanner
)
unless
$scanner
->{def_spf_welcomelist_from_checked};
return
$scanner
->{def_spf_welcomelist_from} ? 1 : 0;
}
*check_for_def_spf_whitelist_from
= \
&check_for_def_spf_welcomelist_from
;
sub
_check_spf {
my
(
$self
,
$scanner
,
$ishelo
) =
@_
;
my
$timer
=
$self
->{main}->time_method(
"check_spf"
);
if
(
$scanner
->{conf}->{ignore_received_spf_header}) {
dbg(
"spf: ignoring any Received-SPF headers from internal hosts, by admin setting"
);
}
elsif
(
$scanner
->{checked_for_received_spf_header}) {
dbg(
"spf: already checked for Received-SPF headers, proceeding with DNS based checks"
);
}
else
{
$scanner
->{checked_for_received_spf_header} = 1;
dbg(
"spf: checking to see if the message has a Received-SPF header that we can use"
);
my
@internal_hdrs
=
$scanner
->get(
'ALL-INTERNAL'
);
unless
(
$scanner
->{conf}->{use_newest_received_spf_header}) {
@internal_hdrs
=
reverse
(
@internal_hdrs
);
}
else
{
dbg(
"spf: starting with the newest Received-SPF headers first"
);
}
foreach
my
$hdr
(
@internal_hdrs
) {
local
($1,$2);
if
(
$hdr
=~ /^received-spf:/i) {
dbg(
"spf: found a Received-SPF header added by an internal host: $hdr"
);
if
(
$hdr
=~ /^received-spf:\s*(pass|neutral|(?:soft)?fail|(?:temp|perm)error|none)\b(?:.*\bidentity=(\S+?);?\b)?/i) {
my
$result
=
lc
($1);
my
$identity
=
''
;
if
(
defined
$2) {
$identity
=
lc
($2);
if
(
$identity
eq
'mfrom'
||
$identity
eq
'mailfrom'
) {
next
if
$scanner
->{spf_checked};
$identity
=
''
;
}
elsif
(
$identity
eq
'helo'
) {
next
if
$scanner
->{spf_helo_checked};
$identity
=
'helo_'
;
}
else
{
dbg(
"spf: found unknown identity value, cannot use: $identity"
);
next
;
}
}
else
{
next
if
$scanner
->{spf_checked};
}
$scanner
->{
"spf_${identity}checked"
} = 1;
$scanner
->{
"spf_${identity}pass"
} = 0;
$scanner
->{
"spf_${identity}neutral"
} = 0;
$scanner
->{
"spf_${identity}none"
} = 0;
$scanner
->{
"spf_${identity}fail"
} = 0;
$scanner
->{
"spf_${identity}softfail"
} = 0;
$scanner
->{
"spf_${identity}temperror"
} = 0;
$scanner
->{
"spf_${identity}permerror"
} = 0;
$scanner
->{
"spf_${identity}failure_comment"
} =
undef
;
$scanner
->{
"spf_${identity}${result}"
} = 1;
dbg(
"spf: re-using %s result from Received-SPF header: %s"
,
(
$identity
?
'helo'
:
'mfrom'
),
$result
);
return
if
(
$scanner
->{spf_checked} &&
$scanner
->{spf_helo_checked});
}
else
{
dbg(
"spf: could not parse result from existing Received-SPF header"
);
}
}
elsif
(
$hdr
=~ /^(?:Arc\-)?Authentication-Results:.*;\s
*SPF
\s*=\s*([^;]*)/i) {
dbg(
"spf: found an Authentication-Results header added by an internal host: $hdr"
);
my
$tmphdr
= $1;
if
(
$tmphdr
=~ /^(pass|neutral|(?:hard|soft)?fail|(?:temp|perm)error|none)(?:[^;]*?\bsmtp\.(\S+)\s*=[^;]+)?/i) {
my
$result
=
lc
($1);
$result
=
'fail'
if
$result
eq
'hardfail'
;
my
$identity
=
''
;
if
(
defined
$2) {
$identity
=
lc
($2);
if
(
$identity
eq
'mfrom'
||
$identity
eq
'mailfrom'
) {
next
if
$scanner
->{spf_checked};
$identity
=
''
;
}
elsif
(
$identity
eq
'helo'
) {
next
if
$scanner
->{spf_helo_checked};
$identity
=
'helo_'
;
}
else
{
dbg(
"spf: found unknown identity value, cannot use: $identity"
);
next
;
}
}
else
{
next
if
$scanner
->{spf_checked};
}
$scanner
->{
"spf_${identity}checked"
} = 1;
$scanner
->{
"spf_${identity}pass"
} = 0;
$scanner
->{
"spf_${identity}neutral"
} = 0;
$scanner
->{
"spf_${identity}none"
} = 0;
$scanner
->{
"spf_${identity}fail"
} = 0;
$scanner
->{
"spf_${identity}softfail"
} = 0;
$scanner
->{
"spf_${identity}temperror"
} = 0;
$scanner
->{
"spf_${identity}permerror"
} = 0;
$scanner
->{
"spf_${identity}failure_comment"
} =
undef
;
$scanner
->{
"spf_${identity}${result}"
} = 1;
dbg(
"spf: re-using %s result from Authentication-Results header: %s"
,
(
$identity
?
'helo'
:
'mfrom'
),
$result
);
return
if
(
$scanner
->{spf_checked} &&
$scanner
->{spf_helo_checked});
}
else
{
dbg(
"spf: could not parse result from existing Authentication-Results header"
);
}
}
}
return
if
( (
$ishelo
&&
$scanner
->{spf_helo_checked}) ||
(!
$ishelo
&&
$scanner
->{spf_checked}) );
}
return
unless
$scanner
->is_dns_available();
return
if
$self
->{no_spf_module};
unless
(
defined
$self
->{has_mail_spf}) {
my
$eval_stat
;
eval
{
if
(!
defined
$Mail::SPF::VERSION
||
$Mail::SPF::VERSION
< 2.001) {
die
"Mail::SPF 2.001 or later required, this is "
.
(
defined
$Mail::SPF::VERSION
?
$Mail::SPF::VERSION
:
'unknown'
).
"\n"
;
}
$self
->{spf_server} = Mail::SPF::Server->new(
hostname
=>
$scanner
->get_tag(
'HOSTNAME'
),
dns_resolver
=>
$self
->{main}->{resolver},
max_dns_interactive_terms
=> 20);
1;
} or
do
{
$eval_stat
= $@ ne
''
? $@ :
"errno=$!"
;
chomp
$eval_stat
;
};
if
(!
defined
(
$eval_stat
)) {
dbg(
"spf: using Mail::SPF for SPF checks"
);
$self
->{has_mail_spf} = 1;
}
else
{
dbg(
"spf: cannot load Mail::SPF: module: $eval_stat"
);
dbg(
"spf: Mail::SPF is required for SPF checks, SPF checks disabled"
);
$self
->{no_spf_module} = 1;
return
;
}
}
return
if
$scanner
->{sender_host_fail} &&
$scanner
->{sender_host_fail} == 2;
if
(
$ishelo
) {
$scanner
->{spf_helo_checked} = 1;
$scanner
->{spf_helo_pass} = 0;
$scanner
->{spf_helo_neutral} = 0;
$scanner
->{spf_helo_none} = 0;
$scanner
->{spf_helo_fail} = 0;
$scanner
->{spf_helo_softfail} = 0;
$scanner
->{spf_helo_permerror} = 0;
$scanner
->{spf_helo_temperror} = 0;
$scanner
->{spf_helo_failure_comment} =
undef
;
}
else
{
$scanner
->{spf_checked} = 1;
$scanner
->{spf_pass} = 0;
$scanner
->{spf_neutral} = 0;
$scanner
->{spf_none} = 0;
$scanner
->{spf_fail} = 0;
$scanner
->{spf_softfail} = 0;
$scanner
->{spf_permerror} = 0;
$scanner
->{spf_temperror} = 0;
$scanner
->{spf_failure_comment} =
undef
;
}
my
$lasthop
=
$scanner
->{relays_external}->[0];
if
(!
defined
$lasthop
) {
dbg(
"spf: no suitable relay for spf use found, skipping SPF%s check"
,
$ishelo
?
'-helo'
:
''
);
return
;
}
my
$ip
=
$lasthop
->{ip};
my
$helo
=
$lasthop
->{helo};
if
(
$ishelo
) {
unless
(
$helo
) {
dbg(
"spf: cannot check HELO, HELO value unknown"
);
return
;
}
dbg(
"spf: checking HELO (helo=$helo, ip=$ip)"
);
}
else
{
if
(!
$scanner
->{spf_sender}) {
return
;
}
dbg(
"spf: checking EnvelopeFrom (helo=%s, ip=%s, envfrom=%s)"
,
(
$helo
?
$helo
:
''
),
$ip
,
$scanner
->{spf_sender});
}
if
(
$ishelo
&& (
$helo
=~ /^[\[!]?\d+\.\d+\.\d+\.\d+[\]!]?$/ ||
$helo
=~ /^[^.]+$/)) {
dbg(
"spf: cannot check HELO of '$helo', skipping"
);
return
;
}
if
(
$helo
&&
$scanner
->server_failed_to_respond_for_domain(
$helo
)) {
dbg(
"spf: we had a previous timeout on '$helo', skipping"
);
return
;
}
my
(
$result
,
$comment
,
$text
,
$err
);
my
$identity
=
$ishelo
?
$helo
: (
$scanner
->{spf_sender});
unless
(
$identity
) {
dbg(
"spf: cannot determine %s identity, skipping %s SPF check"
,
(
$ishelo
?
'helo'
:
'mfrom'
), (
$ishelo
?
'helo'
:
'mfrom'
) );
return
;
}
$helo
||=
'unknown'
;
my
$request
;
eval
{
$request
= Mail::SPF::Request->new(
scope
=>
$ishelo
?
'helo'
:
'mfrom'
,
identity
=>
$identity
,
ip_address
=>
$ip
,
helo_identity
=>
$helo
);
1;
} or
do
{
my
$eval_stat
= $@ ne
''
? $@ :
"errno=$!"
;
chomp
$eval_stat
;
dbg(
"spf: cannot create Mail::SPF::Request object: $eval_stat"
);
return
;
};
my
$timeout
=
$scanner
->{conf}->{spf_timeout};
my
$timer_spf
= Mail::SpamAssassin::Timeout->new(
{
secs
=>
$timeout
,
deadline
=>
$scanner
->{master_deadline} });
$err
=
$timer_spf
->run_and_catch(
sub
{
my
$query
=
$self
->{spf_server}->process(
$request
);
$result
=
$query
->code;
$comment
=
$query
->authority_explanation
if
$query
->can(
"authority_explanation"
);
$text
=
$query
->text;
});
if
(
$err
) {
chomp
$err
;
warn
(
"spf: lookup failed: $err\n"
);
return
0;
}
$result
||=
'timeout'
;
$comment
||=
''
;
$comment
=~ s/\s+/ /gs;
$text
||=
''
;
$text
=~ s/\s+/ /gs;
if
(
$ishelo
) {
if
(
$result
eq
'pass'
) {
$scanner
->{spf_helo_pass} = 1; }
elsif
(
$result
eq
'neutral'
) {
$scanner
->{spf_helo_neutral} = 1; }
elsif
(
$result
eq
'none'
) {
$scanner
->{spf_helo_none} = 1; }
elsif
(
$result
eq
'fail'
) {
$scanner
->{spf_helo_fail} = 1; }
elsif
(
$result
eq
'softfail'
) {
$scanner
->{spf_helo_softfail} = 1; }
elsif
(
$result
eq
'permerror'
) {
$scanner
->{spf_helo_permerror} = 1; }
elsif
(
$result
eq
'temperror'
) {
$scanner
->{spf_helo_temperror} = 1; }
elsif
(
$result
eq
'error'
) {
$scanner
->{spf_helo_temperror} = 1; }
if
(
$result
eq
'fail'
) {
$scanner
->{spf_helo_failure_comment} =
"SPF failed: $comment"
;
}
}
else
{
if
(
$result
eq
'pass'
) {
$scanner
->{spf_pass} = 1; }
elsif
(
$result
eq
'neutral'
) {
$scanner
->{spf_neutral} = 1; }
elsif
(
$result
eq
'none'
) {
$scanner
->{spf_none} = 1; }
elsif
(
$result
eq
'fail'
) {
$scanner
->{spf_fail} = 1; }
elsif
(
$result
eq
'softfail'
) {
$scanner
->{spf_softfail} = 1; }
elsif
(
$result
eq
'permerror'
) {
$scanner
->{spf_permerror} = 1; }
elsif
(
$result
eq
'temperror'
) {
$scanner
->{spf_temperror} = 1; }
elsif
(
$result
eq
'error'
) {
$scanner
->{spf_temperror} = 1; }
if
(
$result
eq
'fail'
) {
$scanner
->{spf_failure_comment} =
"SPF failed: $comment"
;
}
}
if
(
$ishelo
) {
dbg(
"spf: query for $ip/$helo: result: $result, comment: $comment, text: $text"
);
}
else
{
dbg(
"spf: query for $scanner->{spf_sender}/$ip/$helo: result: $result, comment: $comment, text: $text"
);
}
}
sub
_get_sender {
my
(
$self
,
$scanner
) =
@_
;
my
$relay
=
$scanner
->{relays_external}->[0];
if
(
defined
$relay
) {
my
$sender
=
$relay
->{envfrom};
if
(
defined
$sender
) {
dbg(
"spf: found EnvelopeFrom '$sender' in first external Received header"
);
$scanner
->{spf_sender} =
lc
$sender
;
}
else
{
dbg(
"spf: EnvelopeFrom not found in first external Received header"
);
}
}
if
(!
exists
$scanner
->{spf_sender}) {
if
(
$scanner
->{num_relays_trusted} > 0 &&
!
$scanner
->{conf}->{always_trust_envelope_sender}) {
dbg(
"spf: relayed through one or more trusted relays, "
.
"cannot use header-based EnvelopeFrom"
);
}
else
{
my
$sender
= (
$scanner
->get(
"EnvelopeFrom:addr"
))[0];
if
(
defined
$sender
) {
dbg(
"spf: found EnvelopeFrom '$sender' from header"
);
$scanner
->{spf_sender} =
lc
$sender
;
}
else
{
dbg(
"spf: EnvelopeFrom header not found"
);
}
}
}
if
(!
exists
$scanner
->{spf_sender}) {
dbg(
"spf: cannot get EnvelopeFrom, cannot use SPF by DNS"
);
}
}
sub
_check_spf_welcomelist {
my
(
$self
,
$scanner
) =
@_
;
$scanner
->{spf_welcomelist_from_checked} = 1;
$scanner
->{spf_welcomelist_from} = 0;
if
(
$scanner
->{spf_checked} && !
$scanner
->{spf_pass}) {
dbg(
"spf: welcomelist_from_spf: already checked spf and didn't get pass, skipping welcomelist check"
);
return
;
}
if
(!
$scanner
->{spf_sender}) {
dbg(
"spf: spf_welcomelist_from: no EnvelopeFrom available for welcomelist check"
);
return
;
}
$scanner
->{spf_welcomelist_from} =
$self
->_wlcheck(
$scanner
,
'welcomelist_from_spf'
) ||
$self
->_wlcheck(
$scanner
,
'welcomelist_auth'
);
if
(
$scanner
->{spf_welcomelist_from}) {
if
(
$self
->check_for_spf_pass(
$scanner
)) {
dbg(
"spf: welcomelist_from_spf: $scanner->{spf_sender} is in user's WELCOMELIST_FROM_SPF and passed SPF check"
);
}
else
{
dbg(
"spf: welcomelist_from_spf: $scanner->{spf_sender} is in user's WELCOMELIST_FROM_SPF but failed SPF check"
);
$scanner
->{spf_welcomelist_from} = 0;
}
}
else
{
dbg(
"spf: welcomelist_from_spf: $scanner->{spf_sender} is not in user's WELCOMELIST_FROM_SPF"
);
}
}
sub
_check_def_spf_welcomelist {
my
(
$self
,
$scanner
) =
@_
;
$scanner
->{def_spf_welcomelist_from_checked} = 1;
$scanner
->{def_spf_welcomelist_from} = 0;
if
(
$scanner
->{spf_checked} && !
$scanner
->{spf_pass}) {
dbg(
"spf: def_spf_welcomelist_from: already checked spf and didn't get pass, skipping welcomelist check"
);
return
;
}
if
(!
$scanner
->{spf_sender}) {
dbg(
"spf: def_spf_welcomelist_from: could not find usable envelope sender"
);
return
;
}
$scanner
->{def_spf_welcomelist_from} =
$self
->_wlcheck(
$scanner
,
'def_welcomelist_from_spf'
) ||
$self
->_wlcheck(
$scanner
,
'def_welcomelist_auth'
);
if
(
$scanner
->{def_spf_welcomelist_from}) {
if
(
$self
->check_for_spf_pass(
$scanner
)) {
dbg(
"spf: def_welcomelist_from_spf: $scanner->{spf_sender} is in DEF_WELCOMELIST_FROM_SPF and passed SPF check"
);
}
else
{
dbg(
"spf: def_welcomelist_from_spf: $scanner->{spf_sender} is in DEF_WELCOMELIST_FROM_SPF but failed SPF check"
);
$scanner
->{def_spf_welcomelist_from} = 0;
}
}
else
{
dbg(
"spf: def_welcomelist_from_spf: $scanner->{spf_sender} is not in DEF_WELCOMELIST_FROM_SPF"
);
}
}
sub
_wlcheck {
my
(
$self
,
$scanner
,
$param
) =
@_
;
if
(
defined
(
$scanner
->{conf}->{
$param
}->{
$scanner
->{spf_sender}})) {
return
1;
}
else
{
foreach
my
$regexp
(
values
%{
$scanner
->{conf}->{
$param
}}) {
if
(
$scanner
->{spf_sender} =~
$regexp
) {
return
1;
}
}
}
return
0;
}
1;
Hide Show 4 lines of Pod