blob: 51cdd73c2d5da1ee00c3aef1e9399f5bf1d9d06e [file] [log] [blame]
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +01001<?php
2function bcc($_action, $_data = null, $attr = null) {
3 global $pdo;
4 global $lang;
5 if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
6 return false;
7 }
8 switch ($_action) {
9 case 'add':
10 if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
11 $_SESSION['return'][] = array(
12 'type' => 'danger',
13 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
14 'msg' => 'access_denied'
15 );
16 return false;
17 }
18 $local_dest = strtolower(trim($_data['local_dest']));
19 $bcc_dest = $_data['bcc_dest'];
20 $active = intval($_data['active']);
21 $type = $_data['type'];
22 if ($type != 'sender' && $type != 'rcpt') {
23 $_SESSION['return'][] = array(
24 'type' => 'danger',
25 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
26 'msg' => 'invalid_bcc_map_type'
27 );
28 return false;
29 }
30 if (empty($bcc_dest)) {
31 $_SESSION['return'][] = array(
32 'type' => 'danger',
33 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
34 'msg' => 'bcc_empty'
35 );
36 return false;
37 }
38 if (is_valid_domain_name($local_dest)) {
39 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
40 $_SESSION['return'][] = array(
41 'type' => 'danger',
42 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
43 'msg' => 'access_denied'
44 );
45 return false;
46 }
47 $domain = idn_to_ascii($local_dest, 0, INTL_IDNA_VARIANT_UTS46);
48 $local_dest_sane = '@' . idn_to_ascii($local_dest, 0, INTL_IDNA_VARIANT_UTS46);
49 }
50 elseif (filter_var($local_dest, FILTER_VALIDATE_EMAIL)) {
51 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
52 $_SESSION['return'][] = array(
53 'type' => 'danger',
54 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
55 'msg' => 'access_denied'
56 );
57 return false;
58 }
59 $domain = mailbox('get', 'mailbox_details', $local_dest)['domain'];
60 if (empty($domain)) {
61 return false;
62 }
63 $local_dest_sane = $local_dest;
64 }
65 else {
66 return false;
67 }
68 if (!filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) {
69 $_SESSION['return'][] = array(
70 'type' => 'danger',
71 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
72 'msg' => array('bcc_must_be_email', htmlspecialchars($bcc_dest))
73 );
74 return false;
75 }
76
77 $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps`
78 WHERE `local_dest` = :local_dest AND `type` = :type");
79 $stmt->execute(array(':local_dest' => $local_dest_sane, ':type' => $type));
80 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
81
82 if ($num_results != 0) {
83 $_SESSION['return'][] = array(
84 'type' => 'danger',
85 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
86 'msg' => array('bcc_exists', htmlspecialchars($local_dest_sane), $type)
87 );
88 return false;
89 }
90 $stmt = $pdo->prepare("INSERT INTO `bcc_maps` (`local_dest`, `bcc_dest`, `domain`, `active`, `type`) VALUES
91 (:local_dest, :bcc_dest, :domain, :active, :type)");
92 $stmt->execute(array(
93 ':local_dest' => $local_dest_sane,
94 ':bcc_dest' => $bcc_dest,
95 ':domain' => $domain,
96 ':active' => $active,
97 ':type' => $type
98 ));
99 $_SESSION['return'][] = array(
100 'type' => 'success',
101 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
102 'msg' => 'bcc_saved'
103 );
104 break;
105 case 'edit':
106 if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
107 $_SESSION['return'][] = array(
108 'type' => 'danger',
109 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
110 'msg' => 'access_denied'
111 );
112 return false;
113 }
114 $ids = (array)$_data['id'];
115 foreach ($ids as $id) {
116 $is_now = bcc('details', $id);
117 if (!empty($is_now)) {
118 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
119 $bcc_dest = (!empty($_data['bcc_dest'])) ? $_data['bcc_dest'] : $is_now['bcc_dest'];
120 $local_dest = $is_now['local_dest'];
121 $type = (!empty($_data['type'])) ? $_data['type'] : $is_now['type'];
122 }
123 else {
124 $_SESSION['return'][] = array(
125 'type' => 'danger',
126 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
127 'msg' => 'access_denied'
128 );
129 continue;
130 }
131 $active = intval($_data['active']);
132 if (!filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) {
133 $_SESSION['return'][] = array(
134 'type' => 'danger',
135 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
136 'msg' => array('bcc_must_be_email', $bcc_dest)
137 );
138 continue;
139 }
140 if (empty($bcc_dest)) {
141 $_SESSION['return'][] = array(
142 'type' => 'danger',
143 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
144 'msg' => array('bcc_must_be_email', $bcc_dest)
145 );
146 continue;
147 }
148 $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps`
149 WHERE `local_dest` = :local_dest AND `type` = :type");
150 $stmt->execute(array(':local_dest' => $local_dest, ':type' => $type));
151 $id_now = $stmt->fetch(PDO::FETCH_ASSOC)['id'];
152
153 if (isset($id_now) && $id_now != $id) {
154 $_SESSION['return'][] = array(
155 'type' => 'danger',
156 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
157 'msg' => array('bcc_exists', htmlspecialchars($local_dest), $type)
158 );
159 continue;
160 }
161
162 $stmt = $pdo->prepare("UPDATE `bcc_maps` SET `bcc_dest` = :bcc_dest, `active` = :active, `type` = :type WHERE `id`= :id");
163 $stmt->execute(array(
164 ':bcc_dest' => $bcc_dest,
165 ':active' => $active,
166 ':type' => $type,
167 ':id' => $id
168 ));
169 $_SESSION['return'][] = array(
170 'type' => 'success',
171 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
172 'msg' => array('bcc_edited', $bcc_dest)
173 );
174 }
175 break;
176 case 'details':
177 $bccdata = array();
178 $id = intval($_data);
179
180 $stmt = $pdo->prepare("SELECT `id`,
181 `local_dest`,
182 `bcc_dest`,
183 `active`,
184 `type`,
185 `created`,
186 `domain`,
187 `modified` FROM `bcc_maps`
188 WHERE `id` = :id");
189 $stmt->execute(array(':id' => $id));
190 $bccdata = $stmt->fetch(PDO::FETCH_ASSOC);
191
192 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $bccdata['domain'])) {
193 $bccdata = null;
194 return false;
195 }
196 return $bccdata;
197 break;
198 case 'get':
199 $bccdata = array();
200 $all_items = array();
201 $id = intval($_data);
202
203 $stmt = $pdo->query("SELECT `id`, `domain` FROM `bcc_maps`");
204 $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
205
206 foreach ($all_items as $i) {
207 if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $i['domain'])) {
208 $bccdata[] = $i['id'];
209 }
210 }
211 $all_items = null;
212 return $bccdata;
213 break;
214 case 'delete':
215 if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
216 $_SESSION['return'][] = array(
217 'type' => 'danger',
218 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
219 'msg' => 'access_denied'
220 );
221 return false;
222 }
223 $ids = (array)$_data['id'];
224 foreach ($ids as $id) {
225 if (!is_numeric($id)) {
226 return false;
227 }
228 $stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id");
229 $stmt->execute(array(':id' => $id));
230 $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain'];
231 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
232 $_SESSION['return'][] = array(
233 'type' => 'danger',
234 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
235 'msg' => 'access_denied'
236 );
237 continue;
238 }
239 $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `id`= :id");
240 $stmt->execute(array(':id' => $id));
241
242 $_SESSION['return'][] = array(
243 'type' => 'success',
244 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
245 'msg' => array('bcc_deleted', $id)
246 );
247 }
248 break;
249 }
250}
251
252function recipient_map($_action, $_data = null, $attr = null) {
253 global $pdo;
254 global $lang;
255 if ($_SESSION['mailcow_cc_role'] != "admin") {
256 return false;
257 }
258 switch ($_action) {
259 case 'add':
260 $old_dest = strtolower(trim($_data['recipient_map_old']));
261 if (substr($old_dest, 0, 1) == '@') {
262 $old_dest = substr($old_dest, 1);
263 }
264 $new_dest = strtolower(trim($_data['recipient_map_new']));
265 $active = intval($_data['active']);
266 if (is_valid_domain_name($old_dest)) {
267 $old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
268 }
269 elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
270 $old_dest_sane = $old_dest;
271 }
272 else {
273 $_SESSION['return'][] = array(
274 'type' => 'danger',
275 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
276 'msg' => array('invalid_recipient_map_old', htmlspecialchars($old_dest))
277 );
278 return false;
279 }
280 if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
281 $_SESSION['return'][] = array(
282 'type' => 'danger',
283 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
284 'msg' => array('invalid_recipient_map_new', htmlspecialchars($new_dest))
285 );
286 return false;
287 }
288 $rmaps = recipient_map('get');
289 foreach ($rmaps as $rmap) {
290 if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) {
291 $_SESSION['return'][] = array(
292 'type' => 'danger',
293 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
294 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane))
295 );
296 return false;
297 }
298 }
299 $stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES
300 (:old_dest, :new_dest, :active)");
301 $stmt->execute(array(
302 ':old_dest' => $old_dest_sane,
303 ':new_dest' => $new_dest,
304 ':active' => $active
305 ));
306 $_SESSION['return'][] = array(
307 'type' => 'success',
308 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
309 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest_sane))
310 );
311 break;
312 case 'edit':
313 $ids = (array)$_data['id'];
314 foreach ($ids as $id) {
315 $is_now = recipient_map('details', $id);
316 if (!empty($is_now)) {
317 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
318 $new_dest = (!empty($_data['recipient_map_new'])) ? $_data['recipient_map_new'] : $is_now['recipient_map_new'];
319 $old_dest = (!empty($_data['recipient_map_old'])) ? $_data['recipient_map_old'] : $is_now['recipient_map_old'];
320 if (substr($old_dest, 0, 1) == '@') {
321 $old_dest = substr($old_dest, 1);
322 }
323 }
324 else {
325 $_SESSION['return'][] = array(
326 'type' => 'danger',
327 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
328 'msg' => 'access_denied'
329 );
330 continue;
331 }
332 if (is_valid_domain_name($old_dest)) {
333 $old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
334 }
335 elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
336 $old_dest_sane = $old_dest;
337 }
338 else {
339 $_SESSION['return'][] = array(
340 'type' => 'danger',
341 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
342 'msg' => array('invalid_recipient_map_old', htmlspecialchars($old_dest))
343 );
344 continue;
345 }
346 if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
347 $_SESSION['return'][] = array(
348 'type' => 'danger',
349 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
350 'msg' => array('invalid_recipient_map_new', htmlspecialchars($new_dest))
351 );
352 continue;
353 }
354 $rmaps = recipient_map('get');
355 foreach ($rmaps as $rmap) {
356 if ($rmap == $id) { continue; }
357 if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) {
358 $_SESSION['return'][] = array(
359 'type' => 'danger',
360 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
361 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane))
362 );
363 return false;
364 }
365 }
366 $stmt = $pdo->prepare("UPDATE `recipient_maps` SET
367 `old_dest` = :old_dest,
368 `new_dest` = :new_dest,
369 `active` = :active
370 WHERE `id`= :id");
371 $stmt->execute(array(
372 ':old_dest' => $old_dest_sane,
373 ':new_dest' => $new_dest,
374 ':active' => $active,
375 ':id' => $id
376 ));
377 $_SESSION['return'][] = array(
378 'type' => 'success',
379 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
380 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest_sane))
381 );
382 }
383 break;
384 case 'details':
385 $mapdata = array();
386 $id = intval($_data);
387
388 $stmt = $pdo->prepare("SELECT `id`,
389 `old_dest` AS `recipient_map_old`,
390 `new_dest` AS `recipient_map_new`,
391 `active`,
392 `created`,
393 `modified` FROM `recipient_maps`
394 WHERE `id` = :id");
395 $stmt->execute(array(':id' => $id));
396 $mapdata = $stmt->fetch(PDO::FETCH_ASSOC);
397
398 return $mapdata;
399 break;
400 case 'get':
401 $mapdata = array();
402 $all_items = array();
403 $id = intval($_data);
404
405 $stmt = $pdo->query("SELECT `id` FROM `recipient_maps`");
406 $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
407
408 foreach ($all_items as $i) {
409 $mapdata[] = $i['id'];
410 }
411 $all_items = null;
412 return $mapdata;
413 break;
414 case 'delete':
415 $ids = (array)$_data['id'];
416 foreach ($ids as $id) {
417 if (!is_numeric($id)) {
418 return false;
419 }
420 $stmt = $pdo->prepare("DELETE FROM `recipient_maps` WHERE `id`= :id");
421 $stmt->execute(array(':id' => $id));
422 $_SESSION['return'][] = array(
423 'type' => 'success',
424 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
425 'msg' => array('recipient_map_entry_deleted', htmlspecialchars($id))
426 );
427 }
428 break;
429 }
430}