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