use warnings;
use Data::Dumper;
use JSON;
+use Time::Local;
use PVE::Tools;
use PVE::SafeSyslog;
use PVE::JSONSchema qw(get_standard_option);
use PMG::Utils;
+use PMG::Config;
use PMG::RuleDB;
use PMG::Statistic;
my ($param) = @_;
return [
+ { name => "contact" },
{ name => "domains" },
{ name => "mail" },
{ name => "mailcount" },
{ name => "maildistribution" },
{ name => "spamscores" },
{ name => "sender" },
- { name => "senderdetails" },
+ { name => "rblcount" },
+ { name => "receiver" },
{ name => "virus" },
];
}});
return $sorters;
};
-my $orderby_param_desc = {
- description => "Remote sorting (ExtJS compatible).",
- type => 'string',
- optional => 1,
- maxLength => 4096,
+my $api_properties = {
+ orderby => {
+ description => "Remote sorting configuration(JSON, ExtJS compatible).",
+ type => 'string',
+ optional => 1,
+ maxLength => 4096,
+ },
+};
+
+my $default_properties = sub {
+ my ($prop) = @_;
+
+ $prop //= {};
+
+ $prop->{starttime} = get_standard_option('pmg-starttime');
+ $prop->{endtime} = get_standard_option('pmg-endtime');
+
+ $prop->{year} = {
+ description => "Year. Defaults to current year. You will get statistics for the whole year if you do not specify a month or day.",
+ type => 'integer',
+ minimum => 1900,
+ maximum => 3000,
+ optional => 1,
+ };
+
+ $prop->{month} = {
+ description => "Month. You will get statistics for the whole month if you do not specify a day.",
+ type => 'integer',
+ minimum => 1,
+ maximum => 12,
+ optional => 1,
+ };
+
+ $prop->{day} = {
+ description => "Day of month. Get statistics for a single day.",
+ type => 'integer',
+ minimum => 1,
+ maximum => 31,
+ optional => 1,
+ };
+
+ return $prop;
+};
+
+my $extract_start_end = sub {
+ my ($param) = @_;
+
+ my $has_ymd;
+ foreach my $k (qw(year month day)) {
+ if (defined($param->{$k})) {
+ $has_ymd = $k;
+ last;
+ }
+ }
+ my $has_se;
+ foreach my $k (qw(starttime endtime)) {
+ if (defined($param->{$k})) {
+ $has_se = $k;
+ last;
+ }
+ }
+
+ raise_param_exc({ $has_se => "parameter conflicts with parameter '$has_ymd'"})
+ if $has_se && $has_ymd;
+
+ my $start;
+ my $end;
+
+ if ($has_ymd) {
+ my (undef, undef, undef, undef, $month, $year) = localtime(time());
+ $month += 1;
+ $year = $param->{year} if defined($param->{year});
+ if (defined($param->{day})) {
+ $month = $param->{month} if defined($param->{month});
+ $start = timelocal(0, 0, 0, 1, $month - 1, $year);
+ $end = timelocal(0, 0, 0, 1, $month, $year);
+ } elsif (defined($param->{month})) {
+ my $month = $param->{month};
+ if ($month < 12) {
+ $start = timelocal(0, 0, 0, 1, $month - 1, $year);
+ $end = timelocal(0, 0, 0, 1, $month, $year);
+ } else {
+ $start = timelocal(0, 0, 0, 1, 11, $year);
+ $end = timelocal(0, 0, 0, 1, 0, $year + 1);
+ }
+ } else {
+ $start = timelocal(0, 0, 0, 1, 0, $year);
+ $end = timelocal(0, 0, 0, 1, 0, $year + 1);
+ }
+ } else {
+ $start = $param->{starttime} // (time - 86400);
+ $end = $param->{endtime} // ($start + 86400);
+ }
+
+ return ($start, $end);
};
my $userstat_limit = 2000; # hardcoded limit
+__PACKAGE__->register_method ({
+ name => 'contact',
+ path => 'contact',
+ method => 'GET',
+ description => "Contact Address Statistics.",
+ permissions => { check => [ 'admin', 'qmanager', 'audit'] },
+ parameters => {
+ additionalProperties => 0,
+ properties => $default_properties->({
+ filter => {
+ description => "Contact address filter.",
+ type => 'string',
+ maxLength => 512,
+ optional => 1,
+ },
+ orderby => $api_properties->{orderby},
+ }),
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ contact => {
+ description => "Contact email.",
+ type => 'string',
+ },
+ count => {
+ description => "Mail count.",
+ type => 'number',
+ optional => 1,
+ },
+ bytes => {
+ description => "Mail traffic (Bytes).",
+ type => 'number',
+ },
+ viruscount => {
+ description => "Number of sent virus mails.",
+ type => 'number',
+ optional => 1,
+ },
+ },
+ },
+ links => [ { rel => 'child', href => "{contact}" } ],
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $restenv = PMG::RESTEnvironment->get();
+ my $cinfo = $restenv->{cinfo};
+
+ my ($start, $end) = $extract_start_end->($param);
+
+ my $cfg = PMG::Config->new();
+ my $advfilter = $cfg->get('admin', 'advfilter');
+
+ my $stat = PMG::Statistic->new($start, $end);
+ my $rdb = PMG::RuleDB->new();
+
+ my $sorters = [];
+ if ($param->{orderby}) {
+ my $props = ['contact', 'count', 'bytes', 'viruscount'];
+ $sorters = $decode_orderby->($param->{orderby}, $props);
+ }
+
+ my $res = $stat->user_stat_contact($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter);
+
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'contactdetails',
+ path => 'contact/{contact}',
+ method => 'GET',
+ description => "Detailed Contact Statistics.",
+ permissions => { check => [ 'admin', 'qmanager', 'audit'] },
+ parameters => {
+ additionalProperties => 0,
+ properties => $default_properties->({
+ contact => get_standard_option('pmg-email-address', {
+ description => "Contact email address.",
+ }),
+ filter => {
+ description => "Sender address filter.",
+ type => 'string',
+ maxLength => 512,
+ optional => 1,
+ },
+ orderby => $api_properties->{orderby},
+ }),
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ time => {
+ description => "Receive time stamp",
+ type => 'integer',
+ },
+ sender => {
+ description => "Sender email.",
+ type => 'string',
+ },
+ bytes => {
+ description => "Mail traffic (Bytes).",
+ type => 'number',
+ },
+ blocked => {
+ description => "Mail was blocked.",
+ type => 'boolean',
+ },
+ spamlevel => {
+ description => "Spam score.",
+ type => 'number',
+ },
+ virusinfo => {
+ description => "Virus name.",
+ type => 'string',
+ optional => 1,
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $restenv = PMG::RESTEnvironment->get();
+ my $cinfo = $restenv->{cinfo};
+
+ my ($start, $end) = $extract_start_end->($param);
+
+ my $stat = PMG::Statistic->new($start, $end);
+ my $rdb = PMG::RuleDB->new();
+
+ my $sorters = [];
+ if ($param->{orderby}) {
+ my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
+ $sorters = $decode_orderby->($param->{orderby}, $props);
+ }
+
+ return $stat->user_stat_contact_details(
+ $rdb, $param->{contact}, $userstat_limit, $sorters, $param->{filter});
+ }});
+
__PACKAGE__->register_method ({
name => 'sender',
path => 'sender',
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
+ properties => $default_properties->({
filter => {
description => "Sender address filter.",
type => 'string',
maxLength => 512,
optional => 1,
},
- orderby => $orderby_param_desc,
- },
+ orderby => $api_properties->{orderby},
+ }),
},
returns => {
type => 'array',
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
+ properties => $default_properties->({
sender => get_standard_option('pmg-email-address', {
description => "Sender email address.",
}),
maxLength => 512,
optional => 1,
},
- orderby => $orderby_param_desc,
- },
+ orderby => $api_properties->{orderby},
+ }),
},
returns => {
type => 'array',
description => "Spam score.",
type => 'number',
},
- virusname => {
+ virusinfo => {
description => "Virus name.",
type => 'string',
optional => 1,
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
my $sorters = [];
if ($param->{orderby}) {
- my $props = ['time', 'receiver', 'bytes', 'blocked', 'spamlevel', 'viruscount'];
+ my $props = ['time', 'receiver', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
$sorters = $decode_orderby->($param->{orderby}, $props);
}
$rdb, $param->{sender}, $userstat_limit, $sorters, $param->{filter});
}});
+__PACKAGE__->register_method ({
+ name => 'receiver',
+ path => 'receiver',
+ method => 'GET',
+ description => "Receiver Address Statistics.",
+ permissions => { check => [ 'admin', 'qmanager', 'audit'] },
+ parameters => {
+ additionalProperties => 0,
+ properties => $default_properties->({
+ filter => {
+ description => "Receiver address filter.",
+ type => 'string',
+ maxLength => 512,
+ optional => 1,
+ },
+ orderby => $api_properties->{orderby},
+ }),
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ receiver => {
+ description => "Sender email.",
+ type => 'string',
+ },
+ count => {
+ description => "Mail count.",
+ type => 'number',
+ optional => 1,
+ },
+ bytes => {
+ description => "Mail traffic (Bytes).",
+ type => 'number',
+ },
+ spamcount => {
+ description => "Number of sent spam mails.",
+ type => 'number',
+ optional => 1,
+ },
+ viruscount => {
+ description => "Number of sent virus mails.",
+ type => 'number',
+ optional => 1,
+ },
+ },
+ },
+ links => [ { rel => 'child', href => "{receiver}" } ],
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $restenv = PMG::RESTEnvironment->get();
+ my $cinfo = $restenv->{cinfo};
+
+ my ($start, $end) = $extract_start_end->($param);
+
+ my $cfg = PMG::Config->new();
+ my $advfilter = $cfg->get('admin', 'advfilter');
+
+ my $stat = PMG::Statistic->new($start, $end);
+ my $rdb = PMG::RuleDB->new();
+
+ my $sorters = [];
+ if ($param->{orderby}) {
+ my $props = ['receiver', 'count', 'bytes', 'spamcount', 'viruscount'];
+ $sorters = $decode_orderby->($param->{orderby}, $props);
+ }
+
+ my $res = $stat->user_stat_receiver($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter);
+
+ return $res;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'receiverdetails',
+ path => 'receiver/{receiver}',
+ method => 'GET',
+ description => "Detailed Receiver Statistics.",
+ permissions => { check => [ 'admin', 'qmanager', 'audit'] },
+ parameters => {
+ additionalProperties => 0,
+ properties => $default_properties->({
+ receiver => get_standard_option('pmg-email-address', {
+ description => "Receiver email address.",
+ }),
+ filter => {
+ description => "Sender address filter.",
+ type => 'string',
+ maxLength => 512,
+ optional => 1,
+ },
+ orderby => $api_properties->{orderby},
+ }),
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ time => {
+ description => "Receive time stamp",
+ type => 'integer',
+ },
+ sender => {
+ description => "Sender email.",
+ type => 'string',
+ },
+ bytes => {
+ description => "Mail traffic (Bytes).",
+ type => 'number',
+ },
+ blocked => {
+ description => "Mail was blocked.",
+ type => 'boolean',
+ },
+ spamlevel => {
+ description => "Spam score.",
+ type => 'number',
+ },
+ virusinfo => {
+ description => "Virus name.",
+ type => 'string',
+ optional => 1,
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $restenv = PMG::RESTEnvironment->get();
+ my $cinfo = $restenv->{cinfo};
+
+ my ($start, $end) = $extract_start_end->($param);
+
+ my $stat = PMG::Statistic->new($start, $end);
+ my $rdb = PMG::RuleDB->new();
+
+ my $sorters = [];
+ if ($param->{orderby}) {
+ my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
+ $sorters = $decode_orderby->($param->{orderby}, $props);
+ }
+
+ return $stat->user_stat_receiver_details(
+ $rdb, $param->{receiver}, $userstat_limit, $sorters, $param->{filter});
+ }});
+
__PACKAGE__->register_method ({
name => 'domains',
path => 'domains',
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
- },
+ properties => $default_properties->(),
},
returns => {
type => 'array',
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
- },
+ properties => $default_properties->(),
},
returns => {
type => "object",
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
+ properties => $default_properties->({
timespan => {
- description => "Return Mails/<timespan>, when <timespan> is specified in seconds.",
+ description => "Return Mails/<timespan>, where <timespan> is specified in seconds.",
type => 'integer',
minimum => 3600,
maximum => 366*86400,
optional => 1,
default => 3600,
- }
- },
+ },
+ }),
},
returns => {
type => 'array',
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $span = $param->{timespan} // 3600;
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
- },
+ properties => $default_properties->(),
},
returns => {
type => 'array',
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
- },
+ properties => $default_properties->(),
},
returns => {
type => 'array',
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
permissions => { check => [ 'admin', 'qmanager', 'audit'] },
parameters => {
additionalProperties => 0,
- properties => {
- starttime => get_standard_option('pmg-starttime'),
- endtime => get_standard_option('pmg-endtime'),
- },
+ properties => $default_properties->(),
},
returns => {
type => 'array',
my $restenv = PMG::RESTEnvironment->get();
my $cinfo = $restenv->{cinfo};
- my $start = $param->{starttime} // (time - 86400);
- my $end = $param->{endtime} // ($start + 86400);
+ my ($start, $end) = $extract_start_end->($param);
my $stat = PMG::Statistic->new($start, $end);
my $rdb = PMG::RuleDB->new();
return $res;
}});
+__PACKAGE__->register_method ({
+ name => 'rblcount',
+ path => 'rblcount',
+ method => 'GET',
+ description => "Mail RBL Count Statistics.",
+ permissions => { check => [ 'admin', 'qmanager', 'audit'] },
+ parameters => {
+ additionalProperties => 0,
+ properties => $default_properties->({
+ timespan => {
+ description => "Return RBL rejects/<timespan>, where <timespan> is specified in seconds.",
+ type => 'integer',
+ minimum => 3600,
+ maximum => 366*86400,
+ optional => 1,
+ default => 3600,
+ },
+ }),
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ index => {
+ description => "Time index.",
+ type => 'integer',
+ },
+ time => {
+ description => "Time (Unix epoch).",
+ type => 'integer',
+ },
+ count => {
+ description => "RBL recject count.",
+ type => 'number',
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $restenv = PMG::RESTEnvironment->get();
+ my $cinfo = $restenv->{cinfo};
+
+ my ($start, $end) = $extract_start_end->($param);
+
+ my $span = $param->{timespan} // 3600;
+
+ my $count = ($end - $start)/$span;
+
+ die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
+
+ my $stat = PMG::Statistic->new($start, $end);
+ my $rdb = PMG::RuleDB->new();
+
+ my $res = $stat->rbl_count_stats($rdb, $span);
+
+ return $res;
+ }});
+
1;