]> git.proxmox.com Git - pmg-api.git/blame - PMG/API2/Quarantine.pm
remove dead code
[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'"})
157a946b
DM
36 if defined($pmail);
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 => {
380 starttime => {
381 description => "Only consider entries newer than 'starttime' (unix epoch). Default is 'now - 1day'.",
382 type => 'integer',
383 minimum => 0,
384 optional => 1,
385 },
386 endtime => {
387 description => "Only consider entries older than 'endtime' (unix epoch). This is set to '<start> + 1day' by default.",
388 type => 'integer',
389 minimum => 1,
390 optional => 1,
391 },
392 },
393 },
394 returns => {
395 type => 'array',
396 items => {
397 type => "object",
398 properties => {
399 mail => {
400 description => 'the receiving email',
401 type => 'string',
402 },
403 },
404 },
405 },
406 code => sub {
407 my ($param) = @_;
408
409 my $rpcenv = PMG::RESTEnvironment->get();
410 my $authuser = $rpcenv->get_user();
4f41cebc
DC
411
412 my $res = [];
413
414 my $dbh = PMG::DBTools::open_ruledb();
415
416 my $start = $param->{starttime} // (time - 86400);
417 my $end = $param->{endtime} // ($start + 86400);
418
419 my $sth = $dbh->prepare(
420 "SELECT DISTINCT pmail " .
421 "FROM CMailStore, CMSReceivers WHERE " .
422 "time >= $start AND time < $end AND " .
423 "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
424 "AND Status = 'N' ORDER BY pmail");
425
426 $sth->execute();
427
428 while (my $ref = $sth->fetchrow_hashref()) {
429 push @$res, { mail => $ref->{pmail} };
430 }
431
432 return $res;
433 }});
434
ab02ba10
DM
435__PACKAGE__->register_method ({
436 name => 'spamstatus',
437 path => 'spamstatus',
438 method => 'GET',
439 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
440 description => "Get Spam Quarantine Status",
441 parameters => {
442 additionalProperties => 0,
443 properties => {},
444 },
445 returns => {
446 type => "object",
447 properties => {
448 count => {
449 description => 'Number of stored mails.',
450 type => 'integer',
451 },
452 mbytes => {
453 description => "Estimated disk space usage in MByte.",
454 type => 'number',
455 },
456 avgbytes => {
457 description => "Average size of stored mails in bytes.",
458 type => 'number',
459 },
460 avgspam => {
461 description => "Average spam level.",
462 type => 'number',
463 },
464 },
465 },
466 code => sub {
467 my ($param) = @_;
468
ab02ba10
DM
469 my $dbh = PMG::DBTools::open_ruledb();
470 my $ref = PMG::DBTools::get_quarantine_count($dbh, 'S');
471
472 return $ref;
473 }});
474
9867e2da
DM
475__PACKAGE__->register_method ({
476 name => 'quarusers',
477 path => 'quarusers',
478 method => 'GET',
479 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
480 description => "Get a list of users with whitelist/blacklist setttings.",
481 parameters => {
482 additionalProperties => 0,
483 properties => {},
484 },
485 returns => {
486 type => 'array',
487 items => {
488 type => "object",
489 properties => {
490 mail => {
491 description => 'the receiving email',
492 type => 'string',
493 },
494 },
495 },
496 },
497 code => sub {
498 my ($param) = @_;
499
500 my $rpcenv = PMG::RESTEnvironment->get();
501 my $authuser = $rpcenv->get_user();
9867e2da
DM
502
503 my $res = [];
504
505 my $dbh = PMG::DBTools::open_ruledb();
506
507 my $sth = $dbh->prepare(
508 "SELECT DISTINCT pmail FROM UserPrefs ORDER BY pmail");
509
510 $sth->execute();
511
512 while (my $ref = $sth->fetchrow_hashref()) {
513 push @$res, { mail => $ref->{pmail} };
514 }
515
516 return $res;
517 }});
518
ded33c7c 519__PACKAGE__->register_method ({
83ce499f
DC
520 name => 'spam',
521 path => 'spam',
ded33c7c
DM
522 method => 'GET',
523 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
83ce499f 524 description => "Get a list of quarantined spam mails in the given timeframe (default the last 24 hours) for the given user.",
ded33c7c
DM
525 parameters => {
526 additionalProperties => 0,
527 properties => {
528 starttime => {
83ce499f 529 description => "Only consider entries newer than 'starttime' (unix epoch). This is set to 'now - 1day' by default.",
ded33c7c
DM
530 type => 'integer',
531 minimum => 0,
83ce499f 532 optional => 1,
ded33c7c
DM
533 },
534 endtime => {
535 description => "Only consider entries older than 'endtime' (unix epoch). This is set to '<start> + 1day' by default.",
536 type => 'integer',
537 minimum => 1,
538 optional => 1,
539 },
157a946b 540 pmail => $pmail_param_type,
ded33c7c
DM
541 },
542 },
543 returns => {
544 type => 'array',
545 items => {
546 type => "object",
dae021a8
DM
547 properties => {
548 id => {
549 description => 'Unique ID',
550 type => 'string',
551 },
552 bytes => {
553 description => "Size of raw email.",
554 type => 'integer' ,
555 },
556 envelope_sender => {
557 description => "SMTP envelope sender.",
558 type => 'string',
559 },
560 from => {
561 description => "Header 'From' field.",
562 type => 'string',
563 },
564 sender => {
565 description => "Header 'Sender' field.",
566 type => 'string',
567 optional => 1,
568 },
569 receiver => {
570 description => "Receiver email address",
571 type => 'string',
572 },
573 subject => {
574 description => "Header 'Subject' field.",
575 type => 'string',
576 },
577 time => {
578 description => "Receive time stamp",
579 type => 'integer',
580 },
1284c016
DM
581 spamlevel => {
582 description => "Spam score.",
583 type => 'number',
584 },
dae021a8 585 },
ded33c7c
DM
586 },
587 },
588 code => sub {
589 my ($param) = @_;
590
591 my $rpcenv = PMG::RESTEnvironment->get();
592 my $authuser = $rpcenv->get_user();
593 my $role = $rpcenv->get_role();
594
157a946b 595 my $pmail = $verify_optional_pmail->($authuser, $role, $param->{pmail});
b66faa68 596
ded33c7c
DM
597 my $res = [];
598
599 my $dbh = PMG::DBTools::open_ruledb();
600
83ce499f 601 my $start = $param->{starttime} // (time - 86400);
ded33c7c
DM
602 my $end = $param->{endtime} // ($start + 86400);
603
604 my $sth = $dbh->prepare(
605 "SELECT * " .
606 "FROM CMailStore, CMSReceivers WHERE " .
607 "pmail = ? AND time >= $start AND time < $end AND " .
608 "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
609 "AND Status = 'N' ORDER BY pmail, time, receiver");
610
611 $sth->execute($pmail);
612
b66faa68 613 while (my $ref = $sth->fetchrow_hashref()) {
dae021a8
DM
614 my $data = $parse_header_info->($ref);
615 push @$res, $data;
b66faa68
DM
616 }
617
618 return $res;
619 }});
620
bb01dcf8
DM
621__PACKAGE__->register_method ({
622 name => 'virus',
623 path => 'virus',
624 method => 'GET',
625 permissions => { check => [ 'admin', 'qmanager', 'audit' ] },
626 description => "Get a list of quarantined virus mails in the given timeframe (default the last 24 hours).",
627 parameters => {
628 additionalProperties => 0,
629 properties => {
630 starttime => {
631 description => "Only consider entries newer than 'starttime' (unix epoch). This is set to 'now - 1day' by default.",
632 type => 'integer',
633 minimum => 0,
634 optional => 1,
635 },
636 endtime => {
637 description => "Only consider entries older than 'endtime' (unix epoch). This is set to '<start> + 1day' by default.",
638 type => 'integer',
639 minimum => 1,
640 optional => 1,
641 },
642 },
643 },
644 returns => {
645 type => 'array',
646 items => {
647 type => "object",
648 properties => {
649 id => {
650 description => 'Unique ID',
651 type => 'string',
652 },
653 bytes => {
654 description => "Size of raw email.",
655 type => 'integer' ,
656 },
657 envelope_sender => {
658 description => "SMTP envelope sender.",
659 type => 'string',
660 },
661 from => {
662 description => "Header 'From' field.",
663 type => 'string',
664 },
665 sender => {
666 description => "Header 'Sender' field.",
667 type => 'string',
668 optional => 1,
669 },
670 receiver => {
671 description => "Receiver email address",
672 type => 'string',
673 },
674 subject => {
675 description => "Header 'Subject' field.",
676 type => 'string',
677 },
678 time => {
679 description => "Receive time stamp",
680 type => 'integer',
681 },
682 virusname => {
683 description => "Virus name.",
684 type => 'string',
685 },
686 },
687 },
688 },
689 code => sub {
690 my ($param) = @_;
691
692 my $rpcenv = PMG::RESTEnvironment->get();
693 my $authuser = $rpcenv->get_user();
bb01dcf8
DM
694
695 my $res = [];
696
697 my $dbh = PMG::DBTools::open_ruledb();
698
699 my $start = $param->{starttime} // (time - 86400);
700 my $end = $param->{endtime} // ($start + 86400);
701
702 my $sth = $dbh->prepare(
703 "SELECT * " .
704 "FROM CMailStore, CMSReceivers WHERE " .
705 "time >= $start AND time < $end AND " .
706 "QType = 'V' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
707 "AND Status = 'N' ORDER BY time, receiver");
708
709 $sth->execute();
710
711 while (my $ref = $sth->fetchrow_hashref()) {
712 my $data = $parse_header_info->($ref);
713 push @$res, $data;
714 }
715
716 return $res;
717 }});
718
c3246f47
DM
719__PACKAGE__->register_method ({
720 name => 'virusstatus',
721 path => 'virusstatus',
722 method => 'GET',
723 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
724 description => "Get Virus Quarantine Status",
725 parameters => {
726 additionalProperties => 0,
727 properties => {},
728 },
729 returns => {
730 type => "object",
731 properties => {
732 count => {
733 description => 'Number of stored mails.',
734 type => 'integer',
735 },
736 mbytes => {
737 description => "Estimated disk space usage in MByte.",
738 type => 'number',
739 },
740 avgbytes => {
741 description => "Average size of stored mails in bytes.",
742 type => 'number',
743 },
744 },
745 },
746 code => sub {
747 my ($param) = @_;
748
749 my $dbh = PMG::DBTools::open_ruledb();
750 my $ref = PMG::DBTools::get_quarantine_count($dbh, 'V');
751
752 return $ref;
753 }});
754
6e8886d4
DM
755__PACKAGE__->register_method ({
756 name => 'content',
757 path => 'content',
758 method => 'GET',
759 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
34db0c3f 760 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
761 parameters => {
762 additionalProperties => 0,
763 properties => {
764 id => {
765 description => 'Unique ID',
766 type => 'string',
767 pattern => 'C\d+R\d+',
768 maxLength => 40,
769 },
34db0c3f
DM
770 raw => {
771 description => "Display 'raw' eml data. This is only used with the 'htmlmail' formatter.",
772 type => 'boolean',
773 optional => 1,
774 default => 0,
775 },
6e8886d4
DM
776 },
777 },
778 returns => {
779 type => "object",
cd31bb45
DM
780 properties => {
781 id => {
782 description => 'Unique ID',
783 type => 'string',
784 },
785 bytes => {
786 description => "Size of raw email.",
787 type => 'integer' ,
788 },
789 envelope_sender => {
790 description => "SMTP envelope sender.",
791 type => 'string',
792 },
793 from => {
794 description => "Header 'From' field.",
795 type => 'string',
796 },
797 sender => {
798 description => "Header 'Sender' field.",
799 type => 'string',
800 optional => 1,
801 },
802 receiver => {
803 description => "Receiver email address",
804 type => 'string',
805 },
806 subject => {
807 description => "Header 'Subject' field.",
808 type => 'string',
809 },
810 time => {
811 description => "Receive time stamp",
812 type => 'integer',
813 },
814 spamlevel => {
815 description => "Spam score.",
816 type => 'number',
817 },
818 spaminfo => {
819 description => "Information about matched spam tests (name, score, desc, url).",
820 type => 'array',
821 },
822 header => {
823 description => "Raw email header data.",
824 type => 'string',
825 },
826 content => {
827 description => "Raw email data (first 4096 bytes). Useful for preview. NOTE: The 'htmlmail' formatter displays the whole email.",
828 type => 'string',
6eac8473 829 },
cd31bb45 830 },
6e8886d4
DM
831 },
832 code => sub {
833 my ($param) = @_;
834
835 my $rpcenv = PMG::RESTEnvironment->get();
836 my $authuser = $rpcenv->get_user();
837 my $role = $rpcenv->get_role();
34db0c3f 838 my $format = $rpcenv->get_format();
6e8886d4
DM
839
840 my ($cid, $rid) = $param->{id} =~ m/^C(\d+)R(\d+)$/;
841 $cid = int($cid);
842 $rid = int($rid);
843
844 my $dbh = PMG::DBTools::open_ruledb();
845
846 my $ref = PMG::DBTools::load_mail_data($dbh, $cid, $rid);
847
848 if ($role eq 'quser') {
849 raise_perm_exc("mail does not belong to user '$authuser'")
850 if $authuser ne $ref->{pmail};
851 }
852
853 my $res = $parse_header_info->($ref);
854
6e8886d4
DM
855
856 my $filename = $ref->{file};
857 my $spooldir = $PMG::MailQueue::spooldir;
858
859 my $path = "$spooldir/$filename";
860
34db0c3f
DM
861 if ($format eq 'htmlmail') {
862
863 my $cfg = PMG::Config->new();
864 my $viewimages = $cfg->get('spamquar', 'viewimages');
865 my $allowhref = $cfg->get('spamquar', 'allowhrefs');
866
34db0c3f
DM
867 $res->{content} = PMG::HTMLMail::email_to_html($path, $param->{raw}, $viewimages, $allowhref);
868
157a946b
DM
869 # to make result verification happy
870 $res->{file} = '';
871 $res->{header} = '';
872 $res->{spaminfo} = [];
34db0c3f 873 } else {
cd31bb45 874 # include additional details
34db0c3f 875
cd31bb45 876 my ($header, $content) = PMG::HTMLMail::read_raw_email($path, 4096);
157a946b 877
cd31bb45
DM
878 $res->{file} = $ref->{file};
879 $res->{spaminfo} = decode_spaminfo($ref->{info});
34db0c3f
DM
880 $res->{header} = $header;
881 $res->{content} = $content;
882 }
6e8886d4 883
6e8886d4
DM
884
885 return $res;
886
887 }});
888
34db0c3f
DM
889PVE::APIServer::Formatter::register_page_formatter(
890 'format' => 'htmlmail',
891 method => 'GET',
892 path => '/quarantine/content',
893 code => sub {
894 my ($res, $data, $param, $path, $auth, $config) = @_;
895
896 if(!HTTP::Status::is_success($res->{status})) {
897 return ("Error $res->{status}: $res->{message}", "text/plain");
898 }
899
900 my $ct = "text/html;charset=UTF-8";
901
902 my $raw = $data->{content};
903
904 return (encode('UTF-8', $raw), $ct, 1);
905});
906
157a946b
DM
907__PACKAGE__->register_method ({
908 name =>'action',
909 path => 'content',
910 method => 'POST',
911 description => "Execute quarantine actions.",
912 permissions => { check => [ 'admin', 'qmanager', 'quser'] },
913 protected => 1,
914 parameters => {
915 additionalProperties => 0,
916 properties => {
917 id => {
918 description => 'Unique ID',
919 type => 'string',
920 pattern => 'C\d+R\d+',
921 maxLength => 40,
922 },
923 action => {
924 description => 'Action - specify what you want to do with the mail.',
925 type => 'string',
926 enum => ['whitelist', 'blacklist', 'deliver', 'delete'],
927 },
928 },
929 },
930 returns => { type => "null" },
931 code => sub {
932 my ($param) = @_;
933
934 my $rpcenv = PMG::RESTEnvironment->get();
935 my $authuser = $rpcenv->get_user();
936 my $role = $rpcenv->get_role();
937 my $action = $param->{action};
938
939 my ($cid, $rid) = $param->{id} =~ m/^C(\d+)R(\d+)$/;
940 $cid = int($cid);
941 $rid = int($rid);
942
943 my $dbh = PMG::DBTools::open_ruledb();
944
945 my $ref = PMG::DBTools::load_mail_data($dbh, $cid, $rid);
946
947 if ($role eq 'quser') {
948 raise_perm_exc("mail does not belong to user '$authuser'")
949 if $authuser ne $ref->{pmail};
950 }
951
952 my $sender = $get_real_sender->($ref);
953 my $username = $ref->{pmail};
954
955 if ($action eq 'whitelist') {
e84bf942 956 PMG::Quarantine::add_to_blackwhite($dbh, $username, 'WL', [ $sender ]);
157a946b 957 } elsif ($action eq 'blacklist') {
e84bf942 958 PMG::Quarantine::add_to_blackwhite($dbh, $username, 'BL', [ $sender ]);
157a946b 959 } elsif ($action eq 'deliver') {
e84bf942
DM
960 my $targets = [ $ref->{pmail} ];
961 PMG::Quarantine::deliver_quarantined_mail($dbh, $ref, $targets);
157a946b 962 } elsif ($action eq 'delete') {
e84bf942
DM
963 PMG::Quarantine::delete_quarantined_mail($dbh, $ref);
964 } else {
965 die "internal error"; # should not be reached
157a946b
DM
966 }
967
968 return undef;
969 }});
e84bf942 970
b66faa68 9711;