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