]>
Commit | Line | Data |
---|---|---|
b66faa68 DM |
1 | package PMG::API2::Quarantine; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use Time::Local; | |
6 | use Time::Zone; | |
7 | use Data::Dumper; | |
8 | ||
dae021a8 DM |
9 | use Mail::Header; |
10 | ||
b66faa68 DM |
11 | use PVE::SafeSyslog; |
12 | use PVE::Exception qw(raise_param_exc); | |
13 | use PVE::Tools qw(extract_param); | |
14 | use PVE::JSONSchema qw(get_standard_option); | |
15 | use PVE::RESTHandler; | |
16 | use PVE::INotify; | |
17 | ||
dae021a8 | 18 | use PMG::Utils; |
b66faa68 DM |
19 | use PMG::AccessControl; |
20 | use PMG::DBTools; | |
21 | ||
22 | use base qw(PVE::RESTHandler); | |
23 | ||
24 | ||
dae021a8 DM |
25 | my $parse_header_info = sub { |
26 | my ($ref) = @_; | |
27 | ||
28 | my $res = { subject => '', from => '' }; | |
29 | ||
30 | my @lines = split('\n', $ref->{header}); | |
31 | my $head = Mail::Header->new(\@lines); | |
32 | ||
33 | $res->{subject} = PMG::Utils::decode_rfc1522(PVE::Tools::trim($head->get('subject'))) // ''; | |
34 | ||
35 | my @fromarray = split('\s*,\s*', $head->get('from') || $ref->{sender}); | |
36 | ||
37 | $res->{from} = PMG::Utils::decode_rfc1522(PVE::Tools::trim ($fromarray[0])) // ''; | |
38 | ||
39 | my $sender = PMG::Utils::decode_rfc1522(PVE::Tools::trim($head->get('sender'))); | |
40 | $res->{sender} = $sender if $sender; | |
41 | ||
42 | $res->{envelope_sender} = $ref->{sender}; | |
43 | $res->{receiver} = $ref->{receiver}; | |
44 | $res->{id} = $ref->{cid} . '_' . $ref->{rid}; | |
45 | $res->{time} = $ref->{time}; | |
46 | $res->{bytes} = $ref->{bytes}; | |
47 | ||
48 | return $res; | |
49 | }; | |
50 | ||
b66faa68 DM |
51 | __PACKAGE__->register_method ({ |
52 | name => 'index', | |
53 | path => '', | |
54 | method => 'GET', | |
55 | permissions => { user => 'all' }, | |
56 | description => "Directory index.", | |
57 | parameters => { | |
58 | additionalProperties => 0, | |
59 | properties => {}, | |
60 | }, | |
61 | returns => { | |
62 | type => 'array', | |
63 | items => { | |
64 | type => "object", | |
65 | properties => {}, | |
66 | }, | |
67 | links => [ { rel => 'child', href => "{name}" } ], | |
68 | }, | |
69 | code => sub { | |
70 | my ($param) = @_; | |
71 | ||
72 | my $result = [ | |
73 | { name => 'deliver' }, | |
74 | { name => 'spam' }, | |
75 | { name => 'virus' }, | |
76 | ]; | |
77 | ||
78 | return $result; | |
79 | }}); | |
80 | ||
81 | __PACKAGE__->register_method ({ | |
82 | name => 'spam', | |
83 | path => 'spam', | |
84 | method => 'GET', | |
85 | permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] }, | |
86 | description => "Show spam mails distribution (per day).", | |
87 | parameters => { | |
88 | additionalProperties => 0, | |
89 | properties => { | |
90 | starttime => { | |
91 | description => "Only consider entries newer than 'startime' (unix epoch).", | |
92 | type => 'integer', | |
93 | minimum => 0, | |
94 | optional => 1, | |
95 | }, | |
96 | endtime => { | |
97 | description => "Only consider entries older than 'endtime' (unix epoch).", | |
98 | type => 'integer', | |
99 | minimum => 1, | |
100 | optional => 1, | |
101 | }, | |
102 | pmail => { | |
ded33c7c | 103 | 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.", |
b66faa68 DM |
104 | type => 'string', format => 'email', |
105 | optional => 1, | |
106 | }, | |
107 | }, | |
108 | }, | |
109 | returns => { | |
110 | type => 'array', | |
111 | items => { | |
112 | type => "object", | |
113 | properties => { | |
114 | day => { | |
115 | description => "Day (as unix epoch).", | |
116 | type => 'integer', | |
117 | }, | |
bc1ebe25 | 118 | count => { |
b66faa68 DM |
119 | description => "Number of quarantine entries.", |
120 | type => 'integer', | |
121 | }, | |
122 | spamavg => { | |
123 | description => "Average spam level.", | |
124 | type => 'number', | |
bc1ebe25 | 125 | }, |
b66faa68 DM |
126 | }, |
127 | }, | |
ded33c7c | 128 | links => [ { rel => 'child', href => "{day}" } ], |
b66faa68 DM |
129 | }, |
130 | code => sub { | |
131 | my ($param) = @_; | |
132 | ||
133 | my $rpcenv = PMG::RESTEnvironment->get(); | |
134 | my $authuser = $rpcenv->get_user(); | |
135 | my $role = $rpcenv->get_role(); | |
136 | ||
137 | my $pmail = $param->{pmail}; | |
138 | ||
139 | if ($role eq 'quser') { | |
140 | raise_param_exc({ pmail => "paramater not allwed with role '$role'"}) | |
141 | if defined($pmail); | |
142 | $pmail = $authuser; | |
ded33c7c DM |
143 | } else { |
144 | raise_param_exc({ pmail => "paramater required with role '$role'"}) | |
145 | if !defined($pmail); | |
b66faa68 DM |
146 | } |
147 | ||
148 | my $res = []; | |
bc1ebe25 | 149 | |
b66faa68 DM |
150 | my $dbh = PMG::DBTools::open_ruledb(); |
151 | ||
ec7035c2 | 152 | my $start = $param->{starttime}; |
b66faa68 DM |
153 | my $end = $param->{endtime}; |
154 | ||
155 | my $timezone = tz_local_offset(); | |
156 | ||
157 | my $sth = $dbh->prepare( | |
158 | "SELECT " . | |
159 | "((time + $timezone) / 86400) * 86400 - $timezone as day, " . | |
160 | "count (ID) as count, avg (Spamlevel) as spamavg " . | |
161 | "FROM CMailStore, CMSReceivers WHERE " . | |
ec7035c2 DM |
162 | (defined($start) ? "time >= $start AND " : '') . |
163 | (defined($end) ? "time < $end AND " : '') . | |
ded33c7c | 164 | "pmail = ? AND " . |
b66faa68 DM |
165 | "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " . |
166 | "AND Status = 'N' " . | |
167 | "GROUP BY day " . | |
168 | "ORDER BY day DESC"); | |
169 | ||
ded33c7c DM |
170 | $sth->execute($pmail); |
171 | ||
172 | while (my $ref = $sth->fetchrow_hashref()) { | |
173 | push @$res, $ref; | |
174 | } | |
175 | ||
176 | return $res; | |
177 | }}); | |
178 | ||
179 | __PACKAGE__->register_method ({ | |
180 | name => 'spamlist', | |
181 | path => 'spam/{starttime}', | |
182 | method => 'GET', | |
183 | permissions => { check => [ 'admin', 'qmanager', 'audit', 'quser'] }, | |
184 | description => "Show spam mails distribution (per day).", | |
185 | parameters => { | |
186 | additionalProperties => 0, | |
187 | properties => { | |
188 | starttime => { | |
189 | description => "Only consider entries newer than 'starttime' (unix epoch).", | |
190 | type => 'integer', | |
191 | minimum => 0, | |
192 | }, | |
193 | endtime => { | |
194 | description => "Only consider entries older than 'endtime' (unix epoch). This is set to '<start> + 1day' by default.", | |
195 | type => 'integer', | |
196 | minimum => 1, | |
197 | optional => 1, | |
198 | }, | |
199 | pmail => { | |
200 | 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.", | |
201 | type => 'string', format => 'email', | |
202 | optional => 1, | |
203 | }, | |
204 | }, | |
205 | }, | |
206 | returns => { | |
207 | type => 'array', | |
208 | items => { | |
209 | type => "object", | |
dae021a8 DM |
210 | properties => { |
211 | id => { | |
212 | description => 'Unique ID', | |
213 | type => 'string', | |
214 | }, | |
215 | bytes => { | |
216 | description => "Size of raw email.", | |
217 | type => 'integer' , | |
218 | }, | |
219 | envelope_sender => { | |
220 | description => "SMTP envelope sender.", | |
221 | type => 'string', | |
222 | }, | |
223 | from => { | |
224 | description => "Header 'From' field.", | |
225 | type => 'string', | |
226 | }, | |
227 | sender => { | |
228 | description => "Header 'Sender' field.", | |
229 | type => 'string', | |
230 | optional => 1, | |
231 | }, | |
232 | receiver => { | |
233 | description => "Receiver email address", | |
234 | type => 'string', | |
235 | }, | |
236 | subject => { | |
237 | description => "Header 'Subject' field.", | |
238 | type => 'string', | |
239 | }, | |
240 | time => { | |
241 | description => "Receive time stamp", | |
242 | type => 'integer', | |
243 | }, | |
244 | }, | |
ded33c7c DM |
245 | }, |
246 | }, | |
247 | code => sub { | |
248 | my ($param) = @_; | |
249 | ||
250 | my $rpcenv = PMG::RESTEnvironment->get(); | |
251 | my $authuser = $rpcenv->get_user(); | |
252 | my $role = $rpcenv->get_role(); | |
253 | ||
254 | my $pmail = $param->{pmail}; | |
255 | ||
256 | if ($role eq 'quser') { | |
257 | raise_param_exc({ pmail => "paramater not allwed with role '$role'"}) | |
258 | if defined($pmail); | |
259 | $pmail = $authuser; | |
b66faa68 | 260 | } else { |
ded33c7c DM |
261 | raise_param_exc({ pmail => "paramater required with role '$role'"}) |
262 | if !defined($pmail); | |
b66faa68 DM |
263 | } |
264 | ||
ded33c7c DM |
265 | my $res = []; |
266 | ||
267 | my $dbh = PMG::DBTools::open_ruledb(); | |
268 | ||
269 | my $start = $param->{starttime}; | |
270 | my $end = $param->{endtime} // ($start + 86400); | |
271 | ||
272 | my $sth = $dbh->prepare( | |
273 | "SELECT * " . | |
274 | "FROM CMailStore, CMSReceivers WHERE " . | |
275 | "pmail = ? AND time >= $start AND time < $end AND " . | |
276 | "QType = 'S' AND CID = CMailStore_CID AND RID = CMailStore_RID " . | |
277 | "AND Status = 'N' ORDER BY pmail, time, receiver"); | |
278 | ||
279 | $sth->execute($pmail); | |
280 | ||
b66faa68 | 281 | while (my $ref = $sth->fetchrow_hashref()) { |
dae021a8 DM |
282 | my $data = $parse_header_info->($ref); |
283 | push @$res, $data; | |
b66faa68 DM |
284 | } |
285 | ||
286 | return $res; | |
287 | }}); | |
288 | ||
289 | 1; |