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