]> git.proxmox.com Git - pmg-api.git/blame - PMG/API2/Quarantine.pm
PMG/API2/Statistics.pm - implement domain statistics
[pmg-api.git] / PMG / API2 / Quarantine.pm
CommitLineData
b66faa68
DM
1package PMG::API2::Quarantine;
2
3use strict;
4use warnings;
5use Time::Local;
6use Time::Zone;
7use Data::Dumper;
34db0c3f 8use Encode;
b66faa68 9
34db0c3f 10use Mail::Header;
dae021a8 11
b66faa68 12use PVE::SafeSyslog;
6e8886d4 13use PVE::Exception qw(raise_param_exc raise_perm_exc);
b66faa68
DM
14use PVE::Tools qw(extract_param);
15use PVE::JSONSchema qw(get_standard_option);
16use PVE::RESTHandler;
17use PVE::INotify;
34db0c3f 18use PVE::APIServer::Formatter;
b66faa68 19
dae021a8 20use PMG::Utils;
b66faa68 21use PMG::AccessControl;
34db0c3f 22use PMG::Config;
b66faa68 23use PMG::DBTools;
34db0c3f 24use PMG::HTMLMail;
e84bf942 25use PMG::Quarantine;
b66faa68
DM
26
27use base qw(PVE::RESTHandler);
28
1284c016
DM
29my $spamdesc;
30
157a946b
DM
31my $verify_optional_pmail = sub {
32 my ($authuser, $role, $pmail) = @_;
33
34 if ($role eq 'quser') {
5182cea0 35 raise_param_exc({ pmail => "parameter not allwed with role '$role'"})
91affd06 36 if defined($pmail) && ($pmail ne $authuser);
157a946b
DM
37 $pmail = $authuser;
38 } else {
5182cea0 39 raise_param_exc({ pmail => "parameter required with role '$role'"})
157a946b
DM
40 if !defined($pmail);
41 }
42 return $pmail;
43};
44
1284c016
DM
45sub decode_spaminfo {
46 my ($info) = @_;
47
48 $spamdesc = PMG::Utils::load_sa_descriptions() if !$spamdesc;
49
50 my $res = [];
51
52 foreach my $test (split (',', $info)) {
53 my ($name, $score) = split (':', $test);
54
55 my $info = { name => $name, score => $score, desc => '-' };
56 if (my $si = $spamdesc->{$name}) {
57 $info->{desc} = $si->{desc};
58 $info->{url} = $si->{url} if defined($si->{url});
59 }
60 push @$res, $info;
61 }
62
63 return $res;
64}
b66faa68 65
157a946b
DM
66my $extract_email = sub {
67 my $data = shift;
68
69 return $data if !$data;
70
71 if ($data =~ m/^.*\s(\S+)\s*$/) {
72 $data = $1;
73 }
74
75 if ($data =~ m/^<([^<>\s]+)>$/) {
76 $data = $1;
77 }
78
79 if ($data !~ m/[\s><]/ && $data =~ m/^(.+\@[^\.]+\..*[^\.]+)$/) {
80 $data = $1;
81 } else {
82 $data = undef;
83 }
84
85 return $data;
86};
87
88my $get_real_sender = sub {
89 my ($ref) = @_;
90
91 my @lines = split('\n', $ref->{header});
92 my $head = Mail::Header->new(\@lines);
93
94 my @fromarray = split ('\s*,\s*', $head->get ('from') || $ref->{sender});
95 my $from = $extract_email->($fromarray[0]) || $ref->{sender};;
96 my $sender = $extract_email->($head->get ('sender'));
97
98 return $sender if $sender;
99
100 return $from;
101};
102
dae021a8
DM
103my $parse_header_info = sub {
104 my ($ref) = @_;
105
106 my $res = { subject => '', from => '' };
107
108 my @lines = split('\n', $ref->{header});
109 my $head = Mail::Header->new(\@lines);
110
111 $res->{subject} = PMG::Utils::decode_rfc1522(PVE::Tools::trim($head->get('subject'))) // '';
112
113 my @fromarray = split('\s*,\s*', $head->get('from') || $ref->{sender});
114
115 $res->{from} = PMG::Utils::decode_rfc1522(PVE::Tools::trim ($fromarray[0])) // '';
116
117 my $sender = PMG::Utils::decode_rfc1522(PVE::Tools::trim($head->get('sender')));
1284c016 118 $res->{sender} = $sender if $sender && ($sender ne $res->{from});
dae021a8
DM
119
120 $res->{envelope_sender} = $ref->{sender};
e84bf942 121 $res->{receiver} = $ref->{receiver} // $ref->{pmail};
6e8886d4 122 $res->{id} = 'C' . $ref->{cid} . 'R' . $ref->{rid};
dae021a8
DM
123 $res->{time} = $ref->{time};
124 $res->{bytes} = $ref->{bytes};
125
1284c016
DM
126 my $qtype = $ref->{qtype};
127
128 if ($qtype eq 'V') {
129 $res->{virusname} = $ref->{info};
130 } elsif ($qtype eq 'S') {
131 $res->{spamlevel} = $ref->{spamlevel} // 0;
1284c016
DM
132 }
133
dae021a8
DM
134 return $res;
135};
136
157a946b
DM
137my $pmail_param_type = {
138 description => "List entries for the user with this primary email address. Quarantine users cannot speficy this parameter, but it is required for all other roles.",
139 type => 'string', format => 'email',
140 optional => 1,
141};
6e8886d4 142
b66faa68
DM
143__PACKAGE__->register_method ({
144 name => 'index',
145 path => '',
146 method => 'GET',
147 permissions => { user => 'all' },
148 description => "Directory index.",
149 parameters => {
150 additionalProperties => 0,
151 properties => {},
152 },
153 returns => {
154 type => 'array',
155 items => {
156 type => "object",
157 properties => {},
158 },
159 links => [ { rel => 'child', href => "{name}" } ],
160 },
161 code => sub {
162 my ($param) = @_;
163
164 my $result = [
157a946b
DM
165 { name => 'whitelist' },
166 { name => 'blacklist' },
6e8886d4 167 { name => 'content' },
b66faa68 168 { name => 'spam' },
4f41cebc 169 { name => 'spamusers' },
ab02ba10 170 { name => 'spamstatus' },
b66faa68 171 { name => 'virus' },
c3246f47 172 { name => 'virusstatus' },
091d8086 173 { name => 'quarusers' },
b66faa68
DM
174 ];
175
176 return $result;
177 }});
178
157a946b 179
767657cb
DM
180my $read_or_modify_user_bw_list = sub {
181 my ($listname, $param, $addrs, $delete) = @_;
157a946b
DM
182
183 my $rpcenv = PMG::RESTEnvironment->get();
184 my $authuser = $rpcenv->get_user();
185 my $role = $rpcenv->get_role();
186
187 my $pmail = $verify_optional_pmail->($authuser, $role, $param->{pmail});
188
189 my $dbh = PMG::DBTools::open_ruledb();
190
767657cb
DM
191 my $list = PMG::Quarantine::add_to_blackwhite(
192 $dbh, $pmail, $listname, $addrs, $delete);
157a946b
DM
193
194 my $res = [];
195 foreach my $a (@$list) { push @$res, { address => $a }; }
196 return $res;
197};
198
767657cb
DM
199my $address_pattern = '[a-zA-Z0-9\+\-\_\*\.\@]+';
200
157a946b
DM
201__PACKAGE__->register_method ({
202 name => 'whitelist',
203 path => 'whitelist',
204 method => 'GET',
205 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
206 description => "Show user whitelist.",
207 parameters => {
208 additionalProperties => 0,
209 properties => {
210 pmail => $pmail_param_type,
211 },
212 },
213 returns => {
214 type => 'array',
215 items => {
216 type => "object",
217 properties => {
218 address => {
219 type => "string",
220 },
221 },
222 },
223 },
224 code => sub {
225 my ($param) = @_;
226
767657cb
DM
227 return $read_or_modify_user_bw_list->('WL', $param);
228 }});
229
230__PACKAGE__->register_method ({
231 name => 'whitelist_add',
232 path => 'whitelist',
233 method => 'POST',
234 description => "Add user whitelist entries.",
235 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
236 protected => 1,
237 parameters => {
238 additionalProperties => 0,
239 properties => {
240 pmail => $pmail_param_type,
241 address => {
242 description => "The address you want to add.",
243 type => "string",
244 pattern => $address_pattern,
245 maxLength => 512,
246 },
247 },
248 },
249 returns => { type => 'null' },
250 code => sub {
251 my ($param) = @_;
252
253 $read_or_modify_user_bw_list->('WL', $param, [ $param->{address} ]);
254
255 return undef;
256 }});
257
258__PACKAGE__->register_method ({
259 name => 'whitelist_delete',
260 path => 'whitelist/{address}',
261 method => 'DELETE',
262 description => "Delete user whitelist entries.",
263 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
264 protected => 1,
265 parameters => {
266 additionalProperties => 0,
267 properties => {
268 pmail => $pmail_param_type,
269 address => {
270 description => "The address you want to remove.",
271 type => "string",
272 pattern => $address_pattern,
273 maxLength => 512,
274 },
275 },
276 },
277 returns => { type => 'null' },
278 code => sub {
279 my ($param) = @_;
280
281 $read_or_modify_user_bw_list->('WL', $param, [ $param->{address} ], 1);
282
283 return undef;
157a946b
DM
284 }});
285
286__PACKAGE__->register_method ({
287 name => 'blacklist',
288 path => 'blacklist',
289 method => 'GET',
290 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
291 description => "Show user blacklist.",
292 parameters => {
293 additionalProperties => 0,
294 properties => {
295 pmail => $pmail_param_type,
296 },
297 },
298 returns => {
299 type => 'array',
300 items => {
301 type => "object",
302 properties => {
303 address => {
304 type => "string",
305 },
306 },
307 },
308 },
309 code => sub {
310 my ($param) = @_;
311
767657cb
DM
312 return $read_or_modify_user_bw_list->('BL', $param);
313 }});
314
315__PACKAGE__->register_method ({
316 name => 'blacklist_add',
317 path => 'blacklist',
318 method => 'POST',
319 description => "Add user blacklist entries.",
320 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
321 protected => 1,
322 parameters => {
323 additionalProperties => 0,
324 properties => {
325 pmail => $pmail_param_type,
326 address => {
327 description => "The address you want to add.",
328 type => "string",
329 pattern => $address_pattern,
330 maxLength => 512,
331 },
332 },
333 },
334 returns => { type => 'null' },
335 code => sub {
336 my ($param) = @_;
337
338 $read_or_modify_user_bw_list->('BL', $param, [ $param->{address} ]);
339
340 return undef;
341 }});
342
343__PACKAGE__->register_method ({
344 name => 'blacklist_delete',
345 path => 'blacklist/{address}',
346 method => 'DELETE',
347 description => "Delete user blacklist entries.",
348 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
349 protected => 1,
350 parameters => {
351 additionalProperties => 0,
352 properties => {
353 pmail => $pmail_param_type,
354 address => {
355 description => "The address you want to remove.",
356 type => "string",
357 pattern => $address_pattern,
358 maxLength => 512,
359 },
360 },
361 },
362 returns => { type => 'null' },
363 code => sub {
364 my ($param) = @_;
365
366 $read_or_modify_user_bw_list->('BL', $param, [ $param->{address} ], 1);
367
368 return undef;
157a946b
DM
369 }});
370
4f41cebc
DC
371__PACKAGE__->register_method ({
372 name => 'spamusers',
373 path => 'spamusers',
374 method => 'GET',
24a0be04 375 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
4f41cebc
DC
376 description => "Get a list of receivers of spam in the given timespan (Default the last 24 hours).",
377 parameters => {
378 additionalProperties => 0,
379 properties => {
6214b5cf
DM
380 starttime => get_standard_option('pmg-starttime'),
381 endtime => get_standard_option('pmg-endtime'),
4f41cebc
DC
382 },
383 },
384 returns => {
385 type => 'array',
386 items => {
387 type => "object",
388 properties => {
389 mail => {
390 description => 'the receiving email',
391 type => 'string',
392 },
393 },
394 },
395 },
396 code => sub {
397 my ($param) = @_;
398
399 my $rpcenv = PMG::RESTEnvironment->get();
400 my $authuser = $rpcenv->get_user();
4f41cebc
DC
401
402 my $res = [];
403
404 my $dbh = PMG::DBTools::open_ruledb();
405
406 my $start = $param->{starttime} // (time - 86400);
407 my $end = $param->{endtime} // ($start + 86400);
408
409 my $sth = $dbh->prepare(
410 "SELECT DISTINCT pmail " .
411 "FROM CMailStore, CMSReceivers WHERE " .
412 "time >= $start AND time < $end AND " .
413 "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
414 "AND Status = 'N' ORDER BY pmail");
415
416 $sth->execute();
417
418 while (my $ref = $sth->fetchrow_hashref()) {
419 push @$res, { mail => $ref->{pmail} };
420 }
421
422 return $res;
423 }});
424
ab02ba10
DM
425__PACKAGE__->register_method ({
426 name => 'spamstatus',
427 path => 'spamstatus',
428 method => 'GET',
429 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
430 description => "Get Spam Quarantine Status",
431 parameters => {
432 additionalProperties => 0,
433 properties => {},
434 },
435 returns => {
436 type => "object",
437 properties => {
438 count => {
439 description => 'Number of stored mails.',
440 type => 'integer',
441 },
442 mbytes => {
443 description => "Estimated disk space usage in MByte.",
444 type => 'number',
445 },
446 avgbytes => {
447 description => "Average size of stored mails in bytes.",
448 type => 'number',
449 },
450 avgspam => {
451 description => "Average spam level.",
452 type => 'number',
453 },
454 },
455 },
456 code => sub {
457 my ($param) = @_;
458
ab02ba10
DM
459 my $dbh = PMG::DBTools::open_ruledb();
460 my $ref = PMG::DBTools::get_quarantine_count($dbh, 'S');
461
462 return $ref;
463 }});
464
9867e2da
DM
465__PACKAGE__->register_method ({
466 name => 'quarusers',
467 path => 'quarusers',
468 method => 'GET',
469 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
470 description => "Get a list of users with whitelist/blacklist setttings.",
471 parameters => {
472 additionalProperties => 0,
473 properties => {},
474 },
475 returns => {
476 type => 'array',
477 items => {
478 type => "object",
479 properties => {
480 mail => {
481 description => 'the receiving email',
482 type => 'string',
483 },
484 },
485 },
486 },
487 code => sub {
488 my ($param) = @_;
489
490 my $rpcenv = PMG::RESTEnvironment->get();
491 my $authuser = $rpcenv->get_user();
9867e2da
DM
492
493 my $res = [];
494
495 my $dbh = PMG::DBTools::open_ruledb();
496
497 my $sth = $dbh->prepare(
498 "SELECT DISTINCT pmail FROM UserPrefs ORDER BY pmail");
499
500 $sth->execute();
501
502 while (my $ref = $sth->fetchrow_hashref()) {
503 push @$res, { mail => $ref->{pmail} };
504 }
505
506 return $res;
507 }});
508
ded33c7c 509__PACKAGE__->register_method ({
83ce499f
DC
510 name => 'spam',
511 path => 'spam',
ded33c7c
DM
512 method => 'GET',
513 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
83ce499f 514 description => "Get a list of quarantined spam mails in the given timeframe (default the last 24 hours) for the given user.",
ded33c7c
DM
515 parameters => {
516 additionalProperties => 0,
517 properties => {
6214b5cf
DM
518 starttime => get_standard_option('pmg-starttime'),
519 endtime => get_standard_option('pmg-endtime'),
157a946b 520 pmail => $pmail_param_type,
ded33c7c
DM
521 },
522 },
523 returns => {
524 type => 'array',
525 items => {
526 type => "object",
dae021a8
DM
527 properties => {
528 id => {
529 description => 'Unique ID',
530 type => 'string',
531 },
532 bytes => {
533 description => "Size of raw email.",
534 type => 'integer' ,
535 },
536 envelope_sender => {
537 description => "SMTP envelope sender.",
538 type => 'string',
539 },
540 from => {
541 description => "Header 'From' field.",
542 type => 'string',
543 },
544 sender => {
545 description => "Header 'Sender' field.",
546 type => 'string',
547 optional => 1,
548 },
549 receiver => {
550 description => "Receiver email address",
551 type => 'string',
552 },
553 subject => {
554 description => "Header 'Subject' field.",
555 type => 'string',
556 },
557 time => {
558 description => "Receive time stamp",
559 type => 'integer',
560 },
1284c016
DM
561 spamlevel => {
562 description => "Spam score.",
563 type => 'number',
564 },
dae021a8 565 },
ded33c7c
DM
566 },
567 },
568 code => sub {
569 my ($param) = @_;
570
571 my $rpcenv = PMG::RESTEnvironment->get();
572 my $authuser = $rpcenv->get_user();
573 my $role = $rpcenv->get_role();
574
157a946b 575 my $pmail = $verify_optional_pmail->($authuser, $role, $param->{pmail});
b66faa68 576
ded33c7c
DM
577 my $res = [];
578
579 my $dbh = PMG::DBTools::open_ruledb();
580
83ce499f 581 my $start = $param->{starttime} // (time - 86400);
ded33c7c
DM
582 my $end = $param->{endtime} // ($start + 86400);
583
584 my $sth = $dbh->prepare(
585 "SELECT * " .
586 "FROM CMailStore, CMSReceivers WHERE " .
587 "pmail = ? AND time >= $start AND time < $end AND " .
588 "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
589 "AND Status = 'N' ORDER BY pmail, time, receiver");
590
591 $sth->execute($pmail);
592
b66faa68 593 while (my $ref = $sth->fetchrow_hashref()) {
dae021a8
DM
594 my $data = $parse_header_info->($ref);
595 push @$res, $data;
b66faa68
DM
596 }
597
598 return $res;
599 }});
600
bb01dcf8
DM
601__PACKAGE__->register_method ({
602 name => 'virus',
603 path => 'virus',
604 method => 'GET',
605 permissions => { check => [ 'admin', 'qmanager', 'audit' ] },
606 description => "Get a list of quarantined virus mails in the given timeframe (default the last 24 hours).",
607 parameters => {
608 additionalProperties => 0,
609 properties => {
6214b5cf
DM
610 starttime => get_standard_option('pmg-starttime'),
611 endtime => get_standard_option('pmg-endtime'),
bb01dcf8
DM
612 },
613 },
614 returns => {
615 type => 'array',
616 items => {
617 type => "object",
618 properties => {
619 id => {
620 description => 'Unique ID',
621 type => 'string',
622 },
623 bytes => {
624 description => "Size of raw email.",
625 type => 'integer' ,
626 },
627 envelope_sender => {
628 description => "SMTP envelope sender.",
629 type => 'string',
630 },
631 from => {
632 description => "Header 'From' field.",
633 type => 'string',
634 },
635 sender => {
636 description => "Header 'Sender' field.",
637 type => 'string',
638 optional => 1,
639 },
640 receiver => {
641 description => "Receiver email address",
642 type => 'string',
643 },
644 subject => {
645 description => "Header 'Subject' field.",
646 type => 'string',
647 },
648 time => {
649 description => "Receive time stamp",
650 type => 'integer',
651 },
652 virusname => {
653 description => "Virus name.",
654 type => 'string',
655 },
656 },
657 },
658 },
659 code => sub {
660 my ($param) = @_;
661
662 my $rpcenv = PMG::RESTEnvironment->get();
663 my $authuser = $rpcenv->get_user();
bb01dcf8
DM
664
665 my $res = [];
666
667 my $dbh = PMG::DBTools::open_ruledb();
668
669 my $start = $param->{starttime} // (time - 86400);
670 my $end = $param->{endtime} // ($start + 86400);
671
672 my $sth = $dbh->prepare(
673 "SELECT * " .
674 "FROM CMailStore, CMSReceivers WHERE " .
675 "time >= $start AND time < $end AND " .
676 "QType = 'V' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
677 "AND Status = 'N' ORDER BY time, receiver");
678
679 $sth->execute();
680
681 while (my $ref = $sth->fetchrow_hashref()) {
682 my $data = $parse_header_info->($ref);
683 push @$res, $data;
684 }
685
686 return $res;
687 }});
688
c3246f47
DM
689__PACKAGE__->register_method ({
690 name => 'virusstatus',
691 path => 'virusstatus',
692 method => 'GET',
693 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
694 description => "Get Virus Quarantine Status",
695 parameters => {
696 additionalProperties => 0,
697 properties => {},
698 },
699 returns => {
700 type => "object",
701 properties => {
702 count => {
703 description => 'Number of stored mails.',
704 type => 'integer',
705 },
706 mbytes => {
707 description => "Estimated disk space usage in MByte.",
708 type => 'number',
709 },
710 avgbytes => {
711 description => "Average size of stored mails in bytes.",
712 type => 'number',
713 },
714 },
715 },
716 code => sub {
717 my ($param) = @_;
718
719 my $dbh = PMG::DBTools::open_ruledb();
720 my $ref = PMG::DBTools::get_quarantine_count($dbh, 'V');
721
f7fa880f
DM
722 delete $ref->{avgspam};
723
c3246f47
DM
724 return $ref;
725 }});
726
6e8886d4
DM
727__PACKAGE__->register_method ({
728 name => 'content',
729 path => 'content',
730 method => 'GET',
731 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
34db0c3f 732 description => "Get email data. There is a special formatter called 'htmlmail' to get sanitized html view of the mail content (use the '/api2/htmlmail/quarantine/content' url).",
6e8886d4
DM
733 parameters => {
734 additionalProperties => 0,
735 properties => {
736 id => {
737 description => 'Unique ID',
738 type => 'string',
739 pattern => 'C\d+R\d+',
740 maxLength => 40,
741 },
34db0c3f
DM
742 raw => {
743 description => "Display 'raw' eml data. This is only used with the 'htmlmail' formatter.",
744 type => 'boolean',
745 optional => 1,
746 default => 0,
747 },
6e8886d4
DM
748 },
749 },
750 returns => {
751 type => "object",
cd31bb45
DM
752 properties => {
753 id => {
754 description => 'Unique ID',
755 type => 'string',
756 },
757 bytes => {
758 description => "Size of raw email.",
759 type => 'integer' ,
760 },
761 envelope_sender => {
762 description => "SMTP envelope sender.",
763 type => 'string',
764 },
765 from => {
766 description => "Header 'From' field.",
767 type => 'string',
768 },
769 sender => {
770 description => "Header 'Sender' field.",
771 type => 'string',
772 optional => 1,
773 },
774 receiver => {
775 description => "Receiver email address",
776 type => 'string',
777 },
778 subject => {
779 description => "Header 'Subject' field.",
780 type => 'string',
781 },
782 time => {
783 description => "Receive time stamp",
784 type => 'integer',
785 },
786 spamlevel => {
787 description => "Spam score.",
788 type => 'number',
789 },
790 spaminfo => {
791 description => "Information about matched spam tests (name, score, desc, url).",
792 type => 'array',
793 },
794 header => {
795 description => "Raw email header data.",
796 type => 'string',
797 },
798 content => {
799 description => "Raw email data (first 4096 bytes). Useful for preview. NOTE: The 'htmlmail' formatter displays the whole email.",
800 type => 'string',
6eac8473 801 },
cd31bb45 802 },
6e8886d4
DM
803 },
804 code => sub {
805 my ($param) = @_;
806
807 my $rpcenv = PMG::RESTEnvironment->get();
808 my $authuser = $rpcenv->get_user();
809 my $role = $rpcenv->get_role();
34db0c3f 810 my $format = $rpcenv->get_format();
6e8886d4
DM
811
812 my ($cid, $rid) = $param->{id} =~ m/^C(\d+)R(\d+)$/;
813 $cid = int($cid);
814 $rid = int($rid);
815
816 my $dbh = PMG::DBTools::open_ruledb();
817
818 my $ref = PMG::DBTools::load_mail_data($dbh, $cid, $rid);
819
820 if ($role eq 'quser') {
821 raise_perm_exc("mail does not belong to user '$authuser'")
822 if $authuser ne $ref->{pmail};
823 }
824
825 my $res = $parse_header_info->($ref);
826
6e8886d4
DM
827
828 my $filename = $ref->{file};
829 my $spooldir = $PMG::MailQueue::spooldir;
830
831 my $path = "$spooldir/$filename";
832
34db0c3f
DM
833 if ($format eq 'htmlmail') {
834
835 my $cfg = PMG::Config->new();
836 my $viewimages = $cfg->get('spamquar', 'viewimages');
837 my $allowhref = $cfg->get('spamquar', 'allowhrefs');
838
34db0c3f
DM
839 $res->{content} = PMG::HTMLMail::email_to_html($path, $param->{raw}, $viewimages, $allowhref);
840
157a946b
DM
841 # to make result verification happy
842 $res->{file} = '';
843 $res->{header} = '';
844 $res->{spaminfo} = [];
34db0c3f 845 } else {
cd31bb45 846 # include additional details
34db0c3f 847
cd31bb45 848 my ($header, $content) = PMG::HTMLMail::read_raw_email($path, 4096);
157a946b 849
cd31bb45
DM
850 $res->{file} = $ref->{file};
851 $res->{spaminfo} = decode_spaminfo($ref->{info});
34db0c3f
DM
852 $res->{header} = $header;
853 $res->{content} = $content;
854 }
6e8886d4 855
6e8886d4
DM
856
857 return $res;
858
859 }});
860
34db0c3f
DM
861PVE::APIServer::Formatter::register_page_formatter(
862 'format' => 'htmlmail',
863 method => 'GET',
864 path => '/quarantine/content',
865 code => sub {
866 my ($res, $data, $param, $path, $auth, $config) = @_;
867
868 if(!HTTP::Status::is_success($res->{status})) {
869 return ("Error $res->{status}: $res->{message}", "text/plain");
870 }
871
872 my $ct = "text/html;charset=UTF-8";
873
874 my $raw = $data->{content};
875
876 return (encode('UTF-8', $raw), $ct, 1);
877});
878
157a946b
DM
879__PACKAGE__->register_method ({
880 name =>'action',
881 path => 'content',
882 method => 'POST',
883 description => "Execute quarantine actions.",
884 permissions => { check => [ 'admin', 'qmanager', 'quser'] },
885 protected => 1,
886 parameters => {
887 additionalProperties => 0,
888 properties => {
889 id => {
890 description => 'Unique ID',
891 type => 'string',
892 pattern => 'C\d+R\d+',
893 maxLength => 40,
894 },
895 action => {
896 description => 'Action - specify what you want to do with the mail.',
897 type => 'string',
898 enum => ['whitelist', 'blacklist', 'deliver', 'delete'],
899 },
900 },
901 },
902 returns => { type => "null" },
903 code => sub {
904 my ($param) = @_;
905
906 my $rpcenv = PMG::RESTEnvironment->get();
907 my $authuser = $rpcenv->get_user();
908 my $role = $rpcenv->get_role();
909 my $action = $param->{action};
910
911 my ($cid, $rid) = $param->{id} =~ m/^C(\d+)R(\d+)$/;
912 $cid = int($cid);
913 $rid = int($rid);
914
915 my $dbh = PMG::DBTools::open_ruledb();
916
917 my $ref = PMG::DBTools::load_mail_data($dbh, $cid, $rid);
918
919 if ($role eq 'quser') {
920 raise_perm_exc("mail does not belong to user '$authuser'")
921 if $authuser ne $ref->{pmail};
922 }
923
924 my $sender = $get_real_sender->($ref);
925 my $username = $ref->{pmail};
926
927 if ($action eq 'whitelist') {
e84bf942 928 PMG::Quarantine::add_to_blackwhite($dbh, $username, 'WL', [ $sender ]);
157a946b 929 } elsif ($action eq 'blacklist') {
e84bf942 930 PMG::Quarantine::add_to_blackwhite($dbh, $username, 'BL', [ $sender ]);
157a946b 931 } elsif ($action eq 'deliver') {
e84bf942
DM
932 my $targets = [ $ref->{pmail} ];
933 PMG::Quarantine::deliver_quarantined_mail($dbh, $ref, $targets);
157a946b 934 } elsif ($action eq 'delete') {
e84bf942
DM
935 PMG::Quarantine::delete_quarantined_mail($dbh, $ref);
936 } else {
937 die "internal error"; # should not be reached
157a946b
DM
938 }
939
940 return undef;
941 }});
e84bf942 942
b66faa68 9431;