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