]> git.proxmox.com Git - pmg-api.git/blame - PMG/API2/Statistics.pm
extend `pmgdb dump`
[pmg-api.git] / PMG / API2 / Statistics.pm
CommitLineData
5de9374c
DM
1package PMG::API2::Statistics;
2
3use strict;
4use warnings;
5use Data::Dumper;
15a1e62c 6use JSON;
0f6b8ccb 7use Time::Local;
5de9374c
DM
8
9use PVE::Tools;
10use PVE::SafeSyslog;
11use PVE::INotify;
12use PVE::Exception qw(raise_param_exc);
13use PVE::RESTHandler;
14use PMG::RESTEnvironment;
15use PVE::JSONSchema qw(get_standard_option);
16
17use PMG::Utils;
44017d49 18use PMG::Config;
5de9374c
DM
19use PMG::RuleDB;
20use PMG::Statistic;
21
22use base qw(PVE::RESTHandler);
23
24__PACKAGE__->register_method ({
25 name => 'index',
26 path => '',
27 method => 'GET',
28 description => "Directory index.",
29 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
30 parameters => {
31 additionalProperties => 0,
d67b777f 32 properties => {},
5de9374c
DM
33 },
34 returns => {
35 type => 'array',
36 items => {
37 type => "object",
38 properties => {},
39 },
40 links => [ { rel => 'child', href => "{name}" } ],
41 },
42 code => sub {
43 my ($param) = @_;
44
45 return [
bcf493af 46 { name => "contact" },
d19c40e0 47 { name => "domains" },
5de9374c 48 { name => "mail" },
6156e4b6 49 { name => "mailcount" },
fea9d463 50 { name => "recent" },
56e1cb1b 51 { name => "recentreceivers" },
89891fa2 52 { name => "maildistribution" },
67832798 53 { name => "spamscores" },
15a1e62c 54 { name => "sender" },
2719ef94 55 { name => "rblcount" },
0ab6dc2a 56 { name => "receiver" },
d67b777f 57 { name => "virus" },
5de9374c
DM
58 ];
59 }});
60
15a1e62c
DM
61my $decode_orderby = sub {
62 my ($orderby, $allowed_props) = @_;
63
64 my $sorters;
65
66 eval { $sorters = decode_json($orderby); };
67 if (my $err = $@) {
68 raise_param_exc({ orderby => 'invalid JSON'});
69 }
70
71 my $schema = {
72 type => 'array',
73 items => {
74 type => "object",
75 properties => {
76 property => {
77 type => 'string',
78 enum => $allowed_props,
79 },
80 direction => {
81 type => 'string',
82 enum => ['ASC', 'DESC'],
83 },
84 },
85 },
86 };
87
88 PVE::JSONSchema::validate($sorters, $schema, "Parameter 'orderby' verification failed\n");
89
90 return $sorters;
91};
92
f194ac27
DM
93my $api_properties = {
94 orderby => {
95 description => "Remote sorting configuration(JSON, ExtJS compatible).",
96 type => 'string',
97 optional => 1,
98 maxLength => 4096,
99 },
15a1e62c
DM
100};
101
f194ac27
DM
102my $default_properties = sub {
103 my ($prop) = @_;
104
105 $prop //= {};
106
107 $prop->{starttime} = get_standard_option('pmg-starttime');
108 $prop->{endtime} = get_standard_option('pmg-endtime');
109
0f6b8ccb
DM
110 $prop->{year} = {
111 description => "Year. Defaults to current year. You will get statistics for the whole year if you do not specify a month or day.",
112 type => 'integer',
113 minimum => 1900,
114 maximum => 3000,
115 optional => 1,
116 };
117
118 $prop->{month} = {
119 description => "Month. You will get statistics for the whole month if you do not specify a day.",
120 type => 'integer',
121 minimum => 1,
122 maximum => 12,
123 optional => 1,
124 };
125
126 $prop->{day} = {
127 description => "Day of month. Get statistics for a single day.",
128 type => 'integer',
129 minimum => 1,
130 maximum => 31,
131 optional => 1,
132 };
133
f194ac27
DM
134 return $prop;
135};
136
137my $extract_start_end = sub {
138 my ($param) = @_;
139
0f6b8ccb
DM
140 my $has_ymd;
141 foreach my $k (qw(year month day)) {
142 if (defined($param->{$k})) {
143 $has_ymd = $k;
144 last;
145 }
146 }
147 my $has_se;
148 foreach my $k (qw(starttime endtime)) {
149 if (defined($param->{$k})) {
150 $has_se = $k;
151 last;
152 }
153 }
154
155 raise_param_exc({ $has_se => "parameter conflicts with parameter '$has_ymd'"})
156 if $has_se && $has_ymd;
157
158 my $start;
159 my $end;
160
161 if ($has_ymd) {
162 my (undef, undef, undef, undef, $month, $year) = localtime(time());
163 $month += 1;
164 $year = $param->{year} if defined($param->{year});
165 if (defined($param->{day})) {
9bb1fcf1 166 my $day = $param->{day};
0f6b8ccb 167 $month = $param->{month} if defined($param->{month});
9bb1fcf1
DC
168 $start = timelocal(0, 0, 0, $day, $month - 1, $year);
169 $end = timelocal(59, 59, 23, $day, $month - 1, $year);
0f6b8ccb
DM
170 } elsif (defined($param->{month})) {
171 my $month = $param->{month};
172 if ($month < 12) {
173 $start = timelocal(0, 0, 0, 1, $month - 1, $year);
174 $end = timelocal(0, 0, 0, 1, $month, $year);
175 } else {
176 $start = timelocal(0, 0, 0, 1, 11, $year);
177 $end = timelocal(0, 0, 0, 1, 0, $year + 1);
178 }
179 } else {
180 $start = timelocal(0, 0, 0, 1, 0, $year);
181 $end = timelocal(0, 0, 0, 1, 0, $year + 1);
182 }
183 } else {
184 $start = $param->{starttime} // (time - 86400);
185 $end = $param->{endtime} // ($start + 86400);
186 }
f194ac27
DM
187
188 return ($start, $end);
189};
15a1e62c 190
f194ac27 191my $userstat_limit = 2000; # hardcoded limit
bcf493af
DM
192
193__PACKAGE__->register_method ({
194 name => 'contact',
195 path => 'contact',
196 method => 'GET',
197 description => "Contact Address Statistics.",
198 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
199 parameters => {
200 additionalProperties => 0,
f194ac27 201 properties => $default_properties->({
bcf493af
DM
202 filter => {
203 description => "Contact address filter.",
204 type => 'string',
205 maxLength => 512,
206 optional => 1,
207 },
f194ac27
DM
208 orderby => $api_properties->{orderby},
209 }),
bcf493af
DM
210 },
211 returns => {
212 type => 'array',
213 items => {
214 type => "object",
215 properties => {
216 contact => {
217 description => "Contact email.",
218 type => 'string',
219 },
220 count => {
221 description => "Mail count.",
222 type => 'number',
223 optional => 1,
224 },
225 bytes => {
226 description => "Mail traffic (Bytes).",
227 type => 'number',
228 },
229 viruscount => {
230 description => "Number of sent virus mails.",
231 type => 'number',
232 optional => 1,
233 },
234 },
235 },
236 links => [ { rel => 'child', href => "{contact}" } ],
237 },
238 code => sub {
239 my ($param) = @_;
240
241 my $restenv = PMG::RESTEnvironment->get();
242 my $cinfo = $restenv->{cinfo};
243
f194ac27 244 my ($start, $end) = $extract_start_end->($param);
bcf493af 245
44017d49
DM
246 my $cfg = PMG::Config->new();
247 my $advfilter = $cfg->get('admin', 'advfilter');
248
bcf493af
DM
249 my $stat = PMG::Statistic->new($start, $end);
250 my $rdb = PMG::RuleDB->new();
251
252 my $sorters = [];
253 if ($param->{orderby}) {
254 my $props = ['contact', 'count', 'bytes', 'viruscount'];
255 $sorters = $decode_orderby->($param->{orderby}, $props);
256 }
257
44017d49 258 my $res = $stat->user_stat_contact($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter);
bcf493af
DM
259
260 return $res;
261 }});
262
263__PACKAGE__->register_method ({
264 name => 'contactdetails',
265 path => 'contact/{contact}',
266 method => 'GET',
267 description => "Detailed Contact Statistics.",
268 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
269 parameters => {
270 additionalProperties => 0,
f194ac27 271 properties => $default_properties->({
bcf493af
DM
272 contact => get_standard_option('pmg-email-address', {
273 description => "Contact email address.",
274 }),
275 filter => {
276 description => "Sender address filter.",
277 type => 'string',
278 maxLength => 512,
279 optional => 1,
280 },
f194ac27
DM
281 orderby => $api_properties->{orderby},
282 }),
bcf493af
DM
283 },
284 returns => {
285 type => 'array',
286 items => {
287 type => "object",
288 properties => {
289 time => {
290 description => "Receive time stamp",
291 type => 'integer',
292 },
293 sender => {
294 description => "Sender email.",
295 type => 'string',
296 },
297 bytes => {
298 description => "Mail traffic (Bytes).",
299 type => 'number',
300 },
301 blocked => {
302 description => "Mail was blocked.",
303 type => 'boolean',
304 },
305 spamlevel => {
306 description => "Spam score.",
307 type => 'number',
308 },
309 virusinfo => {
310 description => "Virus name.",
311 type => 'string',
312 optional => 1,
313 },
314 },
315 },
316 },
317 code => sub {
318 my ($param) = @_;
319
320 my $restenv = PMG::RESTEnvironment->get();
321 my $cinfo = $restenv->{cinfo};
322
f194ac27 323 my ($start, $end) = $extract_start_end->($param);
bcf493af
DM
324
325 my $stat = PMG::Statistic->new($start, $end);
326 my $rdb = PMG::RuleDB->new();
327
bcf493af
DM
328 my $sorters = [];
329 if ($param->{orderby}) {
330 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
331 $sorters = $decode_orderby->($param->{orderby}, $props);
332 }
333
334 return $stat->user_stat_contact_details(
0e3a95fa 335 $rdb, $param->{contact}, $userstat_limit, $sorters, $param->{filter});
bcf493af
DM
336 }});
337
15a1e62c
DM
338__PACKAGE__->register_method ({
339 name => 'sender',
340 path => 'sender',
341 method => 'GET',
342 description => "Sender Address Statistics.",
343 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
344 parameters => {
345 additionalProperties => 0,
f194ac27 346 properties => $default_properties->({
15a1e62c
DM
347 filter => {
348 description => "Sender address filter.",
349 type => 'string',
350 maxLength => 512,
351 optional => 1,
352 },
f194ac27
DM
353 orderby => $api_properties->{orderby},
354 }),
15a1e62c
DM
355 },
356 returns => {
357 type => 'array',
358 items => {
359 type => "object",
360 properties => {
361 sender => {
362 description => "Sender email.",
363 type => 'string',
364 },
365 count => {
366 description => "Mail count.",
367 type => 'number',
368 optional => 1,
369 },
370 bytes => {
371 description => "Mail traffic (Bytes).",
372 type => 'number',
373 },
374 viruscount => {
375 description => "Number of sent virus mails.",
376 type => 'number',
377 optional => 1,
378 },
379 },
380 },
381 links => [ { rel => 'child', href => "{sender}" } ],
382 },
383 code => sub {
384 my ($param) = @_;
385
386 my $restenv = PMG::RESTEnvironment->get();
387 my $cinfo = $restenv->{cinfo};
388
f194ac27 389 my ($start, $end) = $extract_start_end->($param);
15a1e62c
DM
390
391 my $stat = PMG::Statistic->new($start, $end);
392 my $rdb = PMG::RuleDB->new();
393
394 my $sorters = [];
395 if ($param->{orderby}) {
396 my $props = ['sender', 'count', 'bytes', 'viruscount'];
397 $sorters = $decode_orderby->($param->{orderby}, $props);
398 }
399
400 my $res = $stat->user_stat_sender($rdb, $userstat_limit, $sorters, $param->{filter});
401
402 return $res;
403 }});
404
405__PACKAGE__->register_method ({
406 name => 'senderdetails',
407 path => 'sender/{sender}',
408 method => 'GET',
409 description => "Detailed Sender Statistics.",
410 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
411 parameters => {
412 additionalProperties => 0,
f194ac27 413 properties => $default_properties->({
15a1e62c
DM
414 sender => get_standard_option('pmg-email-address', {
415 description => "Sender email address.",
416 }),
417 filter => {
418 description => "Receiver address filter.",
419 type => 'string',
420 maxLength => 512,
421 optional => 1,
422 },
f194ac27
DM
423 orderby => $api_properties->{orderby},
424 }),
15a1e62c
DM
425 },
426 returns => {
427 type => 'array',
428 items => {
429 type => "object",
430 properties => {
431 time => {
432 description => "Receive time stamp",
433 type => 'integer',
434 },
435 receiver => {
436 description => "Receiver email.",
437 type => 'string',
438 },
439 bytes => {
440 description => "Mail traffic (Bytes).",
441 type => 'number',
442 },
443 blocked => {
444 description => "Mail was blocked.",
445 type => 'boolean',
446 },
447 spamlevel => {
448 description => "Spam score.",
449 type => 'number',
450 },
0ab6dc2a 451 virusinfo => {
15a1e62c
DM
452 description => "Virus name.",
453 type => 'string',
454 optional => 1,
455 },
456 },
457 },
458 },
459 code => sub {
460 my ($param) = @_;
461
462 my $restenv = PMG::RESTEnvironment->get();
463 my $cinfo = $restenv->{cinfo};
464
f194ac27 465 my ($start, $end) = $extract_start_end->($param);
15a1e62c
DM
466
467 my $stat = PMG::Statistic->new($start, $end);
468 my $rdb = PMG::RuleDB->new();
469
470 my $sorters = [];
471 if ($param->{orderby}) {
0ab6dc2a 472 my $props = ['time', 'receiver', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
15a1e62c
DM
473 $sorters = $decode_orderby->($param->{orderby}, $props);
474 }
475
476 return $stat->user_stat_sender_details(
0e3a95fa 477 $rdb, $param->{sender}, $userstat_limit, $sorters, $param->{filter});
0ab6dc2a
DM
478 }});
479
480__PACKAGE__->register_method ({
481 name => 'receiver',
482 path => 'receiver',
483 method => 'GET',
484 description => "Receiver Address Statistics.",
485 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
486 parameters => {
487 additionalProperties => 0,
f194ac27 488 properties => $default_properties->({
0ab6dc2a
DM
489 filter => {
490 description => "Receiver address filter.",
491 type => 'string',
492 maxLength => 512,
493 optional => 1,
494 },
f194ac27
DM
495 orderby => $api_properties->{orderby},
496 }),
0ab6dc2a
DM
497 },
498 returns => {
499 type => 'array',
500 items => {
501 type => "object",
502 properties => {
503 receiver => {
504 description => "Sender email.",
505 type => 'string',
506 },
507 count => {
508 description => "Mail count.",
509 type => 'number',
510 optional => 1,
511 },
512 bytes => {
513 description => "Mail traffic (Bytes).",
514 type => 'number',
515 },
516 spamcount => {
517 description => "Number of sent spam mails.",
518 type => 'number',
519 optional => 1,
520 },
521 viruscount => {
522 description => "Number of sent virus mails.",
523 type => 'number',
524 optional => 1,
525 },
526 },
527 },
528 links => [ { rel => 'child', href => "{receiver}" } ],
529 },
530 code => sub {
531 my ($param) = @_;
532
533 my $restenv = PMG::RESTEnvironment->get();
534 my $cinfo = $restenv->{cinfo};
535
f194ac27 536 my ($start, $end) = $extract_start_end->($param);
0ab6dc2a 537
44017d49
DM
538 my $cfg = PMG::Config->new();
539 my $advfilter = $cfg->get('admin', 'advfilter');
540
0ab6dc2a
DM
541 my $stat = PMG::Statistic->new($start, $end);
542 my $rdb = PMG::RuleDB->new();
543
544 my $sorters = [];
545 if ($param->{orderby}) {
546 my $props = ['receiver', 'count', 'bytes', 'spamcount', 'viruscount'];
547 $sorters = $decode_orderby->($param->{orderby}, $props);
548 }
549
44017d49 550 my $res = $stat->user_stat_receiver($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter);
0ab6dc2a
DM
551
552 return $res;
553 }});
554
555__PACKAGE__->register_method ({
556 name => 'receiverdetails',
557 path => 'receiver/{receiver}',
558 method => 'GET',
559 description => "Detailed Receiver Statistics.",
560 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
561 parameters => {
562 additionalProperties => 0,
f194ac27 563 properties => $default_properties->({
0ab6dc2a
DM
564 receiver => get_standard_option('pmg-email-address', {
565 description => "Receiver email address.",
566 }),
567 filter => {
568 description => "Sender address filter.",
569 type => 'string',
570 maxLength => 512,
571 optional => 1,
572 },
f194ac27
DM
573 orderby => $api_properties->{orderby},
574 }),
0ab6dc2a
DM
575 },
576 returns => {
577 type => 'array',
578 items => {
579 type => "object",
580 properties => {
581 time => {
582 description => "Receive time stamp",
583 type => 'integer',
584 },
585 sender => {
586 description => "Sender email.",
587 type => 'string',
588 },
589 bytes => {
590 description => "Mail traffic (Bytes).",
591 type => 'number',
592 },
593 blocked => {
594 description => "Mail was blocked.",
595 type => 'boolean',
596 },
597 spamlevel => {
598 description => "Spam score.",
599 type => 'number',
600 },
601 virusinfo => {
602 description => "Virus name.",
603 type => 'string',
604 optional => 1,
605 },
606 },
607 },
608 },
609 code => sub {
610 my ($param) = @_;
611
612 my $restenv = PMG::RESTEnvironment->get();
613 my $cinfo = $restenv->{cinfo};
614
f194ac27 615 my ($start, $end) = $extract_start_end->($param);
0ab6dc2a
DM
616
617 my $stat = PMG::Statistic->new($start, $end);
618 my $rdb = PMG::RuleDB->new();
619
0ab6dc2a
DM
620 my $sorters = [];
621 if ($param->{orderby}) {
622 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
623 $sorters = $decode_orderby->($param->{orderby}, $props);
624 }
625
626 return $stat->user_stat_receiver_details(
0e3a95fa 627 $rdb, $param->{receiver}, $userstat_limit, $sorters, $param->{filter});
15a1e62c
DM
628 }});
629
d19c40e0
DM
630__PACKAGE__->register_method ({
631 name => 'domains',
632 path => 'domains',
633 method => 'GET',
634 description => "Mail Domains Statistics.",
635 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
636 parameters => {
637 additionalProperties => 0,
f194ac27 638 properties => $default_properties->(),
d19c40e0
DM
639 },
640 returns => {
641 type => 'array',
642 items => {
643 type => "object",
644 properties => {
645 domain => {
646 description => "Domain name.",
647 type => 'string',
648 },
649 count_in => {
650 description => "Incoming mail count.",
651 type => 'number',
652 },
653 count_out => {
654 description => "Outgoing mail count.",
655 type => 'number',
656 },
657 spamcount_in => {
658 description => "Incoming spam mails.",
659 type => 'number',
660 },
661 spamcount_out => {
662 description => "Outgoing spam mails.",
663 type => 'number',
664 },
6bc396fc
DM
665 bytes_in => {
666 description => "Incoming mail traffic (Bytes).",
d19c40e0
DM
667 type => 'number',
668 },
6bc396fc
DM
669 bytes_out => {
670 description => "Outgoing mail traffic (Bytes).",
d19c40e0
DM
671 type => 'number',
672 },
673 viruscount_in => {
674 description => "Number of incoming virus mails.",
675 type => 'number',
676 },
677 viruscount_out => {
678 description => "Number of outgoing virus mails.",
679 type => 'number',
680 },
681 },
682 },
683 },
684 code => sub {
685 my ($param) = @_;
686
687 my $restenv = PMG::RESTEnvironment->get();
688 my $cinfo = $restenv->{cinfo};
689
f194ac27 690 my ($start, $end) = $extract_start_end->($param);
d19c40e0
DM
691
692 my $stat = PMG::Statistic->new($start, $end);
693 my $rdb = PMG::RuleDB->new();
694
695 #PMG::Statistic::update_stats_domainstat_in($rdb->{dbh}, $cinfo);
696 #PMG::Statistic::update_stats_domainstat_out($rdb->{dbh}, $cinfo);
697
698 my $res = $stat->total_domain_stat($rdb);
699
15a1e62c 700
d19c40e0
DM
701 return $res;
702 }});
703
5de9374c
DM
704__PACKAGE__->register_method ({
705 name => 'mail',
706 path => 'mail',
707 method => 'GET',
708 description => "General Mail Statistics.",
709 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
5de9374c
DM
710 parameters => {
711 additionalProperties => 0,
f194ac27 712 properties => $default_properties->(),
5de9374c
DM
713 },
714 returns => {
715 type => "object",
26e55ddd
DM
716 properties => {
717 avptime => {
718 description => "Average mail processing time in seconds.",
719 type => 'number',
d3550ac9
DM
720 },
721 bounces_in => {
722 description => "Incoming bounce mail count (sender = <>).",
723 type => 'number',
724 },
725 bounces_out => {
726 description => "Outgoing bounce mail count (sender = <>).",
727 type => 'number',
728 },
729 count => {
730 description => "Overall mail count (in and out).",
731 type => 'number',
732 },
733 count_in => {
734 description => "Incoming mail count.",
735 type => 'number',
736 },
737 count_out => {
738 description => "Outgoing mail count.",
739 type => 'number',
740 },
741 glcount => {
742 description => "Number of greylisted mails.",
743 type => 'number',
744 },
4681645a
DM
745 rbl_rejects => {
746 description => "Number of RBL rejects.",
747 type => 'integer',
748 },
749 pregreet_rejects => {
750 description => "PREGREET recject count.",
751 type => 'integer',
752 },
d3550ac9 753 junk_in => {
4681645a 754 description => "Incoming junk mail count (viruscount_in + spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
d3550ac9
DM
755 type => 'number',
756 },
757 junk_out => {
758 description => "Outgoing junk mail count (viruscount_out + spamcount_out).",
759 type => 'number',
760 },
761 spamcount_in => {
762 description => "Incoming spam mails.",
763 type => 'number',
764 },
765 spamcount_out => {
766 description => "Outgoing spam mails.",
767 type => 'number',
768 },
769 spfcount => {
770 description => "Mails rejected by SPF.",
771 type => 'number',
772 },
d19c40e0 773 bytes_in => {
d3550ac9
DM
774 description => "Incoming mail traffic (bytes).",
775 type => 'number',
776 },
d19c40e0 777 bytes_out => {
d3550ac9
DM
778 description => "Outgoing mail traffic (bytes).",
779 type => 'number',
780 },
781 viruscount_in => {
782 description => "Number of incoming virus mails.",
783 type => 'number',
784 },
785 viruscount_out => {
786 description => "Number of outgoing virus mails.",
787 type => 'number',
788 },
26e55ddd 789 },
5de9374c
DM
790 },
791 code => sub {
792 my ($param) = @_;
91bc7652 793
5de9374c
DM
794 my $restenv = PMG::RESTEnvironment->get();
795 my $cinfo = $restenv->{cinfo};
796
f194ac27 797 my ($start, $end) = $extract_start_end->($param);
91bc7652 798
5de9374c
DM
799 my $stat = PMG::Statistic->new($start, $end);
800 my $rdb = PMG::RuleDB->new();
91bc7652 801
5de9374c
DM
802 my $res = $stat->total_mail_stat($rdb);
803
4681645a
DM
804 my $rejects = $stat->postscreen_stat($rdb);
805
806 $res->{rbl_rejects} //= 0;
807 if (defined(my $rbl_rejects = $rejects->{rbl_rejects})) {
808 foreach my $k (qw(rbl_rejects junk_in count_in count)) {
809 $res->{$k} += $rbl_rejects;
810 }
811 }
812
813 $res->{pregreet_rejects} //= 0;
814 if (defined(my $pregreet_rejects = $rejects->{pregreet_rejects})) {
815 foreach my $k (qw(pregreet_rejects junk_in count_in count)) {
816 $res->{$k} += $pregreet_rejects;
817 }
818 }
819
5de9374c
DM
820 return $res;
821 }});
822
fea9d463
DC
823__PACKAGE__->register_method ({
824 name => 'recent',
825 path => 'recent',
826 method => 'GET',
827 description => "Mail Count Statistics.",
828 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
829 parameters => {
830 additionalProperties => 0,
831 properties => {
832 hours => {
833 description => "How many hours you want to get",
834 type => 'integer',
835 minimum => 1,
836 maximum => 24,
837 optional => 1,
838 default => 12,
839 },
840 timespan => {
841 description => "The Timespan for one datapoint (in seconds)",
842 type => 'integer',
843 minimum => 1,
844 maximum => 1800,
845 optional => 1,
846 default => 1800,
847 },
848 },
849 },
850 returns => {
851 type => 'array',
852 items => {
853 type => "object",
854 properties => {
855 index => {
856 description => "Time index.",
857 type => 'integer',
858 },
859 time => {
860 description => "Time (Unix epoch).",
861 type => 'integer',
862 },
863 count => {
864 description => "Overall mail count (in and out).",
865 type => 'number',
866 },
867 count_in => {
868 description => "Incoming mail count.",
869 type => 'number',
870 },
871 count_out => {
872 description => "Outgoing mail count.",
873 type => 'number',
874 },
875 spam => {
876 description => "Overall spam mail count (in and out).",
877 type => 'number',
878 },
879 spam_in => {
880 description => "Incoming spam mails (spamcount_in + glcount + spfcount).",
881 type => 'number',
882 },
883 spam_out => {
884 description => "Outgoing spam mails.",
885 type => 'number',
886 },
887 bytes_in => {
888 description => "Number of incoming bytes mails.",
889 type => 'number',
890 },
891 bytes_out => {
892 description => "Number of outgoing bytes mails.",
893 type => 'number',
894 },
895 virus_in => {
896 description => "Number of incoming virus mails.",
897 type => 'number',
898 },
899 virus_out => {
900 description => "Number of outgoing virus mails.",
901 type => 'number',
902 },
903 timespan => {
904 description => "Timespan in seconds for one data point",
905 type => 'number',
906 }
907 },
908 },
909 },
910 code => sub {
911 my ($param) = @_;
912
913 my $restenv = PMG::RESTEnvironment->get();
914
915 my $hours = $param->{hours} // 12;
916 my $span = $param->{timespan} // 1800;
917
918 my $end = time();
919 my $start = $end - 3600*$hours;
920
921 my $stat = PMG::Statistic->new($start, $end);
922 my $rdb = PMG::RuleDB->new();
923
924 my $res = $stat->recent_mailcount($rdb, $span);
925
926 return $res;
927 }});
928
56e1cb1b
DC
929__PACKAGE__->register_method ({
930 name => 'recentreceivers',
931 path => 'recentreceivers',
932 method => 'GET',
933 description => "Top recent Mail Receivers (including spam)",
934 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
935 parameters => {
936 additionalProperties => 0,
937 properties => {
938 hours => {
939 description => "How many hours you want to get",
940 type => 'integer',
941 minimum => 1,
942 maximum => 24,
943 optional => 1,
944 default => 12,
945 },
946 limit => {
947 description => "The maximum number of receivers to return.",
948 type => 'integer',
949 minimum => 1,
950 maximum => 50,
951 optional => 1,
952 default => 5,
953 },
954 },
955 },
956 returns => {
957 type => 'array',
958 items => {
959 type => "object",
960 properties => {
961 count => {
962 description => "The count of incoming not blocked E-Mails",
963 type => 'integer',
964 },
965 receiver => {
966 description => "The receiver",
967 type => 'string',
968 },
969 },
970 },
971 },
972 code => sub {
973 my ($param) = @_;
974
975 my $restenv = PMG::RESTEnvironment->get();
976
977 my $hours = $param->{hours} // 12;
978
979 my $limit = $param->{limit} // 5;
980
981 my $end = time();
982 my $start = $end - 3600*$hours;
983
984 my $stat = PMG::Statistic->new($start, $end);
985 my $rdb = PMG::RuleDB->new();
986
987 my $res = $stat->recent_receivers($rdb, $limit);
988
989 return $res;
990 }});
991
6156e4b6
DM
992__PACKAGE__->register_method ({
993 name => 'mailcount',
994 path => 'mailcount',
995 method => 'GET',
996 description => "Mail Count Statistics.",
997 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
998 parameters => {
999 additionalProperties => 0,
f194ac27 1000 properties => $default_properties->({
6156e4b6 1001 timespan => {
f194ac27 1002 description => "Return Mails/<timespan>, where <timespan> is specified in seconds.",
6156e4b6
DM
1003 type => 'integer',
1004 minimum => 3600,
1005 maximum => 366*86400,
1006 optional => 1,
1007 default => 3600,
f194ac27
DM
1008 },
1009 }),
6156e4b6
DM
1010 },
1011 returns => {
1012 type => 'array',
1013 items => {
1014 type => "object",
1015 properties => {
1016 index => {
1017 description => "Time index.",
1018 type => 'integer',
1019 },
1020 time => {
1021 description => "Time (Unix epoch).",
1022 type => 'integer',
1023 },
1024 count => {
1025 description => "Overall mail count (in and out).",
1026 type => 'number',
1027 },
1028 count_in => {
1029 description => "Incoming mail count.",
1030 type => 'number',
1031 },
1032 count_out => {
1033 description => "Outgoing mail count.",
1034 type => 'number',
1035 },
1036 spamcount_in => {
4681645a 1037 description => "Incoming spam mails (spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
6156e4b6
DM
1038 type => 'number',
1039 },
1040 spamcount_out => {
1041 description => "Outgoing spam mails.",
1042 type => 'number',
1043 },
1044 viruscount_in => {
1045 description => "Number of incoming virus mails.",
1046 type => 'number',
1047 },
1048 viruscount_out => {
1049 description => "Number of outgoing virus mails.",
1050 type => 'number',
1051 },
4681645a
DM
1052 rbl_rejects => {
1053 description => "Number of RBL rejects.",
1054 type => 'integer',
1055 },
1056 pregreet_rejects => {
1057 description => "PREGREET recject count.",
1058 type => 'integer',
1059 },
6156e4b6
DM
1060 bounces_in => {
1061 description => "Incoming bounce mail count (sender = <>).",
1062 type => 'number',
1063 },
1064 bounces_out => {
1065 description => "Outgoing bounce mail count (sender = <>).",
1066 type => 'number',
1067 },
1068 },
1069 },
1070 },
1071 code => sub {
1072 my ($param) = @_;
1073
1074 my $restenv = PMG::RESTEnvironment->get();
1075 my $cinfo = $restenv->{cinfo};
1076
f194ac27 1077 my ($start, $end) = $extract_start_end->($param);
6156e4b6
DM
1078
1079 my $span = $param->{timespan} // 3600;
1080
1081 my $count = ($end - $start)/$span;
1082
1083 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1084
1085 my $stat = PMG::Statistic->new($start, $end);
1086 my $rdb = PMG::RuleDB->new();
1087
1088 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1089
4681645a
DM
1090 my $rejects = $stat->postscreen_stat_graph($rdb, $span);
1091
6156e4b6
DM
1092 my $res = $stat->traffic_stat_graph ($rdb, $span);
1093
4681645a
DM
1094 my $element_count = scalar(@$res);
1095
1096 for (my $i = 0; $i < $element_count; $i++) {
1097 my $el = $rejects->[$i];
1098 next if !$el;
1099 my $d = $res->[$i];
1100 foreach my $k ('rbl_rejects', 'pregreet_rejects') {
1101 my $count = $el->{$k} // 0;
1102 $d->{$k} = $count;
1103 foreach my $k (qw(count count_in spamcount_in)) {
1104 $d->{$k} += $count;
1105 }
1106 }
1107 }
1108
6156e4b6
DM
1109 return $res;
1110 }});
1111
91bc7652
DM
1112__PACKAGE__->register_method ({
1113 name => 'virus',
1114 path => 'virus',
1115 method => 'GET',
1116 description => "Get Statistics about detected Viruses.",
1117 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
91bc7652
DM
1118 parameters => {
1119 additionalProperties => 0,
f194ac27 1120 properties => $default_properties->(),
91bc7652
DM
1121 },
1122 returns => {
1123 type => 'array',
1124 items => {
1125 type => "object",
1126 properties => {
1127 name => {
1128 description => 'Virus name.',
1129 type => 'string',
1130 },
1131 count => {
1132 description => 'Detection count.',
1133 type => 'integer',
1134 },
1135 },
1136 }
1137 },
1138 code => sub {
1139 my ($param) = @_;
1140
1141 my $restenv = PMG::RESTEnvironment->get();
1142 my $cinfo = $restenv->{cinfo};
1143
f194ac27 1144 my ($start, $end) = $extract_start_end->($param);
91bc7652
DM
1145
1146 my $stat = PMG::Statistic->new($start, $end);
1147 my $rdb = PMG::RuleDB->new();
1148
1149 my $res = $stat->total_virus_stat($rdb);
1150
1151 return $res;
1152 }});
1153
1154__PACKAGE__->register_method ({
67832798
DM
1155 name => 'spamscores',
1156 path => 'spamscores',
91bc7652 1157 method => 'GET',
67832798
DM
1158 description => "Get the count of spam mails grouped by spam score. " .
1159 "Count for score 10 includes mails with spam score > 10.",
91bc7652 1160 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
91bc7652
DM
1161 parameters => {
1162 additionalProperties => 0,
f194ac27 1163 properties => $default_properties->(),
91bc7652
DM
1164 },
1165 returns => {
1166 type => 'array',
1167 items => {
1168 type => "object",
1169 properties => {
1170 level => {
1171 description => 'Spam level.',
1172 type => 'string',
1173 },
1174 count => {
1175 description => 'Detection count.',
1176 type => 'integer',
1177 },
67832798
DM
1178 ratio => {
1179 description => 'Portion of overall mail count.',
1180 type => 'number',
1181 },
91bc7652
DM
1182 },
1183 }
1184 },
1185 code => sub {
1186 my ($param) = @_;
1187
1188 my $restenv = PMG::RESTEnvironment->get();
1189 my $cinfo = $restenv->{cinfo};
1190
f194ac27 1191 my ($start, $end) = $extract_start_end->($param);
91bc7652
DM
1192
1193 my $stat = PMG::Statistic->new($start, $end);
1194 my $rdb = PMG::RuleDB->new();
1195
1196 my $totalstat = $stat->total_mail_stat ($rdb);
1197 my $spamstat = $stat->total_spam_stat($rdb);
1198
d67b777f 1199 my $res = [];
91bc7652 1200
67832798 1201 my $count_in = $totalstat->{count_in};
83081b3d
DM
1202
1203 my $levelcount = {};
1767b03d 1204 my $spamcount = 0;
91bc7652 1205 foreach my $ref (@$spamstat) {
1767b03d
DM
1206 if (my $level = $ref->{spamlevel}) {
1207 next if $level < 1; # just to be sure
1208 $spamcount += $ref->{count};
1209 $level = 10 if $level > 10;
1210 $levelcount->{$level} += $ref->{count};
1211 }
91bc7652
DM
1212 }
1213
1767b03d 1214 $levelcount->{0} = $count_in - $spamcount;
83081b3d
DM
1215
1216 for (my $i = 0; $i <= 10; $i++) {
67832798
DM
1217 my $count = $levelcount->{$i} // 0;
1218 my $ratio = $count_in ? $count/$count_in : 0;
1219 push @$res, { level => $i, count => $count, ratio => $ratio };
83081b3d 1220 }
91bc7652
DM
1221
1222 return $res;
1223 }});
1224
89891fa2
DM
1225__PACKAGE__->register_method ({
1226 name => 'maildistribution',
1227 path => 'maildistribution',
1228 method => 'GET',
1229 description => "Get the count of spam mails grouped by spam score. " .
1230 "Count for score 10 includes mails with spam score > 10.",
1231 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
1232 parameters => {
1233 additionalProperties => 0,
f194ac27 1234 properties => $default_properties->(),
89891fa2
DM
1235 },
1236 returns => {
1237 type => 'array',
1238 items => {
1239 type => "object",
1240 properties => {
1241 index => {
1242 description => "Hour (0-23).",
1243 type => 'integer',
1244 },
1245 count => {
1246 description => "Overall mail count (in and out).",
1247 type => 'number',
1248 },
1249 count_in => {
1250 description => "Incoming mail count.",
1251 type => 'number',
1252 },
1253 count_out => {
1254 description => "Outgoing mail count.",
1255 type => 'number',
1256 },
1257 spamcount_in => {
1258 description => "Incoming spam mails (spamcount_in + glcount + spfcount).",
1259 type => 'number',
1260 },
1261 spamcount_out => {
1262 description => "Outgoing spam mails.",
1263 type => 'number',
1264 },
1265 viruscount_in => {
1266 description => "Number of incoming virus mails.",
1267 type => 'number',
1268 },
1269 viruscount_out => {
1270 description => "Number of outgoing virus mails.",
1271 type => 'number',
1272 },
1273 bounces_in => {
1274 description => "Incoming bounce mail count (sender = <>).",
1275 type => 'number',
1276 },
1277 bounces_out => {
1278 description => "Outgoing bounce mail count (sender = <>).",
1279 type => 'number',
1280 },
1281 },
1282 },
1283 },
1284 code => sub {
1285 my ($param) = @_;
1286
1287 my $restenv = PMG::RESTEnvironment->get();
1288 my $cinfo = $restenv->{cinfo};
1289
f194ac27 1290 my ($start, $end) = $extract_start_end->($param);
89891fa2
DM
1291
1292 my $stat = PMG::Statistic->new($start, $end);
1293 my $rdb = PMG::RuleDB->new();
1294
1295 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1296
1297 my $res = $stat->traffic_stat_day_dist ($rdb);
1298
1299 return $res;
1300 }});
1301
2719ef94 1302__PACKAGE__->register_method ({
980ce907
DM
1303 name => 'rejectcount',
1304 path => 'rejectcount',
2719ef94 1305 method => 'GET',
980ce907 1306 description => "Early SMTP reject count statistic (RBL, PREGREET rejects with postscreen)",
2719ef94
DM
1307 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
1308 parameters => {
1309 additionalProperties => 0,
1310 properties => $default_properties->({
1311 timespan => {
980ce907 1312 description => "Return RBL/PREGREET rejects/<timespan>, where <timespan> is specified in seconds.",
2719ef94
DM
1313 type => 'integer',
1314 minimum => 3600,
1315 maximum => 366*86400,
1316 optional => 1,
1317 default => 3600,
1318 },
1319 }),
1320 },
1321 returns => {
1322 type => 'array',
1323 items => {
1324 type => "object",
1325 properties => {
1326 index => {
1327 description => "Time index.",
1328 type => 'integer',
1329 },
1330 time => {
1331 description => "Time (Unix epoch).",
1332 type => 'integer',
1333 },
980ce907 1334 rbl_rejects => {
2719ef94 1335 description => "RBL recject count.",
980ce907
DM
1336 type => 'integer',
1337 },
1338 pregreet_rejects => {
1339 description => "PREGREET recject count.",
1340 type => 'integer',
2719ef94
DM
1341 },
1342 },
1343 },
1344 },
1345 code => sub {
1346 my ($param) = @_;
1347
1348 my $restenv = PMG::RESTEnvironment->get();
1349 my $cinfo = $restenv->{cinfo};
1350
1351 my ($start, $end) = $extract_start_end->($param);
1352
1353 my $span = $param->{timespan} // 3600;
1354
1355 my $count = ($end - $start)/$span;
1356
1357 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1358
1359 my $stat = PMG::Statistic->new($start, $end);
1360 my $rdb = PMG::RuleDB->new();
1361
4681645a 1362 my $res = $stat->postscreen_stat_graph($rdb, $span);
2719ef94
DM
1363
1364 return $res;
1365 }});
1366
5de9374c 13671;