Email-Abuse-Investigator
view release on metacpan or search on metacpan
$a->{_urls} = [];
$a->{_mailto_domains} = [];
my @contacts = $a->abuse_contacts();
ok !scalar(grep { $_->{address} eq '(unknown)' } @contacts),
'(unknown) abuse address is never added to contacts';
restore_net();
};
subtest 'abuse_contacts() â returns empty list when no contacts determinable' => sub {
my $a = Email::Abuse::Investigator->new();
$a->parse_email(make_email(
from => 'x@noprovider.example',
received => 'from localhost [127.0.0.1] by mx',
));
$a->{_origin} = undef;
$a->{_urls} = [];
$a->{_mailto_domains} = [];
my @contacts = $a->abuse_contacts();
is scalar @contacts, 0,
'empty list returned when origin is undef and no domains/URLs';
};
# =============================================================================
# report()
# =============================================================================
subtest 'report() â returns a non-empty plain string' => sub {
stub_net();
no warnings 'redefine';
local *Email::Abuse::Investigator::_domain_whois = sub { undef };
my $a = Email::Abuse::Investigator->new();
$a->parse_email(make_email());
my $r = $a->report();
ok defined $r, 'returns a defined value';
ok !ref($r), 'returns a plain string';
ok length($r) > 0, 'report is non-empty';
restore_net();
};
subtest 'report() â contains all expected section headings' => sub {
stub_net();
no warnings 'redefine';
local *Email::Abuse::Investigator::_domain_whois = sub { undef };
my $a = Email::Abuse::Investigator->new();
$a->parse_email(make_email(
body => 'https://spamsite.example/buy and info@spamsite.example',
from => 'Bad <bad@gmail.com>',
));
{
no warnings 'redefine';
local *Email::Abuse::Investigator::_resolve_host = sub { '1.2.3.4' };
local *Email::Abuse::Investigator::_whois_ip = sub {
{ org => 'Test Org', abuse => 'abuse@testorg.example', country => 'US' }
};
local *Email::Abuse::Investigator::_domain_whois = sub { undef };
my $r = $a->report();
like $r, qr/Email::Abuse::Investigator Report/, 'report title present';
like $r, qr/RISK ASSESSMENT/, 'RISK ASSESSMENT present';
like $r, qr/ORIGINATING HOST/, 'ORIGINATING HOST present';
like $r, qr/EMBEDDED HTTP\/HTTPS URLs/, 'EMBEDDED HTTP/HTTPS URLs present';
like $r, qr/CONTACT \/ REPLY-TO DOMAINS/, 'CONTACT/REPLY-TO DOMAINS present';
like $r, qr/WHERE TO SEND ABUSE REPORTS/, 'WHERE TO SEND ABUSE REPORTS present';
}
restore_net();
};
subtest 'report() â idempotent on same object' => sub {
stub_net();
no warnings 'redefine';
local *Email::Abuse::Investigator::_domain_whois = sub { undef };
my $a = Email::Abuse::Investigator->new();
$a->parse_email(make_email());
my $r1 = $a->report();
my $r2 = $a->report();
is $r2, $r1, 'report() returns same string on second call';
restore_net();
};
subtest 'report() â envelope headers are decoded and displayed' => sub {
stub_net();
no warnings 'redefine';
local *Email::Abuse::Investigator::_domain_whois = sub { undef };
local *Email::Abuse::Investigator::_resolve_host = sub { undef };
# Use a base64-encoded From: display name (as in the firmluminary spam)
my $enc_from = '=?UTF-8?B?' . encode_base64('eharmony Partner', '') . '?=';
my $enc_subj = '=?UTF-8?B?' . encode_base64('Ready to Find Love', '') . '?=';
my $a = Email::Abuse::Investigator->new();
$a->parse_email(make_email(
from => qq{"$enc_from" <peacelight\@firmluminary.com>},
subject => $enc_subj,
));
my $r = $a->report();
like $r, qr/eharmony Partner/, 'encoded From: display name decoded in report';
like $r, qr/Ready to Find Love/, 'encoded Subject decoded in report';
restore_net();
};
# =============================================================================
# Cross-method: lazy evaluation and re-parse
# =============================================================================
subtest 'parse_email() re-invocation clears all public-method caches' => sub {
stub_net(resolve => '1.2.3.4');
no warnings 'redefine';
local *Email::Abuse::Investigator::_domain_whois = sub { undef };
my $a = Email::Abuse::Investigator->new();
$a->parse_email(make_email(
body => 'https://first.example/page',
from => 'x@first.example',
received => 'from first (first [91.198.174.1]) by mx',
));
my @urls1 = $a->embedded_urls();
my $orig1 = $a->originating_ip();
my $risk1 = $a->risk_assessment();
ok @urls1 > 0, 'first parse: URLs populated';
ok defined $orig1, 'first parse: origin populated';
( run in 1.281 second using v1.01-cache-2.11-cpan-71847e10f99 )