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