-share
=> {
-dist
=> {
'Mail-DMARC'
=>
'share'
} };
use_ok(
'Mail::DMARC'
);
my
$dmarc
= Mail::DMARC->new();
isa_ok(
$dmarc
,
'Mail::DMARC'
);
my
%sample_dmarc
= (
config_file
=>
'mail-dmarc.ini'
,
source_ip
=>
'192.0.1.1'
,
envelope_to
=>
'example.com'
,
envelope_from
=>
'cars4you.info'
,
header_from
=>
'yahoo.com'
,
dkim
=> [
{
domain
=>
'example.com'
,
selector
=>
'apr2015'
,
result
=>
'fail'
,
human_result
=>
'fail (body has been altered)'
,
}
],
spf
=> [
{
domain
=>
'example.com'
,
scope
=>
'mfrom'
,
result
=>
'pass'
,
}
],
);
test_new();
test_config_file_first();
test_header_from();
test_setter_values();
test_spf();
test_dkim();
test_zulu_time();
test_report_window();
test_interval_limits();
test_public_suffix_list();
done_testing();
exit
;
sub
test_public_suffix_list {
my
$data
= {
'com'
=> 1,
'examplebogusdomainname'
=> 0,
'xn--55qx5d.cn'
=> 1,
'xn--zfr164b'
=> 1,
};
foreach
my
$domain
(
keys
%$data
) {
my
$result
=
$dmarc
->is_public_suffix(
$domain
);
is(
$result
,
$data
->{
$domain
},
"Public Suffix: $domain"
);
}
}
sub
test_zulu_time {
my
$data
= [
[
'Day Start'
, 1426032000, 1426032000 ],
[
'Day Middle'
, 1426032050, 1426032000 ],
[
'Day End'
, 1426118399, 1426032000 ],
[
'Day Next'
, 1426118400, 1426118400 ],
];
foreach
my
$test
(
@$data
) {
my
(
$name
,
$now
,
$begin
) =
@$test
;
my
$c_begin
=
$dmarc
->get_start_of_zulu_day(
$now
);
is(
$c_begin
,
$begin
,
"Zulu Day: $name"
);
}
}
sub
test_report_window {
my
$data
= [
[
'Daily Start'
, 86400, 1426032000, 1426032000, 1426118399 ],
[
'Daily Middle'
, 86400, 1426032050, 1426032000, 1426118399 ],
[
'Daily End'
, 86400, 1426118399, 1426032000, 1426118399 ],
[
'Hourly First Start'
, 3600, 1426032000, 1426032000, 1426035599 ],
[
'Hourly First Middle'
, 3600, 1426032050, 1426032000, 1426035599 ],
[
'Hourly First End'
, 3600, 1426035599, 1426032000, 1426035599 ],
[
'Hourly Second Start'
, 3600, 1426035600, 1426035600, 1426039199 ],
[
'Hourly Second Middle'
, 3600, 1426035650, 1426035600, 1426039199 ],
[
'Hourly Second End'
, 3600, 1426039199, 1426035600, 1426039199 ],
[
'Irregular Interval'
, 3604, 1426034321, 1426034321, 1426037924 ],
];
foreach
my
$test
(
@$data
) {
my
(
$name
,
$interval
,
$now
,
$begin
,
$end
) =
@$test
;
my
(
$c_begin
,
$c_end
) =
$dmarc
->get_report_window(
$interval
,
$now
);
is_deeply( [
$c_begin
,
$c_end
] , [
$begin
,
$end
] ,
"Report Window: $name"
);
}
}
sub
test_interval_limits {
my
$data
= [
[
'Below Limit'
, 3600, 86400, 3000, 3600 ],
[
'Lower Limit'
, 3600, 86400, 3600, 3600 ],
[
'Between Limits'
, 3600, 86400, 30000, 30000 ],
[
'Upper Limit'
, 3600, 86400, 86400, 86400 ],
[
'Above Limit'
, 3600, 86400, 87000, 86400 ],
];
my
$now
= 1426035650;
foreach
my
$test
(
@$data
) {
my
(
$name
,
$min
,
$max
,
$interval
,
$expect
) =
@$test
;
$dmarc
->config->{
'report_sending'
}->{
'min_interval'
} =
$min
;
$dmarc
->config->{
'report_sending'
}->{
'max_interval'
} =
$max
;
my
(
$c_begin
,
$c_end
) =
$dmarc
->get_report_window(
$interval
,
$now
);
is_deeply( (
$c_end
-
$c_begin
),
$expect
- 1,
"Interval Limit: $name"
);
}
delete
$dmarc
->config->{
'report_sending'
}->{
'min_interval'
};
delete
$dmarc
->config->{
'report_sending'
}->{
'max_interval'
};
}
sub
test_dkim {
$dmarc
->{dkim} =
undef
;
my
%test_dkim1
= (
domain
=>
'a.c'
,
result
=>
'fail'
,
selector
=>
undef
,
human_result
=>
undef
);
my
%test_dkim2
= (
domain
=>
'a.b.c'
,
result
=>
'pass'
);
ok(
$dmarc
->dkim(
%test_dkim1
),
"dkim, hash set"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
],
"dkim, hash set result"
);
$dmarc
->{dkim} =
undef
;
ok(
$dmarc
->dkim(\
%test_dkim1
),
"dkim, hashref set"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
],
"dkim, hashref set, result"
);
$dmarc
->{dkim} =
undef
;
ok(
$dmarc
->dkim([ \
%test_dkim1
]),
"dkim, arrayref set"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
],
"dkim, arrayref set result"
);
$dmarc
->{dkim} =
undef
;
ok(
$dmarc
->dkim([ \
%test_dkim1
, \
%test_dkim2
]),
"dkim, arrayref set"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
, \
%test_dkim2
],
"dkim, arrayref set result"
);
$dmarc
->{dkim} =
undef
;
ok(
$dmarc
->dkim(
%test_dkim1
),
"dkim, hash set 1"
);
ok(
$dmarc
->dkim(
%test_dkim2
),
"dkim, hash set 2"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
, \
%test_dkim2
],
"dkim, iterative hashes"
);
$dmarc
->{dkim} =
undef
;
my
$dkv
= Mail::DKIM::Verifier->new(
%test_dkim1
);
$dmarc
->dkim(
$dkv
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
],
"dkim, as Mail::DKIM::Verifier"
);
$dmarc
->{dkim} =
undef
;
my
$counter
= 0;
my
$callback
=
sub
{
$counter
++; [ \
%test_dkim1
] };
ok(
$dmarc
->dkim(
$callback
),
"dkim, arrayref set"
);
is(
$counter
, 0,
"callback not yet called"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
],
"dkim, callback-derived result"
);
is_deeply(
$dmarc
->dkim, [ \
%test_dkim1
],
"dkim, callback-cached result"
);
is(
$counter
, 1,
"callback exactly once"
);
eval
{
$dmarc
->dkim(
dom
=>
'foo'
,
'blah'
) };
chomp
$@;
ok( $@,
"dkim, neg, $@"
);
eval
{
$dmarc
->dkim( {
domain
=>
'foo.com'
,
result
=>
'non-existent'
} ) };
chomp
$@;
ok( $@,
"dkim, neg, $@"
);
}
sub
test_spf {
$dmarc
->init;
my
%test_spf
= (
domain
=>
'a.c'
,
scope
=>
'mfrom'
,
result
=>
'fail'
);
ok(
$dmarc
->spf(
%test_spf
),
"spf, hash set"
);
is_deeply(
$dmarc
->spf, [ \
%test_spf
],
"spf, hash set result"
);
$dmarc
->init;
ok(
$dmarc
->spf(\
%test_spf
),
"spf, hashref set"
);
is_deeply(
$dmarc
->spf, [ \
%test_spf
],
"spf, hashref set, result"
);
$dmarc
->init;
ok(
$dmarc
->spf([ \
%test_spf
]),
"spf, arrayref set"
);
is_deeply(
$dmarc
->spf, [ \
%test_spf
],
"spf, arrayref set result"
);
$dmarc
->init;
ok(
$dmarc
->spf([ \
%test_spf
, \
%test_spf
]),
"spf, arrayref set"
);
is_deeply(
$dmarc
->spf, [ \
%test_spf
, \
%test_spf
],
"spf, arrayref set result"
);
$dmarc
->init;
my
$counter
= 0;
my
$callback
=
sub
{
$counter
++; [ \
%test_spf
] };
ok(
$dmarc
->spf(
$callback
),
"spf, callback set"
);
is(
$counter
, 0,
"callback not yet called"
);
is_deeply(
$dmarc
->spf, [ \
%test_spf
],
"spf, callback-derived result"
);
is_deeply(
$dmarc
->spf, [ \
%test_spf
],
"spf, callback-cached result"
);
is(
$counter
, 1,
"callback exactly once"
);
eval
{
$dmarc
->spf(
dom
=>
'foo'
,
'blah'
) };
chomp
$@;
ok( $@,
"spf, neg, $@"
);
}
sub
test_header_from {
my
@good_vals
= (
qw/ spam-example.com bar.com /
);
foreach
my
$k
(
@good_vals
) {
ok(
$dmarc
->header_from(
$k
),
"header_from, $k"
);
}
my
@bad_vals
= (
qw/ a.b a@b.c f*ct.org /
);
foreach
my
$k
(
@bad_vals
) {
eval
{
$dmarc
->header_from(
$k
); };
chomp
$@;
ok( $@,
"header_from, $k, $@"
);
}
}
sub
test_setter_values {
my
%good_vals
= (
source_ip
=> [
qw/ 0.0.0.0 1.1.1.1 255.255.255.255 /
],
envelope_to
=> [
qw/ example.com /
],
envelope_from
=> [
qw/ example.com /
],
header_from
=> [
qw/ spam-example.com /
],
dkim
=> [
$sample_dmarc
{dkim} ],
spf
=> [
$sample_dmarc
{spf} ],
);
foreach
my
$k
(
keys
%good_vals
) {
foreach
my
$t
( @{
$good_vals
{
$k
} } ) {
ok(
defined
$dmarc
->
$k
(
$t
),
"$k, $t"
);
}
}
my
%bad_vals
= (
source_ip
=> [
qw/ 0.257.0.25 255.255.255.256 /
],
envelope_to
=> [
qw/ 3.a /
],
envelope_from
=> [
qw/ /
],
header_from
=> [
qw/ /
],
dkim
=> [
qw/ /
],
spf
=> [
qw/ /
],
);
foreach
my
$k
(
keys
%bad_vals
) {
foreach
my
$t
( @{
$bad_vals
{
$k
} } ) {
eval
{
$dmarc
->
$k
(
$t
); };
ok( $@,
"neg, $k, $t"
) or diag
$dmarc
->
$k
(
$t
);
}
}
}
sub
test_new {
my
$dmarc
= Mail::DMARC->new();
isa_ok(
$dmarc
,
'Mail::DMARC'
);
my
$expected
= {
config_file
=>
'mail-dmarc.ini'
};
is_deeply(
$dmarc
,
$expected
,
"new, empty"
);
$dmarc
= cleanup_obj( Mail::DMARC->new(
%sample_dmarc
) );
isa_ok(
$dmarc
,
'Mail::DMARC'
);
is_deeply(
$dmarc
, \
%sample_dmarc
,
"new, one shot"
);
$dmarc
= Mail::DMARC->new();
foreach
my
$key
(
keys
%sample_dmarc
) {
next
if
grep
{/
$key
/}
qw/ config config_file public_suffixes /
;
my
$val
=
$sample_dmarc
{
$key
};
$dmarc
->
$key
(
$val
)
or diag
"error running $key with $val arg: $@"
;
}
$dmarc
= cleanup_obj(
$dmarc
);
is_deeply(
$dmarc
, \
%sample_dmarc
,
"new, individual accessors"
);
}
sub
test_config_file_first {
my
$new_dmarc
= Mail::DMARC::Testing->new(
config_file
=>
't/mail-dmarc.ini'
,
assert_ok
=> 1,
);
};
sub
cleanup_obj {
my
$obj
=
shift
;
foreach
my
$k
(
qw/ config public_suffixes dkim_ar spf_ar /
) {
delete
$obj
->{
$k
};
}
return
$obj
;
}
sub
new {
my
(
$class
,
%args
) =
@_
;
my
$self
=
bless
{
signatures
=> [] },
$class
;
$self
->signatures(
%args
);
return
$self
;
}
sub
signatures {
my
$self
=
shift
;
return
shift
@{
$self
->{signatures}}
if
0 ==
scalar
@_
;
push
@{
$self
->{signatures} }, Mail::DKIM::Signature->new(
@_
);
$self
->{signatures};
}
1;
sub
new {
my
$class
=
shift
;
return
bless
{
@_
},
$class
; };
sub
result {
return
$_
[0]->{result}; }
sub
domain {
return
$_
[0]->{domain}; }
sub
selector {
return
$_
[0]->{selector}; }
sub
result_detail {
return
$_
[0]->{result_detail} ||
$_
[0]->{human_result};
}
1;
sub
assert_ok {
my
(
$self
) =
@_
;
Test::More::is(
$self
->config->{organization}{domain},
'example-test.com'
,
'config file is initialized before assert_ok'
,
);
}
1;