view release on metacpan or search on metacpan
'Test::More' => '0',
'Test::SetupTeardown' => '0.004',
'Test::MockTime' => '0.16',
'Test::LWP::UserAgent' => '0.033',
},
requires => {
'Path::Tiny' => '0.108',
'YAML::Tiny' => '1.70',
'File::Tail' => '1.3',
'File::Touch' => '0.11',
'DateTime::Format::Strptime' => '1.75',
'JSON' => '2.97001',
'LWP::Protocol::https' => '6.07',
'PHP::HTTPBuildQuery' => '0.09',
'Text::CSV' => '1.99',
'Date::Format' => '2.24'
},
add_to_cleanup => [ 'App-Spoor-*' ],
);
$builder->create_build_script();
}
},
"configure" : {
"requires" : {
"Module::Build" : "0"
}
},
"runtime" : {
"requires" : {
"Date::Format" : "2.24",
"DateTime::Format::Strptime" : "1.75",
"File::Tail" : "1.3",
"File::Touch" : "0.11",
"JSON" : "2.97001",
"LWP::Protocol::https" : "6.07",
"PHP::HTTPBuildQuery" : "0.09",
"Path::Tiny" : "0.108",
"Text::CSV" : "1.99",
"YAML::Tiny" : "1.70"
}
}
App::Spoor::TransmissionFormatter:
file: lib/App/Spoor/TransmissionFormatter.pm
version: '0.01'
App::Spoor::TransmitterUnitFile:
file: lib/App/Spoor/TransmitterUnitFile.pm
version: '0.01'
SpoorForwardHook:
file: lib/App/Spoor/CpanelHookFile.pm
requires:
Date::Format: '2.24'
DateTime::Format::Strptime: '1.75'
File::Tail: '1.3'
File::Touch: '0.11'
JSON: '2.97001'
LWP::Protocol::https: '6.07'
PHP::HTTPBuildQuery: '0.09'
Path::Tiny: '0.108'
Text::CSV: '1.99'
YAML::Tiny: '1.70'
resources:
license: http://www.perlfoundation.org/artistic_license_2_0
lib/App/Spoor/AccessEntryParser.pm view on Meta::CPAN
This subroutine accepts a single line from a CPanel access log (as a string) and returns a reference to a hash
representation of that entry.
The hash representation contains the following elements when the entry could be successfully parsed:
=over 2
=item * type: This is hardcoded to 'access'
=item * log_time: A DateTime instance representing the time of the log entry
=item * event: A description of the event that the entry refers to - can be one of forward_added_partial_ip, forward_removed, unrecognised.
=item * ip: The IP address listed in the entry
=item * credential: The user performing the request
=item * context: The context within which the operation is being performed can be either 'mailbox' or 'unrecognised'
=item * status: The status of the request can be one of 'success' or 'failed'
lib/App/Spoor/AccessEntryParser.pm view on Meta::CPAN
=item * type: This is hardcoded to 'access'
=item * event: This is hardcoded to 'unrecognised'.
=back
=cut
sub parse {
use DateTime::Format::Strptime;
use URI::Escape qw( uri_unescape );
my $log_entry = shift;
my $level;
my $event;
my $status;
my $forward_recipient;
my %result;
my $date_parser = DateTime::Format::Strptime->new(pattern => '%m/%d/%Y:%H:%M:%S %z', on_error => 'croak');
if ($log_entry =~ /
\A
(?<ip>\S+)\s
-\s
(?<username>.+)\s
\[(?<timestamp>[^\]]+)\]\s
"(?<http_request>[^"]+)"\s
(?<response_code>\d{3})\s
/x) {
lib/App/Spoor/ErrorEntryParser.pm view on Meta::CPAN
representation of that entry.
The hash representation contains the following elements:
=over 2
=item * type: This is hardcoded to 'error'
=item * event: A description of the event that the entry refers to - can be one of forward_added_partial_recipient, unrecognised.
=item * log_time: A DateTime instance representing the time of the log entry. It is not set if the event is 'unrecognised'.
=item * context: The context within which the operation is being performed can be either 'mailbox' or 'domain'. It is not set if the event is 'unrecognised'.
=item * forward_type: Can be one of 'system_user', 'pipe' or 'email'. It is not set if the event is 'unrecognised'.
=item * forward_to: The recipient of the forwarded email. It is not set if the event is 'unrecognised'.
=item * email: The mailbox that the forward is being applied to. It is not set if the event is 'unrecognised'.
=item * status: The status of the request is hardcoded to success. It is not set if the event is 'unrecognised'.
=back
=cut
sub parse {
use DateTime::Format::Strptime;
use JSON;
my $log_entry = shift;
my $date_parser = DateTime::Format::Strptime->new(pattern => '%Y-%m-%d %H:%M:%S %z', on_error => 'croak');
my %response;
my $data_ref;
my $timestamp;
my $forward_type;
if ($log_entry =~ /
\A
\[(?<timestamp>[^\]]+)\]\s
info\s
\[spoor_forward_added\]\s
lib/App/Spoor/LoginEntryParser.pm view on Meta::CPAN
representation of that entry.
The hash representation contains the following elements:
=over 2
=item * type: This is hardcoded to 'login'
=item * event: This is hardcoded to 'login'.
=item * log_time: A DateTime instance representing the time of the log entry.
=item * context: The context within which the operation is being performed can be either 'mailbox', 'domain' or 'system'.
=item * scope: Can be one of 'webmaild', 'cpaneld' or 'whostmgrd'.
=item * ip: The ip logging in.
=item * status: Can be one of 'success', 'deferred' or 'failed'.
=item * credential: The credential (email address/username) presented.
lib/App/Spoor/LoginEntryParser.pm view on Meta::CPAN
=item * message: This is only set if the entry contained additional info (generally on a non-successful login), e.g. "security token missing".
=item * endpoint: HTTP-related information, only present on a non-successful login.
=back
=cut
sub parse {
use DateTime::Format::Strptime;
my $log_entry = shift;
my $date_parser = DateTime::Format::Strptime->new(pattern => '%Y-%m-%d %H:%M:%S %z', on_error => 'croak');
my %response;
if ($log_entry =~ /
\A
\[(?<timestamp>[^\]]+)\]\s
info\s
\[(?<scope>[^\]]+)\]\s
(?<ip>\S+)\s
-\s(?<credential_string>[^-]+)\s-\s
SUCCESS
/x) {
lib/App/Spoor/TransmissionFormatter.pm view on Meta::CPAN
Takes a hash representation of a hash as input and returns an entry converted into a format suitable for submission to
the Spoor API.
use Sys::Hostname;
my $host = hostname;
my %login_entry = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 9,
day => 19,
hour => 16,
minute => 2,
second => 36,
time_zone => '+0000'
)->epoch(),
scope => 'webmaild',
ip => '10.10.10.10',
t/AccessEntryParser.t view on Meta::CPAN
ok(defined(&App::Spoor::AccessEntryParser::parse), 'App::Spoor::AccessEntryParser::parse is defined');
my $access_log_entry_forward_added = '10.10.10.10 - rorymckinley%40blah.capefox.co [10/15/2018:17:47:27 -0000] ' .
'"POST /cpsess0248462691/webmail/paper_lantern/mail/doaddfwd.html HTTP/1.1" 200 0 "https://cp4.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" "s" "-" 2096';
my %parsed_log_entry_forward_added = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 17,
minute => 47,
second => 27,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'forward_added_partial_ip',
t/AccessEntryParser.t view on Meta::CPAN
'Parses an access log entry - adding a forward with a trailing newline'
);
my $access_log_entry_not_mailbox_level = '10.10.10.10 - foo [10/15/2018:17:47:27 -0000] ' .
'"POST /cpsess0248462691/webmail/paper_lantern/mail/doaddfwd.html HTTP/1.1" 200 0 "https://cp4.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" "s" "-" 2096';
my %parsed_log_entry_not_mailbox_level = (
type => 'access',
ip => '10.10.10.10',
credential => 'foo',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 17,
minute => 47,
second => 27,
time_zone => '-0000'
)->epoch(),
context => 'unrecognised',
event => 'unrecognised',
t/AccessEntryParser.t view on Meta::CPAN
'Parses an access log entry - not mailbox level with a trailing newline'
);
my $access_log_entry_incorrect_verb = '10.10.10.10 - rorymckinley%40blah.capefox.co [10/15/2018:17:47:27 -0000] ' .
'"GET /cpsess0248462691/webmail/paper_lantern/mail/doaddfwd.html HTTP/1.1" 200 0 "https://cp4.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" "s" "-" 2096';
my %parsed_log_entry_incorrect_verb = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 17,
minute => 47,
second => 27,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'unrecognised',
t/AccessEntryParser.t view on Meta::CPAN
'Parses an access log entry - incorrect http verb with a trailing newline'
);
my $access_log_entry_incorrect_endpoint = '10.10.10.10 - rorymckinley%40blah.capefox.co [10/15/2018:17:47:27 -0000] ' .
'"POST /cpsess0248462691/webmail/paper_lantern/mail/xxxx.html HTTP/1.1" 200 0 "https://cp4.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" "s" "-" 2096';
my %parsed_log_entry_incorrect_endpoint = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 17,
minute => 47,
second => 27,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'unrecognised',
t/AccessEntryParser.t view on Meta::CPAN
'Parses an access log entry - incorrect endpoint with a trailing newline'
);
my $access_log_entry_non_200_response = '10.10.10.10 - rorymckinley%40blah.capefox.co [10/15/2018:17:47:27 -0000] ' .
'"POST /cpsess0248462691/webmail/paper_lantern/mail/doaddfwd.html HTTP/1.1" 400 0 "https://cp4.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" "s" "-" 2096';
my %parsed_log_entry_non_200_response = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 17,
minute => 47,
second => 27,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'forward_added_partial_ip',
t/AccessEntryParser.t view on Meta::CPAN
my $access_log_forward_removed = '10.10.10.10 - rorymckinley%40blah.capefox.co [03/05/2019:10:38:37 -0000] ' .
'"GET /cpsess9858418447/webmail/paper_lantern/mail/dodelfwd.html?email=rorymckinley%40blah.capefox.co' .
'&emaildest=rorymckinley%2bcpanel%40gmail.com HTTP/1.1" 200 0 "https://cp6.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 ' .
'Safari/537.36" "s" "-" 2096';
my %parsed_forward_removed = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2019,
month => 3,
day => 5,
hour => 10,
minute => 38,
second => 37,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'forward_removed',
t/AccessEntryParser.t view on Meta::CPAN
my $access_log_forward_removed_not_mailbox = '10.10.10.10 - foobar [03/05/2019:10:38:37 -0000] ' .
'"GET /cpsess9858418447/webmail/paper_lantern/mail/dodelfwd.html?email=rorymckinley%40blah.capefox.co' .
'&emaildest=rorymckinley%2bcpanel%40gmail.com HTTP/1.1" 200 0 "https://cp6.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 ' .
'Safari/537.36" "s" "-" 2096';
my %parsed_forward_removed_not_mailbox = (
type => 'access',
ip => '10.10.10.10',
credential => 'foobar',
log_time => DateTime->new(
year => 2019,
month => 3,
day => 5,
hour => 10,
minute => 38,
second => 37,
time_zone => '-0000'
)->epoch(),
context => 'unrecognised',
event => 'unrecognised',
t/AccessEntryParser.t view on Meta::CPAN
my $access_log_forward_removed_fail = '10.10.10.10 - rorymckinley%40blah.capefox.co [03/05/2019:10:38:37 -0000] ' .
'"GET /cpsess9858418447/webmail/paper_lantern/mail/dodelfwd.html?email=rorymckinley%40blah.capefox.co' .
'&emaildest=rorymckinley%2bcpanel%40gmail.com HTTP/1.1" 400 0 "https://cp6.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 ' .
'Safari/537.36" "s" "-" 2096';
my %parsed_forward_removed_fail = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2019,
month => 3,
day => 5,
hour => 10,
minute => 38,
second => 37,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'forward_removed',
t/AccessEntryParser.t view on Meta::CPAN
my $access_log_forward_removed_verb = '10.10.10.10 - rorymckinley%40blah.capefox.co [03/05/2019:10:38:37 -0000] ' .
'"POST /cpsess9858418447/webmail/paper_lantern/mail/dodelfwd.html?email=rorymckinley%40blah.capefox.co' .
'&emaildest=rorymckinley%2bcpanel%40gmail.com HTTP/1.1" 200 0 "https://cp6.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 ' .
'Safari/537.36" "s" "-" 2096';
my %parsed_forward_removed_verb = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2019,
month => 3,
day => 5,
hour => 10,
minute => 38,
second => 37,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'unrecognised',
t/AccessEntryParser.t view on Meta::CPAN
my $access_log_forward_removed_parameter = '10.10.10.10 - rorymckinley%40blah.capefox.co [03/05/2019:10:38:37 -0000] ' .
'"GET /cpsess9858418447/webmail/paper_lantern/mail/dodelfwd.html?email=rorymckinley%40blah.capefox.co' .
' HTTP/1.1" 200 0 "https://cp6.capefox.co:2096/" ' .
'"Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 ' .
'Safari/537.36" "s" "-" 2096';
my %parsed_forward_removed_parameter = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2019,
month => 3,
day => 5,
hour => 10,
minute => 38,
second => 37,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'unrecognised',
t/ErrorEntryParser.t view on Meta::CPAN
use strict;
use warnings;
use v5.10;
use Test::More;
use JSON;
use DateTime;
BEGIN {
use_ok('App::Spoor::ErrorEntryParser') || print("Could not load App::Spoor::ErrorEntryParse\n");
}
ok(defined(&App::Spoor::ErrorEntryParser::parse), 'App::Spoor::ErrorEntryParser::parse is not defined');
my $json;
my $entry;
my %expected_parsed_entry;
t/ErrorEntryParser.t view on Meta::CPAN
],
user => 'spoortest'
);
$json = to_json(\%webmail_forward_added_data);
$entry = "[2019-02-10 10:24:17 +0000] info [spoor_forward_added] $json";
%expected_parsed_entry = (
type => 'error',
event => 'forward_added_partial_recipient',
log_time => DateTime->new(
year => 2019,
month => 2,
day => 10,
hour => 10,
minute => 24,
second => 17,
time_zone => '+0000'
)->epoch(),
context => 'mailbox',
email => 'victim@spoor.test',
t/ErrorEntryParser.t view on Meta::CPAN
],
user => 'spoortest'
);
$json = to_json(\%domain_level_forward_data);
$entry = "[2019-02-10 10:24:17 +0000] info [spoor_forward_added] $json";
%expected_parsed_entry = (
type => 'error',
event => 'forward_added_partial_recipient',
log_time => DateTime->new(
year => 2019,
month => 2,
day => 10,
hour => 10,
minute => 24,
second => 17,
time_zone => '+0000'
)->epoch(),
context => 'domain',
email => 'victim@spoor.test',
t/ErrorEntryParser.t view on Meta::CPAN
],
user => 'spoortest'
);
$json = to_json(\%system_user_forward_data);
$entry = "[2019-02-10 10:24:17 +0000] info [spoor_forward_added] $json";
%expected_parsed_entry = (
type => 'error',
event => 'forward_added_partial_recipient',
log_time => DateTime->new(
year => 2019,
month => 2,
day => 10,
hour => 10,
minute => 24,
second => 17,
time_zone => '+0000'
)->epoch(),
context => 'domain',
email => 'victim@spoor.test',
t/ErrorEntryParser.t view on Meta::CPAN
],
user => 'spoortest'
);
$json = to_json(\%pipe_to_script_forward_data);
$entry = "[2019-02-10 10:24:17 +0000] info [spoor_forward_added] $json";
%expected_parsed_entry = (
type => 'error',
event => 'forward_added_partial_recipient',
log_time => DateTime->new(
year => 2019,
month => 2,
day => 10,
hour => 10,
minute => 24,
second => 17,
time_zone => '+0000'
)->epoch(),
context => 'domain',
email => 'victim@spoor.test',
t/LoginEntryParser.t view on Meta::CPAN
use strict;
use warnings;
use v5.10;
use Test::More;
use DateTime;
BEGIN {
use_ok('App::Spoor::LoginEntryParser') || print "Could not load App::Spoor::LoginEntryParser\n";
}
ok (defined(&App::Spoor::LoginEntryParser::parse), 'App::Spoor::LoginEntryParser::parse is defined');
my $successful_webmaild_login = '[2018-09-19 16:02:36 +0000] info [webmaild] 10.10.10.10 ' .
'- rorymckinley@blah.capefox.co (possessor: blahuser) - SUCCESS LOGIN webmaild';
my %parsed_successful_webmaild_login = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 9,
day => 19,
hour => 16,
minute => 2,
second => 36,
time_zone => '+0000'
)->epoch(),
scope => 'webmaild',
ip => '10.10.10.10',
t/LoginEntryParser.t view on Meta::CPAN
is_deeply(
App::Spoor::LoginEntryParser::parse("$successful_webmaild_login\n"),
\%parsed_successful_webmaild_login,
'Parses a successful webmaild login with a trailing newline');
my $successful_webmaild_login_domain_level = '[2018-09-19 16:02:36 +0000] info [webmaild] 10.10.10.10 ' .
'- foobarbazzle (possessor: blahuser) - SUCCESS LOGIN webmaild';
my %parsed_successful_webmaild_login_domain_level = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 9,
day => 19,
hour => 16,
minute => 2,
second => 36,
time_zone => '+0000'
)->epoch(),
scope => 'webmaild',
ip => '10.10.10.10',
t/LoginEntryParser.t view on Meta::CPAN
is_deeply(
App::Spoor::LoginEntryParser::parse("$successful_webmaild_login_domain_level\n"),
\%parsed_successful_webmaild_login_domain_level,
'Parses a successful webmaild login at domain level with a trailing newline');
my $successful_whm_login = '[2018-10-12 12:38:31 +0000] info [whostmgrd] 10.10.10.10 ' .
'- root - SUCCESS LOGIN whostmgrd';
my %parsed_successful_whm_login = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 12,
hour => 12,
minute => 38,
second => 31,
time_zone => '+0000'
)->epoch(),
scope => 'whostmgrd',
ip => '10.10.10.10',
t/LoginEntryParser.t view on Meta::CPAN
is_deeply(
App::Spoor::LoginEntryParser::parse("$successful_whm_login\n"),
\%parsed_successful_whm_login,
'Parses a successful whm login with trailing newline');
my $successful_cpanel_login = '[2018-10-14 06:40:21 +0000] info [cpaneld] 10.10.10.10 ' .
'- blahuser - SUCCESS LOGIN cpaneld';
my %parsed_successful_cpanel_login = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 14,
hour => 6,
minute => 40,
second => 21,
time_zone => '+0000'
)->epoch(),
scope => 'cpaneld',
ip => '10.10.10.10',
t/LoginEntryParser.t view on Meta::CPAN
App::Spoor::LoginEntryParser::parse("$successful_cpanel_login\n"),
\%parsed_successful_cpanel_login,
'Parses a successful cpanel login with trailing newline'
);
my $deferred_whm_login = '[2018-10-14 09:09:12 +0000] info [whostmgrd] 10.10.10.10 ' .
'- root "GET / HTTP/1.1" DEFERRED LOGIN whostmgrd: security token missing';
my %parsed_deferred_whm_login = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 14,
hour => 9,
minute => 9,
second => 12,
time_zone => '+0000'
)->epoch(),
scope => 'whostmgrd',
ip => '10.10.10.10',
t/LoginEntryParser.t view on Meta::CPAN
App::Spoor::LoginEntryParser::parse("$deferred_whm_login\n"),
\%parsed_deferred_whm_login,
'Parses a deferred whm login with trailing newline');
my $failed_cpaneld_login = '[2018-10-15 15:42:18 +0000] info [cpaneld] 10.10.10.10 ' .
'- cpresellercapefo "POST /login/?login_only=1 HTTP/1.1" FAILED LOGIN cpaneld: ' .
'access denied for root, reseller, and user password';
my %parsed_failed_cpanel_login = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 15,
minute => 42,
second => 18,
time_zone => '+0000'
)->epoch(),
scope => 'cpaneld',
ip => '10.10.10.10',
t/TransmissionFormatter.t view on Meta::CPAN
use strict;
use warnings;
use utf8;
use v5.10;
use Test::More;
use App::Spoor::TransmissionFormatter;
use DateTime;
my $host = 'foo.host.com';
my %login_entry = (
type => 'login',
event => 'login',
log_time => DateTime->new(
year => 2018,
month => 9,
day => 19,
hour => 16,
minute => 2,
second => 36,
time_zone => '+0000'
)->epoch(),
scope => 'webmaild',
ip => '10.10.10.10',
t/TransmissionFormatter.t view on Meta::CPAN
ip => $login_entry{ip},
mailbox_address => $login_entry{credential},
context => $login_entry{context},
host => $host
);
my %forward_added_partial_entry_ip = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2018,
month => 10,
day => 15,
hour => 17,
minute => 47,
second => 27,
time_zone => '-0000'
)->epoch(),
context => 'foobar',
event => 'forward_added_partial_ip',
t/TransmissionFormatter.t view on Meta::CPAN
ip => $forward_added_partial_entry_ip{ip},
time => $forward_added_partial_entry_ip{log_time},
mailbox_address => $forward_added_partial_entry_ip{credential},
context => $forward_added_partial_entry_ip{context},
host => $host
);
my %forward_added_partial_entry_recipient = (
type => 'error',
event => 'forward_added_partial_recipient',
log_time => DateTime->new(
year => 2019,
month => 2,
day => 10,
hour => 10,
minute => 24,
second => 17,
time_zone => '+0000'
)->epoch(),
context => 'barbaz',
email => 'victim@spoor.test',
t/TransmissionFormatter.t view on Meta::CPAN
mailbox_address => $forward_added_partial_entry_recipient{email},
forward_recipient => $forward_added_partial_entry_recipient{forward_to},
context => $forward_added_partial_entry_recipient{context},
host => $host
);
my %forward_removed = (
type => 'access',
ip => '10.10.10.10',
credential => 'rorymckinley@blah.capefox.co',
log_time => DateTime->new(
year => 2019,
month => 3,
day => 5,
hour => 10,
minute => 38,
second => 37,
time_zone => '-0000'
)->epoch(),
context => 'mailbox',
event => 'forward_removed',