]> git.proxmox.com Git - pmg-api.git/blame - PMG/API2/Quarantine.pm
implement virus quarantine API /quarantine/virus
[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
ded33c7c 433__PACKAGE__->register_method ({
83ce499f
DC
434 name => 'spam',
435 path => 'spam',
ded33c7c
DM
436 method => 'GET',
437 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
83ce499f 438 description => "Get a list of quarantined spam mails in the given timeframe (default the last 24 hours) for the given user.",
ded33c7c
DM
439 parameters => {
440 additionalProperties => 0,
441 properties => {
442 starttime => {
83ce499f 443 description => "Only consider entries newer than 'starttime' (unix epoch). This is set to 'now - 1day' by default.",
ded33c7c
DM
444 type => 'integer',
445 minimum => 0,
83ce499f 446 optional => 1,
ded33c7c
DM
447 },
448 endtime => {
449 description => "Only consider entries older than 'endtime' (unix epoch). This is set to '<start> + 1day' by default.",
450 type => 'integer',
451 minimum => 1,
452 optional => 1,
453 },
157a946b 454 pmail => $pmail_param_type,
ded33c7c
DM
455 },
456 },
457 returns => {
458 type => 'array',
459 items => {
460 type => "object",
dae021a8
DM
461 properties => {
462 id => {
463 description => 'Unique ID',
464 type => 'string',
465 },
466 bytes => {
467 description => "Size of raw email.",
468 type => 'integer' ,
469 },
470 envelope_sender => {
471 description => "SMTP envelope sender.",
472 type => 'string',
473 },
474 from => {
475 description => "Header 'From' field.",
476 type => 'string',
477 },
478 sender => {
479 description => "Header 'Sender' field.",
480 type => 'string',
481 optional => 1,
482 },
483 receiver => {
484 description => "Receiver email address",
485 type => 'string',
486 },
487 subject => {
488 description => "Header 'Subject' field.",
489 type => 'string',
490 },
491 time => {
492 description => "Receive time stamp",
493 type => 'integer',
494 },
1284c016
DM
495 spamlevel => {
496 description => "Spam score.",
497 type => 'number',
498 },
dae021a8 499 },
ded33c7c
DM
500 },
501 },
502 code => sub {
503 my ($param) = @_;
504
505 my $rpcenv = PMG::RESTEnvironment->get();
506 my $authuser = $rpcenv->get_user();
507 my $role = $rpcenv->get_role();
508
157a946b 509 my $pmail = $verify_optional_pmail->($authuser, $role, $param->{pmail});
b66faa68 510
ded33c7c
DM
511 my $res = [];
512
513 my $dbh = PMG::DBTools::open_ruledb();
514
83ce499f 515 my $start = $param->{starttime} // (time - 86400);
ded33c7c
DM
516 my $end = $param->{endtime} // ($start + 86400);
517
518 my $sth = $dbh->prepare(
519 "SELECT * " .
520 "FROM CMailStore, CMSReceivers WHERE " .
521 "pmail = ? AND time >= $start AND time < $end AND " .
522 "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
523 "AND Status = 'N' ORDER BY pmail, time, receiver");
524
525 $sth->execute($pmail);
526
b66faa68 527 while (my $ref = $sth->fetchrow_hashref()) {
dae021a8
DM
528 my $data = $parse_header_info->($ref);
529 push @$res, $data;
b66faa68
DM
530 }
531
532 return $res;
533 }});
534
bb01dcf8
DM
535__PACKAGE__->register_method ({
536 name => 'virus',
537 path => 'virus',
538 method => 'GET',
539 permissions => { check => [ 'admin', 'qmanager', 'audit' ] },
540 description => "Get a list of quarantined virus mails in the given timeframe (default the last 24 hours).",
541 parameters => {
542 additionalProperties => 0,
543 properties => {
544 starttime => {
545 description => "Only consider entries newer than 'starttime' (unix epoch). This is set to 'now - 1day' by default.",
546 type => 'integer',
547 minimum => 0,
548 optional => 1,
549 },
550 endtime => {
551 description => "Only consider entries older than 'endtime' (unix epoch). This is set to '<start> + 1day' by default.",
552 type => 'integer',
553 minimum => 1,
554 optional => 1,
555 },
556 },
557 },
558 returns => {
559 type => 'array',
560 items => {
561 type => "object",
562 properties => {
563 id => {
564 description => 'Unique ID',
565 type => 'string',
566 },
567 bytes => {
568 description => "Size of raw email.",
569 type => 'integer' ,
570 },
571 envelope_sender => {
572 description => "SMTP envelope sender.",
573 type => 'string',
574 },
575 from => {
576 description => "Header 'From' field.",
577 type => 'string',
578 },
579 sender => {
580 description => "Header 'Sender' field.",
581 type => 'string',
582 optional => 1,
583 },
584 receiver => {
585 description => "Receiver email address",
586 type => 'string',
587 },
588 subject => {
589 description => "Header 'Subject' field.",
590 type => 'string',
591 },
592 time => {
593 description => "Receive time stamp",
594 type => 'integer',
595 },
596 virusname => {
597 description => "Virus name.",
598 type => 'string',
599 },
600 },
601 },
602 },
603 code => sub {
604 my ($param) = @_;
605
606 my $rpcenv = PMG::RESTEnvironment->get();
607 my $authuser = $rpcenv->get_user();
608 my $role = $rpcenv->get_role();
609
610
611 my $res = [];
612
613 my $dbh = PMG::DBTools::open_ruledb();
614
615 my $start = $param->{starttime} // (time - 86400);
616 my $end = $param->{endtime} // ($start + 86400);
617
618 my $sth = $dbh->prepare(
619 "SELECT * " .
620 "FROM CMailStore, CMSReceivers WHERE " .
621 "time >= $start AND time < $end AND " .
622 "QType = 'V' AND CID = CMailStore_CID AND RID = CMailStore_RID " .
623 "AND Status = 'N' ORDER BY time, receiver");
624
625 $sth->execute();
626
627 while (my $ref = $sth->fetchrow_hashref()) {
628 my $data = $parse_header_info->($ref);
629 push @$res, $data;
630 }
631
632 return $res;
633 }});
634
6e8886d4
DM
635__PACKAGE__->register_method ({
636 name => 'content',
637 path => 'content',
638 method => 'GET',
639 permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] },
34db0c3f 640 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
641 parameters => {
642 additionalProperties => 0,
643 properties => {
644 id => {
645 description => 'Unique ID',
646 type => 'string',
647 pattern => 'C\d+R\d+',
648 maxLength => 40,
649 },
34db0c3f
DM
650 raw => {
651 description => "Display 'raw' eml data. This is only used with the 'htmlmail' formatter.",
652 type => 'boolean',
653 optional => 1,
654 default => 0,
655 },
6e8886d4
DM
656 },
657 },
658 returns => {
659 type => "object",
cd31bb45
DM
660 properties => {
661 id => {
662 description => 'Unique ID',
663 type => 'string',
664 },
665 bytes => {
666 description => "Size of raw email.",
667 type => 'integer' ,
668 },
669 envelope_sender => {
670 description => "SMTP envelope sender.",
671 type => 'string',
672 },
673 from => {
674 description => "Header 'From' field.",
675 type => 'string',
676 },
677 sender => {
678 description => "Header 'Sender' field.",
679 type => 'string',
680 optional => 1,
681 },
682 receiver => {
683 description => "Receiver email address",
684 type => 'string',
685 },
686 subject => {
687 description => "Header 'Subject' field.",
688 type => 'string',
689 },
690 time => {
691 description => "Receive time stamp",
692 type => 'integer',
693 },
694 spamlevel => {
695 description => "Spam score.",
696 type => 'number',
697 },
698 spaminfo => {
699 description => "Information about matched spam tests (name, score, desc, url).",
700 type => 'array',
701 },
702 header => {
703 description => "Raw email header data.",
704 type => 'string',
705 },
706 content => {
707 description => "Raw email data (first 4096 bytes). Useful for preview. NOTE: The 'htmlmail' formatter displays the whole email.",
708 type => 'string',
6eac8473 709 },
cd31bb45 710 },
6e8886d4
DM
711 },
712 code => sub {
713 my ($param) = @_;
714
715 my $rpcenv = PMG::RESTEnvironment->get();
716 my $authuser = $rpcenv->get_user();
717 my $role = $rpcenv->get_role();
34db0c3f 718 my $format = $rpcenv->get_format();
6e8886d4
DM
719
720 my ($cid, $rid) = $param->{id} =~ m/^C(\d+)R(\d+)$/;
721 $cid = int($cid);
722 $rid = int($rid);
723
724 my $dbh = PMG::DBTools::open_ruledb();
725
726 my $ref = PMG::DBTools::load_mail_data($dbh, $cid, $rid);
727
728 if ($role eq 'quser') {
729 raise_perm_exc("mail does not belong to user '$authuser'")
730 if $authuser ne $ref->{pmail};
731 }
732
733 my $res = $parse_header_info->($ref);
734
6e8886d4
DM
735
736 my $filename = $ref->{file};
737 my $spooldir = $PMG::MailQueue::spooldir;
738
739 my $path = "$spooldir/$filename";
740
34db0c3f
DM
741 if ($format eq 'htmlmail') {
742
743 my $cfg = PMG::Config->new();
744 my $viewimages = $cfg->get('spamquar', 'viewimages');
745 my $allowhref = $cfg->get('spamquar', 'allowhrefs');
746
34db0c3f
DM
747 $res->{content} = PMG::HTMLMail::email_to_html($path, $param->{raw}, $viewimages, $allowhref);
748
157a946b
DM
749 # to make result verification happy
750 $res->{file} = '';
751 $res->{header} = '';
752 $res->{spaminfo} = [];
34db0c3f 753 } else {
cd31bb45 754 # include additional details
34db0c3f 755
cd31bb45 756 my ($header, $content) = PMG::HTMLMail::read_raw_email($path, 4096);
157a946b 757
cd31bb45
DM
758 $res->{file} = $ref->{file};
759 $res->{spaminfo} = decode_spaminfo($ref->{info});
34db0c3f
DM
760 $res->{header} = $header;
761 $res->{content} = $content;
762 }
6e8886d4 763
6e8886d4
DM
764
765 return $res;
766
767 }});
768
34db0c3f
DM
769PVE::APIServer::Formatter::register_page_formatter(
770 'format' => 'htmlmail',
771 method => 'GET',
772 path => '/quarantine/content',
773 code => sub {
774 my ($res, $data, $param, $path, $auth, $config) = @_;
775
776 if(!HTTP::Status::is_success($res->{status})) {
777 return ("Error $res->{status}: $res->{message}", "text/plain");
778 }
779
780 my $ct = "text/html;charset=UTF-8";
781
782 my $raw = $data->{content};
783
784 return (encode('UTF-8', $raw), $ct, 1);
785});
786
157a946b
DM
787__PACKAGE__->register_method ({
788 name =>'action',
789 path => 'content',
790 method => 'POST',
791 description => "Execute quarantine actions.",
792 permissions => { check => [ 'admin', 'qmanager', 'quser'] },
793 protected => 1,
794 parameters => {
795 additionalProperties => 0,
796 properties => {
797 id => {
798 description => 'Unique ID',
799 type => 'string',
800 pattern => 'C\d+R\d+',
801 maxLength => 40,
802 },
803 action => {
804 description => 'Action - specify what you want to do with the mail.',
805 type => 'string',
806 enum => ['whitelist', 'blacklist', 'deliver', 'delete'],
807 },
808 },
809 },
810 returns => { type => "null" },
811 code => sub {
812 my ($param) = @_;
813
814 my $rpcenv = PMG::RESTEnvironment->get();
815 my $authuser = $rpcenv->get_user();
816 my $role = $rpcenv->get_role();
817 my $action = $param->{action};
818
819 my ($cid, $rid) = $param->{id} =~ m/^C(\d+)R(\d+)$/;
820 $cid = int($cid);
821 $rid = int($rid);
822
823 my $dbh = PMG::DBTools::open_ruledb();
824
825 my $ref = PMG::DBTools::load_mail_data($dbh, $cid, $rid);
826
827 if ($role eq 'quser') {
828 raise_perm_exc("mail does not belong to user '$authuser'")
829 if $authuser ne $ref->{pmail};
830 }
831
832 my $sender = $get_real_sender->($ref);
833 my $username = $ref->{pmail};
834
835 if ($action eq 'whitelist') {
e84bf942 836 PMG::Quarantine::add_to_blackwhite($dbh, $username, 'WL', [ $sender ]);
157a946b 837 } elsif ($action eq 'blacklist') {
e84bf942 838 PMG::Quarantine::add_to_blackwhite($dbh, $username, 'BL', [ $sender ]);
157a946b 839 } elsif ($action eq 'deliver') {
e84bf942
DM
840 my $targets = [ $ref->{pmail} ];
841 PMG::Quarantine::deliver_quarantined_mail($dbh, $ref, $targets);
157a946b 842 } elsif ($action eq 'delete') {
e84bf942
DM
843 PMG::Quarantine::delete_quarantined_mail($dbh, $ref);
844 } else {
845 die "internal error"; # should not be reached
157a946b
DM
846 }
847
848 return undef;
849 }});
e84bf942 850
b66faa68 8511;