blob: fff419005c712bb3a3c064477d5e2af0e795a899 [file] [log] [blame]
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +01001<?php
2function mailbox($_action, $_type, $_data = null, $_extra = null) {
3 global $pdo;
4 global $redis;
5 global $lang;
6 global $MAILBOX_DEFAULT_ATTRIBUTES;
7 $_data_log = $_data;
8 !isset($_data_log['password']) ?: $_data_log['password'] = '*';
9 !isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
10 switch ($_action) {
11 case 'add':
12 switch ($_type) {
13 case 'time_limited_alias':
14 if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) {
15 $_SESSION['return'][] = array(
16 'type' => 'danger',
17 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
18 'msg' => 'access_denied'
19 );
20 return false;
21 }
22 if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) {
23 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) {
24 $_SESSION['return'][] = array(
25 'type' => 'danger',
26 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
27 'msg' => 'access_denied'
28 );
29 return false;
30 }
31 else {
32 $username = $_data['username'];
33 }
34 }
35 else {
36 $username = $_SESSION['mailcow_cc_username'];
37 }
38 if (!is_numeric($_data["validity"]) || $_data["validity"] > 672) {
39 $_SESSION['return'][] = array(
40 'type' => 'danger',
41 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
42 'msg' => 'validity_missing'
43 );
44 return false;
45 }
46 $domain = mailbox('get', 'mailbox_details', $username)['domain'];
47 if (!is_valid_domain_name($domain)) {
48 $_SESSION['return'][] = array(
49 'type' => 'danger',
50 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
51 'msg' => 'domain_invalid'
52 );
53 return false;
54 }
55 $validity = strtotime("+".$_data["validity"]." hour");
56 $letters = 'abcefghijklmnopqrstuvwxyz1234567890';
57 $random_name = substr(str_shuffle($letters), 0, 24);
58 $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES
59 (:address, :goto, :validity)");
60 $stmt->execute(array(
61 ':address' => $random_name . '@' . $domain,
62 ':goto' => $username,
63 ':validity' => $validity
64 ));
65 $_SESSION['return'][] = array(
66 'type' => 'success',
67 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
68 'msg' => array('mailbox_modified', $username)
69 );
70 break;
71 case 'global_filter':
72 if ($_SESSION['mailcow_cc_role'] != "admin") {
73 $_SESSION['return'][] = array(
74 'type' => 'danger',
75 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
76 'msg' => 'access_denied'
77 );
78 return false;
79 }
80 $sieve = new Sieve\SieveParser();
81 $script_data = $_data['script_data'];
82 $script_data = str_replace("\r\n", "\n", $script_data); // windows -> unix
83 $script_data = str_replace("\r", "\n", $script_data); // remaining -> unix
84 $filter_type = $_data['filter_type'];
85 try {
86 $sieve->parse($script_data);
87 }
88 catch (Exception $e) {
89 $_SESSION['return'][] = array(
90 'type' => 'danger',
91 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
92 'msg' => array('sieve_error', $e->getMessage())
93 );
94 return false;
95 }
96 if ($filter_type == 'prefilter') {
97 try {
98 if (file_exists('/global_sieve/before')) {
99 $filter_handle = fopen('/global_sieve/before', 'w');
100 if (!$filter_handle) {
101 throw new Exception($lang['danger']['file_open_error']);
102 }
103 fwrite($filter_handle, $script_data);
104 fclose($filter_handle);
105 }
106 $restart_response = json_decode(docker('post', 'dovecot-mailcow', 'restart'), true);
107 if ($restart_response['type'] == "success") {
108 $_SESSION['return'][] = array(
109 'type' => 'success',
110 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
111 'msg' => 'dovecot_restart_success'
112 );
113 }
114 else {
115 $_SESSION['return'][] = array(
116 'type' => 'warning',
117 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
118 'msg' => 'dovecot_restart_failed'
119 );
120 }
121 }
122 catch (Exception $e) {
123 $_SESSION['return'][] = array(
124 'type' => 'danger',
125 'log' => array(__FUNCTION__, $_action, $_data_log),
126 'msg' => array('global_filter_write_error', htmlspecialchars($e->getMessage()))
127 );
128 return false;
129 }
130 }
131 elseif ($filter_type == 'postfilter') {
132 try {
133 if (file_exists('/global_sieve/after')) {
134 $filter_handle = fopen('/global_sieve/after', 'w');
135 if (!$filter_handle) {
136 throw new Exception($lang['danger']['file_open_error']);
137 }
138 fwrite($filter_handle, $script_data);
139 fclose($filter_handle);
140 }
141 $restart_response = json_decode(docker('post', 'dovecot-mailcow', 'restart'), true);
142 if ($restart_response['type'] == "success") {
143 $_SESSION['return'][] = array(
144 'type' => 'success',
145 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
146 'msg' => 'dovecot_restart_success'
147 );
148 }
149 else {
150 $_SESSION['return'][] = array(
151 'type' => 'warning',
152 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
153 'msg' => 'dovecot_restart_failed'
154 );
155 }
156 }
157 catch (Exception $e) {
158 $_SESSION['return'][] = array(
159 'type' => 'danger',
160 'log' => array(__FUNCTION__, $_action, $_data_log),
161 'msg' => array('global_filter_write_error', htmlspecialchars($e->getMessage()))
162 );
163 return false;
164 }
165 }
166 else {
167 $_SESSION['return'][] = array(
168 'type' => 'danger',
169 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
170 'msg' => 'invalid_filter_type'
171 );
172 return false;
173 }
174 $_SESSION['return'][] = array(
175 'type' => 'success',
176 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
177 'msg' => 'global_filter_written'
178 );
179 return true;
180 case 'filter':
181 $sieve = new Sieve\SieveParser();
182 if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) {
183 $_SESSION['return'][] = array(
184 'type' => 'danger',
185 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
186 'msg' => 'access_denied'
187 );
188 return false;
189 }
190 if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) {
191 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) {
192 $_SESSION['return'][] = array(
193 'type' => 'danger',
194 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
195 'msg' => 'access_denied'
196 );
197 return false;
198 }
199 else {
200 $username = $_data['username'];
201 }
202 }
203 elseif ($_SESSION['mailcow_cc_role'] == "user") {
204 $username = $_SESSION['mailcow_cc_username'];
205 }
206 else {
207 $_SESSION['return'][] = array(
208 'type' => 'danger',
209 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
210 'msg' => 'no_user_defined'
211 );
212 return false;
213 }
214 $active = intval($_data['active']);
215 $script_data = $_data['script_data'];
216 $script_desc = $_data['script_desc'];
217 $filter_type = $_data['filter_type'];
218 if (empty($script_data)) {
219 $_SESSION['return'][] = array(
220 'type' => 'danger',
221 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
222 'msg' => 'script_empty'
223 );
224 return false;
225 }
226 try {
227 $sieve->parse($script_data);
228 }
229 catch (Exception $e) {
230 $_SESSION['return'][] = array(
231 'type' => 'danger',
232 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
233 'msg' => array('sieve_error', $e->getMessage())
234 );
235 return false;
236 }
237 if (empty($script_data) || empty($script_desc)) {
238 $_SESSION['return'][] = array(
239 'type' => 'danger',
240 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
241 'msg' => 'value_missing'
242 );
243 return false;
244 }
245 if ($filter_type != 'postfilter' && $filter_type != 'prefilter') {
246 $_SESSION['return'][] = array(
247 'type' => 'danger',
248 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
249 'msg' => 'filter_type'
250 );
251 return false;
252 }
253 if (!empty($active)) {
254 $script_name = 'active';
255 $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_name` = 'inactive' WHERE `username` = :username AND `filter_type` = :filter_type");
256 $stmt->execute(array(
257 ':username' => $username,
258 ':filter_type' => $filter_type
259 ));
260 }
261 else {
262 $script_name = 'inactive';
263 }
264 $stmt = $pdo->prepare("INSERT INTO `sieve_filters` (`username`, `script_data`, `script_desc`, `script_name`, `filter_type`)
265 VALUES (:username, :script_data, :script_desc, :script_name, :filter_type)");
266 $stmt->execute(array(
267 ':username' => $username,
268 ':script_data' => $script_data,
269 ':script_desc' => $script_desc,
270 ':script_name' => $script_name,
271 ':filter_type' => $filter_type
272 ));
273 $_SESSION['return'][] = array(
274 'type' => 'success',
275 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
276 'msg' => array('mailbox_modified', $username)
277 );
278 break;
279 case 'syncjob':
280 if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) {
281 $_SESSION['return'][] = array(
282 'type' => 'danger',
283 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
284 'msg' => 'access_denied'
285 );
286 return false;
287 }
288 if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) {
289 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) {
290 $_SESSION['return'][] = array(
291 'type' => 'danger',
292 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
293 'msg' => 'access_denied'
294 );
295 return false;
296 }
297 else {
298 $username = $_data['username'];
299 }
300 }
301 elseif ($_SESSION['mailcow_cc_role'] == "user") {
302 $username = $_SESSION['mailcow_cc_username'];
303 }
304 else {
305 $_SESSION['return'][] = array(
306 'type' => 'danger',
307 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
308 'msg' => 'no_user_defined'
309 );
310 return false;
311 }
312 $active = intval($_data['active']);
313 $subscribeall = intval($_data['subscribeall']);
314 $delete2duplicates = intval($_data['delete2duplicates']);
315 $delete1 = intval($_data['delete1']);
316 $delete2 = intval($_data['delete2']);
317 $timeout1 = intval($_data['timeout1']);
318 $timeout2 = intval($_data['timeout2']);
319 $skipcrossduplicates = intval($_data['skipcrossduplicates']);
320 $automap = intval($_data['automap']);
321 $port1 = $_data['port1'];
322 $host1 = strtolower($_data['host1']);
323 $password1 = $_data['password1'];
324 $exclude = $_data['exclude'];
325 $maxage = $_data['maxage'];
326 $maxbytespersecond = $_data['maxbytespersecond'];
327 $subfolder2 = $_data['subfolder2'];
328 $user1 = $_data['user1'];
329 $mins_interval = $_data['mins_interval'];
330 $enc1 = $_data['enc1'];
331 $custom_params = (empty(trim($_data['custom_params']))) ? '' : trim($_data['custom_params']);
332 // Workaround, fixme
333 if (strpos($custom_params, 'pipemess')) {
334 $custom_params = '';
335 }
336 if (empty($subfolder2)) {
337 $subfolder2 = "";
338 }
339 if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
340 $maxage = "0";
341 }
342 if (!isset($timeout1) || !filter_var($timeout1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
343 $timeout1 = "600";
344 }
345 if (!isset($timeout2) || !filter_var($timeout2, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
346 $timeout2 = "600";
347 }
348 if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
349 $maxbytespersecond = "0";
350 }
351 if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
352 $_SESSION['return'][] = array(
353 'type' => 'danger',
354 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
355 'msg' => 'access_denied'
356 );
357 return false;
358 }
359 if (!filter_var($mins_interval, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 43800)))) {
360 $_SESSION['return'][] = array(
361 'type' => 'danger',
362 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
363 'msg' => 'access_denied'
364 );
365 return false;
366 }
367 // if (!is_valid_domain_name($host1)) {
368 // $_SESSION['return'][] = array(
369 // 'type' => 'danger',
370 // 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
371 // 'msg' => 'access_denied'
372 // );
373 // return false;
374 // }
375 if ($enc1 != "TLS" && $enc1 != "SSL" && $enc1 != "PLAIN") {
376 $_SESSION['return'][] = array(
377 'type' => 'danger',
378 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
379 'msg' => 'access_denied'
380 );
381 return false;
382 }
383 if (@preg_match("/" . $exclude . "/", null) === false) {
384 $_SESSION['return'][] = array(
385 'type' => 'danger',
386 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
387 'msg' => 'access_denied'
388 );
389 return false;
390 }
391 $stmt = $pdo->prepare("SELECT '1' FROM `imapsync`
392 WHERE `user2` = :user2 AND `user1` = :user1 AND `host1` = :host1");
393 $stmt->execute(array(':user1' => $user1, ':user2' => $username, ':host1' => $host1));
394 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
395 if ($num_results != 0) {
396 $_SESSION['return'][] = array(
397 'type' => 'danger',
398 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
399 'msg' => array('object_exists', htmlspecialchars($host1 . ' / ' . $user1))
400 );
401 return false;
402 }
403 $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`)
404 VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)");
405 $stmt->execute(array(
406 ':user2' => $username,
407 ':custom_params' => $custom_params,
408 ':exclude' => $exclude,
409 ':maxage' => $maxage,
410 ':delete1' => $delete1,
411 ':delete2' => $delete2,
412 ':timeout1' => $timeout1,
413 ':timeout2' => $timeout2,
414 ':automap' => $automap,
415 ':skipcrossduplicates' => $skipcrossduplicates,
416 ':maxbytespersecond' => $maxbytespersecond,
417 ':subscribeall' => $subscribeall,
418 ':subfolder2' => $subfolder2,
419 ':host1' => $host1,
420 ':authmech1' => 'PLAIN',
421 ':user1' => $user1,
422 ':password1' => $password1,
423 ':mins_interval' => $mins_interval,
424 ':port1' => $port1,
425 ':enc1' => $enc1,
426 ':delete2duplicates' => $delete2duplicates,
427 ':active' => $active,
428 ));
429 $_SESSION['return'][] = array(
430 'type' => 'success',
431 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
432 'msg' => array('mailbox_modified', $username)
433 );
434 break;
435 case 'domain':
436 if ($_SESSION['mailcow_cc_role'] != "admin") {
437 $_SESSION['return'][] = array(
438 'type' => 'danger',
439 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
440 'msg' => 'access_denied'
441 );
442 return false;
443 }
444 $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
445 $description = $_data['description'];
446 if (empty($description)) {
447 $description = $domain;
448 }
449 $aliases = $_data['aliases'];
450 $mailboxes = $_data['mailboxes'];
451 $defquota = $_data['defquota'];
452 $maxquota = $_data['maxquota'];
453 $restart_sogo = $_data['restart_sogo'];
454 $quota = $_data['quota'];
455 if ($defquota > $maxquota) {
456 $_SESSION['return'][] = array(
457 'type' => 'danger',
458 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
459 'msg' => 'mailbox_defquota_exceeds_mailbox_maxquota'
460 );
461 return false;
462 }
463 if ($maxquota > $quota) {
464 $_SESSION['return'][] = array(
465 'type' => 'danger',
466 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
467 'msg' => 'mailbox_quota_exceeds_domain_quota'
468 );
469 return false;
470 }
471 if ($defquota == "0" || empty($defquota)) {
472 $_SESSION['return'][] = array(
473 'type' => 'danger',
474 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
475 'msg' => 'defquota_empty'
476 );
477 return false;
478 }
479 if ($maxquota == "0" || empty($maxquota)) {
480 $_SESSION['return'][] = array(
481 'type' => 'danger',
482 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
483 'msg' => 'maxquota_empty'
484 );
485 return false;
486 }
487 $active = intval($_data['active']);
488 $relay_all_recipients = intval($_data['relay_all_recipients']);
489 $relay_unknown_only = intval($_data['relay_unknown_only']);
490 $backupmx = intval($_data['backupmx']);
491 $gal = intval($_data['gal']);
492 if ($relay_all_recipients == 1) {
493 $backupmx = '1';
494 }
495 if ($relay_unknown_only == 1) {
496 $backupmx = 1;
497 $relay_all_recipients = 1;
498 }
499 if (!is_valid_domain_name($domain)) {
500 $_SESSION['return'][] = array(
501 'type' => 'danger',
502 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
503 'msg' => 'domain_invalid'
504 );
505 return false;
506 }
507 foreach (array($quota, $maxquota, $mailboxes, $aliases) as $data) {
508 if (!is_numeric($data)) {
509 $_SESSION['return'][] = array(
510 'type' => 'danger',
511 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
512 'msg' => array('object_is_not_numeric', htmlspecialchars($data))
513 );
514 return false;
515 }
516 }
517 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
518 WHERE `domain` = :domain");
519 $stmt->execute(array(':domain' => $domain));
520 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
521 $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain`
522 WHERE `alias_domain` = :domain");
523 $stmt->execute(array(':domain' => $domain));
524 $num_results = $num_results + count($stmt->fetchAll(PDO::FETCH_ASSOC));
525 if ($num_results != 0) {
526 $_SESSION['return'][] = array(
527 'type' => 'danger',
528 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
529 'msg' => array('domain_exists', htmlspecialchars($domain))
530 );
531 return false;
532 }
533 if ($domain == getenv('MAILCOW_HOSTNAME')) {
534 $_SESSION['return'][] = array(
535 'type' => 'danger',
536 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
537 'msg' => 'domain_cannot_match_hostname'
538 );
539 return false;
540 }
541 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `send_as` LIKE :domain");
542 $stmt->execute(array(
543 ':domain' => '%@' . $domain
544 ));
545 $stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `defquota`, `maxquota`, `quota`, `backupmx`, `gal`, `active`, `relay_unknown_only`, `relay_all_recipients`)
546 VALUES (:domain, :description, :aliases, :mailboxes, :defquota, :maxquota, :quota, :backupmx, :gal, :active, :relay_unknown_only, :relay_all_recipients)");
547 $stmt->execute(array(
548 ':domain' => $domain,
549 ':description' => $description,
550 ':aliases' => $aliases,
551 ':mailboxes' => $mailboxes,
552 ':defquota' => $defquota,
553 ':maxquota' => $maxquota,
554 ':quota' => $quota,
555 ':backupmx' => $backupmx,
556 ':gal' => $gal,
557 ':active' => $active,
558 ':relay_unknown_only' => $relay_unknown_only,
559 ':relay_all_recipients' => $relay_all_recipients
560 ));
561 try {
562 $redis->hSet('DOMAIN_MAP', $domain, 1);
563 }
564 catch (RedisException $e) {
565 $_SESSION['return'][] = array(
566 'type' => 'danger',
567 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
568 'msg' => array('redis_error', $e)
569 );
570 return false;
571 }
572 if (!empty(intval($_data['rl_value']))) {
573 ratelimit('edit', 'domain', array('rl_value' => $_data['rl_value'], 'rl_frame' => $_data['rl_frame'], 'object' => $domain));
574 }
575 if (!empty($restart_sogo)) {
576 $restart_response = json_decode(docker('post', 'sogo-mailcow', 'restart'), true);
577 if ($restart_response['type'] == "success") {
578 $_SESSION['return'][] = array(
579 'type' => 'success',
580 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
581 'msg' => array('domain_added', htmlspecialchars($domain))
582 );
583 return true;
584 }
585 else {
586 $_SESSION['return'][] = array(
587 'type' => 'warning',
588 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
589 'msg' => 'domain_added_sogo_failed'
590 );
591 return false;
592 }
593 }
594 $_SESSION['return'][] = array(
595 'type' => 'success',
596 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
597 'msg' => array('domain_added', htmlspecialchars($domain))
598 );
599 return true;
600 break;
601 case 'alias':
602 $addresses = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
603 $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
604 $active = intval($_data['active']);
605 $sogo_visible = intval($_data['sogo_visible']);
606 $goto_null = intval($_data['goto_null']);
607 $goto_spam = intval($_data['goto_spam']);
608 $goto_ham = intval($_data['goto_ham']);
609 $private_comment = $_data['private_comment'];
610 $public_comment = $_data['public_comment'];
611 if (strlen($private_comment) > 160 | strlen($public_comment) > 160){
612 $_SESSION['return'][] = array(
613 'type' => 'danger',
614 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
615 'msg' => 'comment_too_long'
616 );
617 return false;
618 }
619 if (empty($addresses[0])) {
620 $_SESSION['return'][] = array(
621 'type' => 'danger',
622 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
623 'msg' => 'alias_empty'
624 );
625 return false;
626 }
627 if (empty($gotos[0]) && ($goto_null + $goto_spam + $goto_ham == 0)) {
628 $_SESSION['return'][] = array(
629 'type' => 'danger',
630 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
631 'msg' => 'goto_empty'
632 );
633 return false;
634 }
635 if ($goto_null == "1") {
636 $goto = "null@localhost";
637 }
638 elseif ($goto_spam == "1") {
639 $goto = "spam@localhost";
640 }
641 elseif ($goto_ham == "1") {
642 $goto = "ham@localhost";
643 }
644 else {
645 foreach ($gotos as $i => &$goto) {
646 if (empty($goto)) {
647 continue;
648 }
649 $goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
650 $goto_local_part = strstr($goto, '@', true);
651 $goto = $goto_local_part.'@'.$goto_domain;
652 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
653 WHERE `kind` REGEXP 'location|thing|group'
654 AND `username`= :goto");
655 $stmt->execute(array(':goto' => $goto));
656 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
657 if ($num_results != 0) {
658 $_SESSION['return'][] = array(
659 'type' => 'danger',
660 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
661 'msg' => array('goto_invalid', htmlspecialchars($goto))
662 );
663 unset($gotos[$i]);
664 continue;
665 }
666 if (!filter_var($goto, FILTER_VALIDATE_EMAIL) === true) {
667 $_SESSION['return'][] = array(
668 'type' => 'danger',
669 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
670 'msg' => array('goto_invalid', htmlspecialchars($goto))
671 );
672 unset($gotos[$i]);
673 continue;
674 }
675 }
676 $gotos = array_filter($gotos);
677 if (empty($gotos)) { return false; }
678 $goto = implode(",", $gotos);
679 }
680 foreach ($addresses as $address) {
681 if (empty($address)) {
682 continue;
683 }
684 if (in_array($address, $gotos)) {
685 continue;
686 }
687 $domain = idn_to_ascii(substr(strstr($address, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
688 $local_part = strstr($address, '@', true);
689 $address = $local_part.'@'.$domain;
690 $domaindata = mailbox('get', 'domain_details', $domain);
691 if (is_array($domaindata) && $domaindata['aliases_left'] == "0") {
692 $_SESSION['return'][] = array(
693 'type' => 'danger',
694 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
695 'msg' => 'max_alias_exceeded'
696 );
697 return false;
698 }
699 $stmt = $pdo->prepare("SELECT `address` FROM `alias`
700 WHERE `address`= :address OR `address` IN (
701 SELECT `username` FROM `mailbox`, `alias_domain`
702 WHERE (
703 `alias_domain`.`alias_domain` = :address_d
704 AND `mailbox`.`username` = CONCAT(:address_l, '@', alias_domain.target_domain)))");
705 $stmt->execute(array(
706 ':address' => $address,
707 ':address_l' => $local_part,
708 ':address_d' => $domain
709 ));
710 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
711 if ($num_results != 0) {
712 $_SESSION['return'][] = array(
713 'type' => 'danger',
714 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
715 'msg' => array('is_alias_or_mailbox', htmlspecialchars($address))
716 );
717 continue;
718 }
719 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
720 WHERE `domain`= :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)");
721 $stmt->execute(array(':domain1' => $domain, ':domain2' => $domain));
722 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
723 if ($num_results == 0) {
724 $_SESSION['return'][] = array(
725 'type' => 'danger',
726 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
727 'msg' => array('domain_not_found', htmlspecialchars($domain))
728 );
729 continue;
730 }
731 $stmt = $pdo->prepare("SELECT `address` FROM `spamalias`
732 WHERE `address`= :address");
733 $stmt->execute(array(':address' => $address));
734 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
735 if ($num_results != 0) {
736 $_SESSION['return'][] = array(
737 'type' => 'danger',
738 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
739 'msg' => array('is_spam_alias', htmlspecialchars($address))
740 );
741 continue;
742 }
743 if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) {
744 $_SESSION['return'][] = array(
745 'type' => 'danger',
746 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
747 'msg' => array('alias_invalid', $address)
748 );
749 continue;
750 }
751 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
752 $_SESSION['return'][] = array(
753 'type' => 'danger',
754 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
755 'msg' => 'access_denied'
756 );
757 continue;
758 }
759 $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `active`)
760 VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :active)");
761 if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) {
762 $stmt->execute(array(
763 ':address' => '@'.$domain,
764 ':public_comment' => $public_comment,
765 ':private_comment' => $private_comment,
766 ':address' => '@'.$domain,
767 ':goto' => $goto,
768 ':domain' => $domain,
769 ':sogo_visible' => $sogo_visible,
770 ':active' => $active
771 ));
772 }
773 else {
774 $stmt->execute(array(
775 ':address' => $address,
776 ':public_comment' => $public_comment,
777 ':private_comment' => $private_comment,
778 ':goto' => $goto,
779 ':domain' => $domain,
780 ':sogo_visible' => $sogo_visible,
781 ':active' => $active
782 ));
783 }
784 $id = $pdo->lastInsertId();
785 $_SESSION['return'][] = array(
786 'type' => 'success',
787 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
788 'msg' => array('alias_added', $address, $id)
789 );
790 }
791 break;
792 case 'alias_domain':
793 $active = intval($_data['active']);
794 $alias_domains = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['alias_domain']));
795 $alias_domains = array_filter($alias_domains);
796 $target_domain = idn_to_ascii(strtolower(trim($_data['target_domain'])), 0, INTL_IDNA_VARIANT_UTS46);
797 if (!isset($_SESSION['acl']['alias_domains']) || $_SESSION['acl']['alias_domains'] != "1" ) {
798 $_SESSION['return'][] = array(
799 'type' => 'danger',
800 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
801 'msg' => 'access_denied'
802 );
803 return false;
804 }
805 if (!is_valid_domain_name($target_domain)) {
806 $_SESSION['return'][] = array(
807 'type' => 'danger',
808 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
809 'msg' => 'target_domain_invalid'
810 );
811 return false;
812 }
813 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $target_domain)) {
814 $_SESSION['return'][] = array(
815 'type' => 'danger',
816 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
817 'msg' => 'access_denied'
818 );
819 return false;
820 }
821 foreach ($alias_domains as $i => $alias_domain) {
822 $alias_domain = idn_to_ascii(strtolower(trim($alias_domain)), 0, INTL_IDNA_VARIANT_UTS46);
823 if (!is_valid_domain_name($alias_domain)) {
824 $_SESSION['return'][] = array(
825 'type' => 'danger',
826 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
827 'msg' => array('alias_domain_invalid', htmlspecialchars(alias_domain))
828 );
829 continue;
830 }
831 if ($alias_domain == $target_domain) {
832 $_SESSION['return'][] = array(
833 'type' => 'danger',
834 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
835 'msg' => array('aliasd_targetd_identical', htmlspecialchars($target_domain))
836 );
837 continue;
838 }
839 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
840 WHERE `domain`= :target_domain");
841 $stmt->execute(array(':target_domain' => $target_domain));
842 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
843 if ($num_results == 0) {
844 $_SESSION['return'][] = array(
845 'type' => 'danger',
846 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
847 'msg' => array('targetd_not_found', htmlspecialchars($target_domain))
848 );
849 continue;
850 }
851 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
852 WHERE `domain`= :target_domain AND `backupmx` = '1'");
853 $stmt->execute(array(':target_domain' => $target_domain));
854 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
855 if ($num_results == 1) {
856 $_SESSION['return'][] = array(
857 'type' => 'danger',
858 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
859 'msg' => array('targetd_relay_domain', htmlspecialchars($target_domain))
860 );
861 continue;
862 }
863 $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain`= :alias_domain
864 UNION
865 SELECT `domain` FROM `domain` WHERE `domain`= :alias_domain_in_domain");
866 $stmt->execute(array(':alias_domain' => $alias_domain, ':alias_domain_in_domain' => $alias_domain));
867 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
868 if ($num_results != 0) {
869 $_SESSION['return'][] = array(
870 'type' => 'danger',
871 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
872 'msg' => array('alias_domain_invalid', $alias_domain)
873 );
874 continue;
875 }
876 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `send_as` LIKE :domain");
877 $stmt->execute(array(
878 ':domain' => '%@' . $domain
879 ));
880 $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`)
881 VALUES (:alias_domain, :target_domain, :active)");
882 $stmt->execute(array(
883 ':alias_domain' => $alias_domain,
884 ':target_domain' => $target_domain,
885 ':active' => $active
886 ));
887 try {
888 $redis->hSet('DOMAIN_MAP', $alias_domain, 1);
889 }
890 catch (RedisException $e) {
891 $_SESSION['return'][] = array(
892 'type' => 'danger',
893 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
894 'msg' => array('redis_error', $e)
895 );
896 return false;
897 }
898 if (!empty(intval($_data['rl_value']))) {
899 ratelimit('edit', 'domain', array('rl_value' => $_data['rl_value'], 'rl_frame' => $_data['rl_frame'], 'object' => $alias_domain));
900 }
901 $_SESSION['return'][] = array(
902 'type' => 'success',
903 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
904 'msg' => array('aliasd_added', htmlspecialchars($alias_domain))
905 );
906 }
907 break;
908 case 'mailbox':
909 $local_part = strtolower(trim($_data['local_part']));
910 $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
911 $username = $local_part . '@' . $domain;
912 if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
913 $_SESSION['return'][] = array(
914 'type' => 'danger',
915 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
916 'msg' => 'mailbox_invalid'
917 );
918 return false;
919 }
920 if (empty($_data['local_part'])) {
921 $_SESSION['return'][] = array(
922 'type' => 'danger',
923 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
924 'msg' => 'mailbox_invalid'
925 );
926 return false;
927 }
928 $password = $_data['password'];
929 $password2 = $_data['password2'];
930 $name = ltrim(rtrim($_data['name'], '>'), '<');
931 $quota_m = intval($_data['quota']);
932 if ((!isset($_SESSION['acl']['unlimited_quota']) || $_SESSION['acl']['unlimited_quota'] != "1") && $quota_m === 0) {
933 $_SESSION['return'][] = array(
934 'type' => 'danger',
935 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
936 'msg' => 'unlimited_quota_acl'
937 );
938 return false;
939 }
940 if (empty($name)) {
941 $name = $local_part;
942 }
943 $active = intval($_data['active']);
944 $force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
945 $tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
946 $tls_enforce_out = (isset($_data['tls_enforce_out'])) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
947 $sogo_access = (isset($_data['sogo_access'])) ? intval($_data['sogo_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_access']);
948 $imap_access = (isset($_data['imap_access'])) ? intval($_data['imap_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
949 $pop3_access = (isset($_data['pop3_access'])) ? intval($_data['pop3_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
950 $smtp_access = (isset($_data['smtp_access'])) ? intval($_data['smtp_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
951 $quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
952 $quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
953 $quota_b = ($quota_m * 1048576);
954 $mailbox_attrs = json_encode(
955 array(
956 'force_pw_update' => strval($force_pw_update),
957 'tls_enforce_in' => strval($tls_enforce_in),
958 'tls_enforce_out' => strval($tls_enforce_out),
959 'sogo_access' => strval($sogo_access),
960 'imap_access' => strval($imap_access),
961 'pop3_access' => strval($pop3_access),
962 'smtp_access' => strval($smtp_access),
963 'mailbox_format' => strval($MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format']),
964 'quarantine_notification' => strval($quarantine_notification),
965 'quarantine_category' => strval($quarantine_category)
966 )
967 );
968 if (!is_valid_domain_name($domain)) {
969 $_SESSION['return'][] = array(
970 'type' => 'danger',
971 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
972 'msg' => 'domain_invalid'
973 );
974 return false;
975 }
976 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
977 $_SESSION['return'][] = array(
978 'type' => 'danger',
979 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
980 'msg' => 'access_denied'
981 );
982 return false;
983 }
984 $stmt = $pdo->prepare("SELECT `mailboxes`, `maxquota`, `quota` FROM `domain`
985 WHERE `domain` = :domain");
986 $stmt->execute(array(':domain' => $domain));
987 $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
988 $stmt = $pdo->prepare("SELECT
989 COUNT(*) as count,
990 COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota`
991 FROM `mailbox`
992 WHERE `kind` NOT REGEXP 'location|thing|group'
993 AND `domain` = :domain");
994 $stmt->execute(array(':domain' => $domain));
995 $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
996 $stmt = $pdo->prepare("SELECT `local_part` FROM `mailbox` WHERE `local_part` = :local_part and `domain`= :domain");
997 $stmt->execute(array(':local_part' => $local_part, ':domain' => $domain));
998 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
999 if ($num_results != 0) {
1000 $_SESSION['return'][] = array(
1001 'type' => 'danger',
1002 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1003 'msg' => array('object_exists', htmlspecialchars($username))
1004 );
1005 return false;
1006 }
1007 $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :username");
1008 $stmt->execute(array(':username' => $username));
1009 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1010 if ($num_results != 0) {
1011 $_SESSION['return'][] = array(
1012 'type' => 'danger',
1013 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1014 'msg' => array('is_alias', htmlspecialchars($username))
1015 );
1016 return false;
1017 }
1018 $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :username");
1019 $stmt->execute(array(':username' => $username));
1020 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1021 if ($num_results != 0) {
1022 $_SESSION['return'][] = array(
1023 'type' => 'danger',
1024 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1025 'msg' => array('is_spam_alias', htmlspecialchars($username))
1026 );
1027 return false;
1028 }
1029 $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain");
1030 $stmt->execute(array(':domain' => $domain));
1031 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1032 if ($num_results == 0) {
1033 $_SESSION['return'][] = array(
1034 'type' => 'danger',
1035 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1036 'msg' => array('domain_not_found', htmlspecialchars($domain))
1037 );
1038 return false;
1039 }
1040 if (!empty($password) && !empty($password2)) {
1041 if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
1042 $_SESSION['return'][] = array(
1043 'type' => 'danger',
1044 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1045 'msg' => 'password_complexity'
1046 );
1047 return false;
1048 }
1049 if ($password != $password2) {
1050 $_SESSION['return'][] = array(
1051 'type' => 'danger',
1052 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1053 'msg' => 'password_mismatch'
1054 );
1055 return false;
1056 }
1057 // support pre hashed passwords
1058 if (preg_match('/^({SSHA256}|{SSHA}|{SHA512-CRYPT}|{SSHA512}|{MD5-CRYPT}|{PLAIN-MD5})/i', $password)) {
1059 $password_hashed = $password;
1060 }
1061 else {
1062 $password_hashed = hash_password($password);
1063 }
1064 }
1065 else {
1066 $_SESSION['return'][] = array(
1067 'type' => 'danger',
1068 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1069 'msg' => 'password_empty'
1070 );
1071 return false;
1072 }
1073 if ($MailboxData['count'] >= $DomainData['mailboxes']) {
1074 $_SESSION['return'][] = array(
1075 'type' => 'danger',
1076 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1077 'msg' => array('max_mailbox_exceeded', $MailboxData['count'], $DomainData['mailboxes'])
1078 );
1079 return false;
1080 }
1081 if ($quota_m > $DomainData['maxquota']) {
1082 $_SESSION['return'][] = array(
1083 'type' => 'danger',
1084 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1085 'msg' => array('mailbox_quota_exceeded', $DomainData['maxquota'])
1086 );
1087 return false;
1088 }
1089 if (($MailboxData['quota'] + $quota_m) > $DomainData['quota']) {
1090 $quota_left_m = ($DomainData['quota'] - $MailboxData['quota']);
1091 $_SESSION['return'][] = array(
1092 'type' => 'danger',
1093 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1094 'msg' => array('mailbox_quota_left_exceeded', $quota_left_m)
1095 );
1096 return false;
1097 }
1098 $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `quota`, `local_part`, `domain`, `attributes`, `active`)
1099 VALUES (:username, :password_hashed, :name, :quota_b, :local_part, :domain, :mailbox_attrs, :active)");
1100 $stmt->execute(array(
1101 ':username' => $username,
1102 ':password_hashed' => $password_hashed,
1103 ':name' => $name,
1104 ':quota_b' => $quota_b,
1105 ':local_part' => $local_part,
1106 ':domain' => $domain,
1107 ':mailbox_attrs' => $mailbox_attrs,
1108 ':active' => $active
1109 ));
1110 $stmt = $pdo->prepare("INSERT INTO `quota2` (`username`, `bytes`, `messages`)
1111 VALUES (:username, '0', '0') ON DUPLICATE KEY UPDATE `bytes` = '0', `messages` = '0';");
1112 $stmt->execute(array(':username' => $username));
1113 $stmt = $pdo->prepare("INSERT INTO `quota2replica` (`username`, `bytes`, `messages`)
1114 VALUES (:username, '0', '0') ON DUPLICATE KEY UPDATE `bytes` = '0', `messages` = '0';");
1115 $stmt->execute(array(':username' => $username));
1116 $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`)
1117 VALUES (:username1, :username2, :domain, :active)");
1118 $stmt->execute(array(
1119 ':username1' => $username,
1120 ':username2' => $username,
1121 ':domain' => $domain,
1122 ':active' => $active
1123 ));
1124 $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)");
1125 $stmt->execute(array(
1126 ':username' => $username
1127 ));
1128 $_SESSION['return'][] = array(
1129 'type' => 'success',
1130 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1131 'msg' => array('mailbox_added', htmlspecialchars($username))
1132 );
1133 break;
1134 case 'resource':
1135 $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
1136 $description = $_data['description'];
1137 $local_part = preg_replace('/[^\da-z]/i', '', preg_quote($description, '/'));
1138 $name = $local_part . '@' . $domain;
1139 $kind = $_data['kind'];
1140 $multiple_bookings = intval($_data['multiple_bookings']);
1141 $active = intval($_data['active']);
1142 if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
1143 $_SESSION['return'][] = array(
1144 'type' => 'danger',
1145 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1146 'msg' => 'resource_invalid'
1147 );
1148 return false;
1149 }
1150 if (empty($description)) {
1151 $_SESSION['return'][] = array(
1152 'type' => 'danger',
1153 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1154 'msg' => 'description_invalid'
1155 );
1156 return false;
1157 }
1158 if (!isset($multiple_bookings) || $multiple_bookings < -1) {
1159 $multiple_bookings = -1;
1160 }
1161 if ($kind != 'location' && $kind != 'group' && $kind != 'thing') {
1162 $_SESSION['return'][] = array(
1163 'type' => 'danger',
1164 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1165 'msg' => 'resource_invalid'
1166 );
1167 return false;
1168 }
1169 if (!is_valid_domain_name($domain)) {
1170 $_SESSION['return'][] = array(
1171 'type' => 'danger',
1172 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1173 'msg' => 'domain_invalid'
1174 );
1175 return false;
1176 }
1177 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
1178 $_SESSION['return'][] = array(
1179 'type' => 'danger',
1180 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1181 'msg' => 'access_denied'
1182 );
1183 return false;
1184 }
1185 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :name");
1186 $stmt->execute(array(':name' => $name));
1187 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1188 if ($num_results != 0) {
1189 $_SESSION['return'][] = array(
1190 'type' => 'danger',
1191 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1192 'msg' => array('object_exists', htmlspecialchars($name))
1193 );
1194 return false;
1195 }
1196 $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :name");
1197 $stmt->execute(array(':name' => $name));
1198 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1199 if ($num_results != 0) {
1200 $_SESSION['return'][] = array(
1201 'type' => 'danger',
1202 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1203 'msg' => array('is_alias', htmlspecialchars($name))
1204 );
1205 return false;
1206 }
1207 $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :name");
1208 $stmt->execute(array(':name' => $name));
1209 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1210 if ($num_results != 0) {
1211 $_SESSION['return'][] = array(
1212 'type' => 'danger',
1213 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1214 'msg' => array('is_spam_alias', htmlspecialchars($name))
1215 );
1216 return false;
1217 }
1218 $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain");
1219 $stmt->execute(array(':domain' => $domain));
1220 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1221 if ($num_results == 0) {
1222 $_SESSION['return'][] = array(
1223 'type' => 'danger',
1224 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1225 'msg' => array('domain_not_found', htmlspecialchars($domain))
1226 );
1227 return false;
1228 }
1229 $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `quota`, `local_part`, `domain`, `active`, `multiple_bookings`, `kind`)
1230 VALUES (:name, 'RESOURCE', :description, 0, :local_part, :domain, :active, :multiple_bookings, :kind)");
1231 $stmt->execute(array(
1232 ':name' => $name,
1233 ':description' => $description,
1234 ':local_part' => $local_part,
1235 ':domain' => $domain,
1236 ':active' => $active,
1237 ':kind' => $kind,
1238 ':multiple_bookings' => $multiple_bookings
1239 ));
1240 $_SESSION['return'][] = array(
1241 'type' => 'success',
1242 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1243 'msg' => array('resource_added', htmlspecialchars($name))
1244 );
1245 break;
1246 }
1247 break;
1248 case 'edit':
1249 switch ($_type) {
1250 case 'alias_domain':
1251 $alias_domains = (array)$_data['alias_domain'];
1252 foreach ($alias_domains as $alias_domain) {
1253 $alias_domain = idn_to_ascii(strtolower(trim($alias_domain)), 0, INTL_IDNA_VARIANT_UTS46);
1254 $is_now = mailbox('get', 'alias_domain_details', $alias_domain);
1255 if (!empty($is_now)) {
1256 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
1257 $target_domain = (!empty($_data['target_domain'])) ? idn_to_ascii(strtolower(trim($_data['target_domain'])), 0, INTL_IDNA_VARIANT_UTS46) : $is_now['target_domain'];
1258 }
1259 else {
1260 $_SESSION['return'][] = array(
1261 'type' => 'danger',
1262 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1263 'msg' => array('alias_domain_invalid', htmlspecialchars($alias_domain))
1264 );
1265 continue;
1266 }
1267 if (!is_valid_domain_name($target_domain)) {
1268 $_SESSION['return'][] = array(
1269 'type' => 'danger',
1270 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1271 'msg' => array('target_domain_invalid', htmlspecialchars($target_domain))
1272 );
1273 continue;
1274 }
1275 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $target_domain)) {
1276 $_SESSION['return'][] = array(
1277 'type' => 'danger',
1278 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1279 'msg' => 'access_denied'
1280 );
1281 continue;
1282 }
1283 if (empty(mailbox('get', 'domain_details', $target_domain)) || !empty(mailbox('get', 'alias_domain_details', $target_domain))) {
1284 $_SESSION['return'][] = array(
1285 'type' => 'danger',
1286 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1287 'msg' => array('target_domain_invalid', htmlspecialchars($target_domain))
1288 );
1289 continue;
1290 }
1291 $stmt = $pdo->prepare("UPDATE `alias_domain` SET
1292 `target_domain` = :target_domain,
1293 `active` = :active
1294 WHERE `alias_domain` = :alias_domain");
1295 $stmt->execute(array(
1296 ':alias_domain' => $alias_domain,
1297 ':target_domain' => $target_domain,
1298 ':active' => $active
1299 ));
1300 $_SESSION['return'][] = array(
1301 'type' => 'success',
1302 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1303 'msg' => array('aliasd_modified', htmlspecialchars($alias_domain))
1304 );
1305 }
1306 break;
1307 case 'tls_policy':
1308 if (!is_array($_data['username'])) {
1309 $usernames = array();
1310 $usernames[] = $_data['username'];
1311 }
1312 else {
1313 $usernames = $_data['username'];
1314 }
1315 if (!isset($_SESSION['acl']['tls_policy']) || $_SESSION['acl']['tls_policy'] != "1" ) {
1316 $_SESSION['return'][] = array(
1317 'type' => 'danger',
1318 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1319 'msg' => 'access_denied'
1320 );
1321 return false;
1322 }
1323 foreach ($usernames as $username) {
1324 if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
1325 $_SESSION['return'][] = array(
1326 'type' => 'danger',
1327 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1328 'msg' => 'access_denied'
1329 );
1330 continue;
1331 }
1332 $is_now = mailbox('get', 'tls_policy', $username);
1333 if (!empty($is_now)) {
1334 $tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
1335 $tls_enforce_out = (isset($_data['tls_enforce_out'])) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out'];
1336 }
1337 else {
1338 $_SESSION['return'][] = array(
1339 'type' => 'danger',
1340 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1341 'msg' => 'access_denied'
1342 );
1343 continue;
1344 }
1345 $stmt = $pdo->prepare("UPDATE `mailbox`
1346 SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_out),
1347 `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_in)
1348 WHERE `username` = :username");
1349 $stmt->execute(array(
1350 ':tls_out' => intval($tls_enforce_out),
1351 ':tls_in' => intval($tls_enforce_in),
1352 ':username' => $username
1353 ));
1354 $_SESSION['return'][] = array(
1355 'type' => 'success',
1356 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1357 'msg' => array('mailbox_modified', $username)
1358 );
1359 }
1360 break;
1361 case 'quarantine_notification':
1362 if (!is_array($_data['username'])) {
1363 $usernames = array();
1364 $usernames[] = $_data['username'];
1365 }
1366 else {
1367 $usernames = $_data['username'];
1368 }
1369 if (!isset($_SESSION['acl']['quarantine_notification']) || $_SESSION['acl']['quarantine_notification'] != "1" ) {
1370 $_SESSION['return'][] = array(
1371 'type' => 'danger',
1372 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1373 'msg' => 'access_denied'
1374 );
1375 return false;
1376 }
1377 foreach ($usernames as $username) {
1378 if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
1379 $_SESSION['return'][] = array(
1380 'type' => 'danger',
1381 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1382 'msg' => 'access_denied'
1383 );
1384 continue;
1385 }
1386 $is_now = mailbox('get', 'quarantine_notification', $username);
1387 if (!empty($is_now)) {
1388 $quarantine_notification = (isset($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
1389 }
1390 else {
1391 $_SESSION['return'][] = array(
1392 'type' => 'danger',
1393 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1394 'msg' => 'access_denied'
1395 );
1396 continue;
1397 }
1398 if (!in_array($quarantine_notification, array('never', 'hourly', 'daily', 'weekly'))) {
1399 $_SESSION['return'][] = array(
1400 'type' => 'danger',
1401 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1402 'msg' => 'access_denied'
1403 );
1404 continue;
1405 }
1406 $stmt = $pdo->prepare("UPDATE `mailbox`
1407 SET `attributes` = JSON_SET(`attributes`, '$.quarantine_notification', :quarantine_notification)
1408 WHERE `username` = :username");
1409 $stmt->execute(array(
1410 ':quarantine_notification' => $quarantine_notification,
1411 ':username' => $username
1412 ));
1413 $_SESSION['return'][] = array(
1414 'type' => 'success',
1415 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1416 'msg' => array('mailbox_modified', $username)
1417 );
1418 }
1419 break;
1420 case 'quarantine_category':
1421 if (!is_array($_data['username'])) {
1422 $usernames = array();
1423 $usernames[] = $_data['username'];
1424 }
1425 else {
1426 $usernames = $_data['username'];
1427 }
1428 if (!isset($_SESSION['acl']['quarantine_category']) || $_SESSION['acl']['quarantine_category'] != "1" ) {
1429 $_SESSION['return'][] = array(
1430 'type' => 'danger',
1431 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1432 'msg' => 'access_denied'
1433 );
1434 return false;
1435 }
1436 foreach ($usernames as $username) {
1437 if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
1438 $_SESSION['return'][] = array(
1439 'type' => 'danger',
1440 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1441 'msg' => 'access_denied'
1442 );
1443 continue;
1444 }
1445 $is_now = mailbox('get', 'quarantine_category', $username);
1446 if (!empty($is_now)) {
1447 $quarantine_category = (isset($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
1448 }
1449 else {
1450 $_SESSION['return'][] = array(
1451 'type' => 'danger',
1452 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1453 'msg' => 'access_denied'
1454 );
1455 continue;
1456 }
1457 if (!in_array($quarantine_category, array('add_header', 'reject', 'all'))) {
1458 $_SESSION['return'][] = array(
1459 'type' => 'danger',
1460 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1461 'msg' => 'access_denied'
1462 );
1463 continue;
1464 }
1465 $stmt = $pdo->prepare("UPDATE `mailbox`
1466 SET `attributes` = JSON_SET(`attributes`, '$.quarantine_category', :quarantine_category)
1467 WHERE `username` = :username");
1468 $stmt->execute(array(
1469 ':quarantine_category' => $quarantine_category,
1470 ':username' => $username
1471 ));
1472 $_SESSION['return'][] = array(
1473 'type' => 'success',
1474 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1475 'msg' => array('mailbox_modified', $username)
1476 );
1477 }
1478 break;
1479 case 'spam_score':
1480 if (!is_array($_data['username'])) {
1481 $usernames = array();
1482 $usernames[] = $_data['username'];
1483 }
1484 else {
1485 $usernames = $_data['username'];
1486 }
1487 if (!isset($_SESSION['acl']['spam_score']) || $_SESSION['acl']['spam_score'] != "1" ) {
1488 $_SESSION['return'][] = array(
1489 'type' => 'danger',
1490 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1491 'msg' => 'access_denied'
1492 );
1493 return false;
1494 }
1495 foreach ($usernames as $username) {
1496 if ($_data['spam_score'] == "default") {
1497 $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
1498 AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
1499 $stmt->execute(array(
1500 ':username' => $username
1501 ));
1502 $_SESSION['return'][] = array(
1503 'type' => 'success',
1504 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1505 'msg' => array('mailbox_modified', $username)
1506 );
1507 continue;
1508 }
1509 $lowspamlevel = explode(',', $_data['spam_score'])[0];
1510 $highspamlevel = explode(',', $_data['spam_score'])[1];
1511 if (!is_numeric($lowspamlevel) || !is_numeric($highspamlevel)) {
1512 $_SESSION['return'][] = array(
1513 'type' => 'danger',
1514 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1515 'msg' => 'Invalid spam score, format must be "1,2" where first is low and second is high spam value.'
1516 );
1517 continue;
1518 }
1519 $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
1520 AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
1521 $stmt->execute(array(
1522 ':username' => $username
1523 ));
1524 $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`)
1525 VALUES (:username, 'highspamlevel', :highspamlevel)");
1526 $stmt->execute(array(
1527 ':username' => $username,
1528 ':highspamlevel' => $highspamlevel
1529 ));
1530 $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`)
1531 VALUES (:username, 'lowspamlevel', :lowspamlevel)");
1532 $stmt->execute(array(
1533 ':username' => $username,
1534 ':lowspamlevel' => $lowspamlevel
1535 ));
1536 $_SESSION['return'][] = array(
1537 'type' => 'success',
1538 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1539 'msg' => array('mailbox_modified', $username)
1540 );
1541 }
1542 break;
1543 case 'time_limited_alias':
1544 if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) {
1545 $_SESSION['return'][] = array(
1546 'type' => 'danger',
1547 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1548 'msg' => 'access_denied'
1549 );
1550 return false;
1551 }
1552 if (!is_array($_data['address'])) {
1553 $addresses = array();
1554 $addresses[] = $_data['address'];
1555 }
1556 else {
1557 $addresses = $_data['address'];
1558 }
1559 foreach ($addresses as $address) {
1560 $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address");
1561 $stmt->execute(array(':address' => $address));
1562 $goto = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
1563 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $goto)) {
1564 $_SESSION['return'][] = array(
1565 'type' => 'danger',
1566 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1567 'msg' => 'access_denied'
1568 );
1569 continue;
1570 }
1571 if (empty($_data['validity'])) {
1572 continue;
1573 }
1574 $validity = round((int)time() + ($_data['validity'] * 3600));
1575 $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = :validity WHERE
1576 `address` = :address");
1577 $stmt->execute(array(
1578 ':address' => $address,
1579 ':validity' => $validity
1580 ));
1581 $_SESSION['return'][] = array(
1582 'type' => 'success',
1583 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1584 'msg' => array('mailbox_modified', htmlspecialchars(implode(', ', $usernames)))
1585 );
1586 }
1587 break;
1588 case 'delimiter_action':
1589 if (!is_array($_data['username'])) {
1590 $usernames = array();
1591 $usernames[] = $_data['username'];
1592 }
1593 else {
1594 $usernames = $_data['username'];
1595 }
1596 if (!isset($_SESSION['acl']['delimiter_action']) || $_SESSION['acl']['delimiter_action'] != "1" ) {
1597 $_SESSION['return'][] = array(
1598 'type' => 'danger',
1599 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1600 'msg' => 'access_denied'
1601 );
1602 return false;
1603 }
1604 foreach ($usernames as $username) {
1605 if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
1606 $_SESSION['return'][] = array(
1607 'type' => 'danger',
1608 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1609 'msg' => 'access_denied'
1610 );
1611 continue;
1612 }
1613 if (isset($_data['tagged_mail_handler']) && $_data['tagged_mail_handler'] == "subject") {
1614 try {
1615 $redis->hSet('RCPT_WANTS_SUBJECT_TAG', $username, 1);
1616 $redis->hDel('RCPT_WANTS_SUBFOLDER_TAG', $username);
1617 }
1618 catch (RedisException $e) {
1619 $_SESSION['return'][] = array(
1620 'type' => 'danger',
1621 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1622 'msg' => array('redis_error', $e)
1623 );
1624 continue;
1625 }
1626 }
1627 else if (isset($_data['tagged_mail_handler']) && $_data['tagged_mail_handler'] == "subfolder") {
1628 try {
1629 $redis->hSet('RCPT_WANTS_SUBFOLDER_TAG', $username, 1);
1630 $redis->hDel('RCPT_WANTS_SUBJECT_TAG', $username);
1631 }
1632 catch (RedisException $e) {
1633 $_SESSION['return'][] = array(
1634 'type' => 'danger',
1635 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1636 'msg' => array('redis_error', $e)
1637 );
1638 continue;
1639 }
1640 }
1641 else {
1642 try {
1643 $redis->hDel('RCPT_WANTS_SUBJECT_TAG', $username);
1644 $redis->hDel('RCPT_WANTS_SUBFOLDER_TAG', $username);
1645 }
1646 catch (RedisException $e) {
1647 $_SESSION['return'][] = array(
1648 'type' => 'danger',
1649 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1650 'msg' => array('redis_error', $e)
1651 );
1652 continue;
1653 }
1654 }
1655 $_SESSION['return'][] = array(
1656 'type' => 'success',
1657 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1658 'msg' => array('mailbox_modified', $username)
1659 );
1660 }
1661 break;
1662 case 'syncjob':
1663 if (!is_array($_data['id'])) {
1664 $ids = array();
1665 $ids[] = $_data['id'];
1666 }
1667 else {
1668 $ids = $_data['id'];
1669 }
1670 if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) {
1671 $_SESSION['return'][] = array(
1672 'type' => 'danger',
1673 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1674 'msg' => 'access_denied'
1675 );
1676 return false;
1677 }
1678 foreach ($ids as $id) {
1679 $is_now = mailbox('get', 'syncjob_details', $id, array('with_password'));
1680 if (!empty($is_now)) {
1681 $username = $is_now['user2'];
1682 $user1 = (!empty($_data['user1'])) ? $_data['user1'] : $is_now['user1'];
1683 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
1684 $last_run = (isset($_data['last_run'])) ? NULL : $is_now['last_run'];
1685 $delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates'];
1686 $subscribeall = (isset($_data['subscribeall'])) ? intval($_data['subscribeall']) : $is_now['subscribeall'];
1687 $delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1'];
1688 $delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2'];
1689 $automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap'];
1690 $skipcrossduplicates = (isset($_data['skipcrossduplicates'])) ? intval($_data['skipcrossduplicates']) : $is_now['skipcrossduplicates'];
1691 $port1 = (!empty($_data['port1'])) ? $_data['port1'] : $is_now['port1'];
1692 $password1 = (!empty($_data['password1'])) ? $_data['password1'] : $is_now['password1'];
1693 $host1 = (!empty($_data['host1'])) ? $_data['host1'] : $is_now['host1'];
1694 $subfolder2 = (isset($_data['subfolder2'])) ? $_data['subfolder2'] : $is_now['subfolder2'];
1695 $enc1 = (!empty($_data['enc1'])) ? $_data['enc1'] : $is_now['enc1'];
1696 $mins_interval = (!empty($_data['mins_interval'])) ? $_data['mins_interval'] : $is_now['mins_interval'];
1697 $exclude = (isset($_data['exclude'])) ? $_data['exclude'] : $is_now['exclude'];
1698 $custom_params = (isset($_data['custom_params'])) ? $_data['custom_params'] : $is_now['custom_params'];
1699 $maxage = (isset($_data['maxage']) && $_data['maxage'] != "") ? intval($_data['maxage']) : $is_now['maxage'];
1700 $maxbytespersecond = (isset($_data['maxbytespersecond']) && $_data['maxbytespersecond'] != "") ? intval($_data['maxbytespersecond']) : $is_now['maxbytespersecond'];
1701 $timeout1 = (isset($_data['timeout1']) && $_data['timeout1'] != "") ? intval($_data['timeout1']) : $is_now['timeout1'];
1702 $timeout2 = (isset($_data['timeout2']) && $_data['timeout2'] != "") ? intval($_data['timeout2']) : $is_now['timeout2'];
1703 }
1704 else {
1705 $_SESSION['return'][] = array(
1706 'type' => 'danger',
1707 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1708 'msg' => 'access_denied'
1709 );
1710 continue;
1711 }
1712 if (strpos($custom_params, 'pipemess')) {
1713 $custom_params = '';
1714 }
1715 if (empty($subfolder2)) {
1716 $subfolder2 = "";
1717 }
1718 if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
1719 $maxage = "0";
1720 }
1721 if (!isset($timeout1) || !filter_var($timeout1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
1722 $timeout1 = "600";
1723 }
1724 if (!isset($timeout2) || !filter_var($timeout2, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32000)))) {
1725 $timeout2 = "600";
1726 }
1727 if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
1728 $maxbytespersecond = "0";
1729 }
1730 if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
1731 $_SESSION['return'][] = array(
1732 'type' => 'danger',
1733 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1734 'msg' => 'access_denied'
1735 );
1736 continue;
1737 }
1738 if (!filter_var($mins_interval, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 43800)))) {
1739 $_SESSION['return'][] = array(
1740 'type' => 'danger',
1741 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1742 'msg' => 'access_denied'
1743 );
1744 continue;
1745 }
1746 if (!is_valid_domain_name($host1)) {
1747 $_SESSION['return'][] = array(
1748 'type' => 'danger',
1749 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1750 'msg' => 'access_denied'
1751 );
1752 continue;
1753 }
1754 if ($enc1 != "TLS" && $enc1 != "SSL" && $enc1 != "PLAIN") {
1755 $_SESSION['return'][] = array(
1756 'type' => 'danger',
1757 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1758 'msg' => 'access_denied'
1759 );
1760 continue;
1761 }
1762 if (@preg_match("/" . $exclude . "/", null) === false) {
1763 $_SESSION['return'][] = array(
1764 'type' => 'danger',
1765 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1766 'msg' => 'access_denied'
1767 );
1768 continue;
1769 }
1770 $stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1,
1771 `delete2` = :delete2,
1772 `automap` = :automap,
1773 `skipcrossduplicates` = :skipcrossduplicates,
1774 `maxage` = :maxage,
1775 `maxbytespersecond` = :maxbytespersecond,
1776 `subfolder2` = :subfolder2,
1777 `exclude` = :exclude,
1778 `host1` = :host1,
1779 `last_run` = :last_run,
1780 `user1` = :user1,
1781 `password1` = :password1,
1782 `mins_interval` = :mins_interval,
1783 `port1` = :port1,
1784 `enc1` = :enc1,
1785 `delete2duplicates` = :delete2duplicates,
1786 `custom_params` = :custom_params,
1787 `timeout1` = :timeout1,
1788 `timeout2` = :timeout2,
1789 `subscribeall` = :subscribeall,
1790 `active` = :active
1791 WHERE `id` = :id");
1792 $stmt->execute(array(
1793 ':delete1' => $delete1,
1794 ':delete2' => $delete2,
1795 ':automap' => $automap,
1796 ':skipcrossduplicates' => $skipcrossduplicates,
1797 ':id' => $id,
1798 ':exclude' => $exclude,
1799 ':maxage' => $maxage,
1800 ':maxbytespersecond' => $maxbytespersecond,
1801 ':subfolder2' => $subfolder2,
1802 ':host1' => $host1,
1803 ':user1' => $user1,
1804 ':password1' => $password1,
1805 ':last_run' => $last_run,
1806 ':mins_interval' => $mins_interval,
1807 ':port1' => $port1,
1808 ':enc1' => $enc1,
1809 ':delete2duplicates' => $delete2duplicates,
1810 ':custom_params' => $custom_params,
1811 ':timeout1' => $timeout1,
1812 ':timeout2' => $timeout2,
1813 ':subscribeall' => $subscribeall,
1814 ':active' => $active,
1815 ));
1816 $_SESSION['return'][] = array(
1817 'type' => 'success',
1818 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1819 'msg' => array('mailbox_modified', $username)
1820 );
1821 }
1822 break;
1823 case 'filter':
1824 if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) {
1825 $_SESSION['return'][] = array(
1826 'type' => 'danger',
1827 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1828 'msg' => 'access_denied'
1829 );
1830 return false;
1831 }
1832 $sieve = new Sieve\SieveParser();
1833 if (!is_array($_data['id'])) {
1834 $ids = array();
1835 $ids[] = $_data['id'];
1836 }
1837 else {
1838 $ids = $_data['id'];
1839 }
1840 foreach ($ids as $id) {
1841 $is_now = mailbox('get', 'filter_details', $id);
1842 if (!empty($is_now)) {
1843 $username = $is_now['username'];
1844 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
1845 $script_desc = (!empty($_data['script_desc'])) ? $_data['script_desc'] : $is_now['script_desc'];
1846 $script_data = (!empty($_data['script_data'])) ? $_data['script_data'] : $is_now['script_data'];
1847 $filter_type = (!empty($_data['filter_type'])) ? $_data['filter_type'] : $is_now['filter_type'];
1848 }
1849 else {
1850 $_SESSION['return'][] = array(
1851 'type' => 'danger',
1852 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1853 'msg' => 'access_denied'
1854 );
1855 continue;
1856 }
1857 try {
1858 $sieve->parse($script_data);
1859 }
1860 catch (Exception $e) {
1861 $_SESSION['return'][] = array(
1862 'type' => 'danger',
1863 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1864 'msg' => array('sieve_error', $e->getMessage())
1865 );
1866 continue;
1867 }
1868 if ($filter_type != 'postfilter' && $filter_type != 'prefilter') {
1869 $_SESSION['return'][] = array(
1870 'type' => 'danger',
1871 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1872 'msg' => 'filter_type'
1873 );
1874 continue;
1875 }
1876 if ($active == '1') {
1877 $script_name = 'active';
1878 $stmt = $pdo->prepare("UPDATE `sieve_filters`
1879 SET `script_name` = 'inactive'
1880 WHERE `username` = :username
1881 AND `filter_type` = :filter_type");
1882 $stmt->execute(array(
1883 ':username' => $username,
1884 ':filter_type' => $filter_type
1885 ));
1886 }
1887 else {
1888 $script_name = 'inactive';
1889 }
1890 $stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_desc` = :script_desc, `script_data` = :script_data, `script_name` = :script_name, `filter_type` = :filter_type
1891 WHERE `id` = :id");
1892 $stmt->execute(array(
1893 ':script_desc' => $script_desc,
1894 ':script_data' => $script_data,
1895 ':script_name' => $script_name,
1896 ':filter_type' => $filter_type,
1897 ':id' => $id
1898 ));
1899 $_SESSION['return'][] = array(
1900 'type' => 'success',
1901 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1902 'msg' => array('mailbox_modified', $username)
1903 );
1904 }
1905 break;
1906 case 'alias':
1907 if (!is_array($_data['id'])) {
1908 $ids = array();
1909 $ids[] = $_data['id'];
1910 }
1911 else {
1912 $ids = $_data['id'];
1913 }
1914 foreach ($ids as $id) {
1915 $is_now = mailbox('get', 'alias_details', $id);
1916 if (!empty($is_now)) {
1917 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
1918 $sogo_visible = (isset($_data['sogo_visible'])) ? intval($_data['sogo_visible']) : $is_now['sogo_visible'];
1919 $goto_null = (isset($_data['goto_null'])) ? intval($_data['goto_null']) : 0;
1920 $goto_spam = (isset($_data['goto_spam'])) ? intval($_data['goto_spam']) : 0;
1921 $goto_ham = (isset($_data['goto_ham'])) ? intval($_data['goto_ham']) : 0;
1922 $public_comment = (isset($_data['public_comment'])) ? $_data['public_comment'] : $is_now['public_comment'];
1923 $private_comment = (isset($_data['private_comment'])) ? $_data['private_comment'] : $is_now['private_comment'];
1924 $goto = (!empty($_data['goto'])) ? $_data['goto'] : $is_now['goto'];
1925 $address = (!empty($_data['address'])) ? $_data['address'] : $is_now['address'];
1926 }
1927 else {
1928 $_SESSION['return'][] = array(
1929 'type' => 'danger',
1930 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1931 'msg' => array('alias_invalid', $address)
1932 );
1933 continue;
1934 }
1935 $domain = idn_to_ascii(substr(strstr($address, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
1936 if ($is_now['address'] != $address) {
1937 $local_part = strstr($address, '@', true);
1938 $address = $local_part.'@'.$domain;
1939 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
1940 $_SESSION['return'][] = array(
1941 'type' => 'danger',
1942 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1943 'msg' => 'access_denied'
1944 );
1945 continue;
1946 }
1947 if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) {
1948 $_SESSION['return'][] = array(
1949 'type' => 'danger',
1950 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1951 'msg' => array('alias_invalid', $address)
1952 );
1953 continue;
1954 }
1955 if (strtolower($is_now['address']) != strtolower($address)) {
1956 $stmt = $pdo->prepare("SELECT `address` FROM `alias`
1957 WHERE `address`= :address OR `address` IN (
1958 SELECT `username` FROM `mailbox`, `alias_domain`
1959 WHERE (
1960 `alias_domain`.`alias_domain` = :address_d
1961 AND `mailbox`.`username` = CONCAT(:address_l, '@', alias_domain.target_domain)))");
1962 $stmt->execute(array(
1963 ':address' => $address,
1964 ':address_l' => $local_part,
1965 ':address_d' => $domain
1966 ));
1967 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1968 if ($num_results != 0) {
1969 $_SESSION['return'][] = array(
1970 'type' => 'danger',
1971 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1972 'msg' => array('is_alias_or_mailbox', htmlspecialchars($address))
1973 );
1974 continue;
1975 }
1976 }
1977 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
1978 WHERE `domain`= :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)");
1979 $stmt->execute(array(':domain1' => $domain, ':domain2' => $domain));
1980 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1981 if ($num_results == 0) {
1982 $_SESSION['return'][] = array(
1983 'type' => 'danger',
1984 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1985 'msg' => array('domain_not_found', htmlspecialchars($domain))
1986 );
1987 continue;
1988 }
1989 $stmt = $pdo->prepare("SELECT `address` FROM `spamalias`
1990 WHERE `address`= :address");
1991 $stmt->execute(array(':address' => $address));
1992 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
1993 if ($num_results != 0) {
1994 $_SESSION['return'][] = array(
1995 'type' => 'danger',
1996 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
1997 'msg' => array('is_spam_alias', htmlspecialchars($address))
1998 );
1999 continue;
2000 }
2001 }
2002 if ($goto_null == "1") {
2003 $goto = "null@localhost";
2004 }
2005 elseif ($goto_spam == "1") {
2006 $goto = "spam@localhost";
2007 }
2008 elseif ($goto_ham == "1") {
2009 $goto = "ham@localhost";
2010 }
2011 else {
2012 $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $goto));
2013 foreach ($gotos as $i => &$goto) {
2014 if (empty($goto)) {
2015 continue;
2016 }
2017 if (!filter_var($goto, FILTER_VALIDATE_EMAIL)) {
2018 $_SESSION['return'][] = array(
2019 'type' => 'danger',
2020 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2021 'msg' => array('goto_invalid', $goto)
2022 );
2023 unset($gotos[$i]);
2024 continue;
2025 }
2026 if ($goto == $address) {
2027 $_SESSION['return'][] = array(
2028 'type' => 'danger',
2029 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2030 'msg' => 'alias_goto_identical'
2031 );
2032 unset($gotos[$i]);
2033 continue;
2034 }
2035 // Delete from sender_acl to prevent duplicates
2036 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE
2037 `logged_in_as` = :goto AND
2038 `send_as` = :address");
2039 $stmt->execute(array(
2040 ':goto' => $goto,
2041 ':address' => $address
2042 ));
2043 }
2044 $gotos = array_filter($gotos);
2045 $goto = implode(",", $gotos);
2046 }
2047 if (!empty($goto)) {
2048 $stmt = $pdo->prepare("UPDATE `alias` SET
2049 `address` = :address,
2050 `public_comment` = :public_comment,
2051 `private_comment` = :private_comment,
2052 `domain` = :domain,
2053 `goto` = :goto,
2054 `sogo_visible`= :sogo_visible,
2055 `active`= :active
2056 WHERE `id` = :id");
2057 $stmt->execute(array(
2058 ':address' => $address,
2059 ':public_comment' => $public_comment,
2060 ':private_comment' => $private_comment,
2061 ':domain' => $domain,
2062 ':goto' => $goto,
2063 ':sogo_visible' => $sogo_visible,
2064 ':active' => $active,
2065 ':id' => $is_now['id']
2066 ));
2067 }
2068 $_SESSION['return'][] = array(
2069 'type' => 'success',
2070 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2071 'msg' => array('alias_modified', htmlspecialchars($address))
2072 );
2073 }
2074 break;
2075 case 'domain':
2076 if (!is_array($_data['domain'])) {
2077 $domains = array();
2078 $domains[] = $_data['domain'];
2079 }
2080 else {
2081 $domains = $_data['domain'];
2082 }
2083 foreach ($domains as $domain) {
2084 $domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
2085 if (!is_valid_domain_name($domain)) {
2086 $_SESSION['return'][] = array(
2087 'type' => 'danger',
2088 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2089 'msg' => 'domain_invalid'
2090 );
2091 continue;
2092 }
2093 if ($_SESSION['mailcow_cc_role'] == "domainadmin" &&
2094 hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
2095 $is_now = mailbox('get', 'domain_details', $domain);
2096 if (!empty($is_now)) {
2097 $gal = (isset($_data['gal'])) ? intval($_data['gal']) : $is_now['gal'];
2098 $description = (!empty($_data['description']) && isset($_SESSION['acl']['domain_desc']) && $_SESSION['acl']['domain_desc'] == "1") ? $_data['description'] : $is_now['description'];
2099 }
2100 else {
2101 $_SESSION['return'][] = array(
2102 'type' => 'danger',
2103 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2104 'msg' => 'domain_invalid'
2105 );
2106 continue;
2107 }
2108 $stmt = $pdo->prepare("UPDATE `domain` SET
2109 `description` = :description,
2110 `gal` = :gal
2111 WHERE `domain` = :domain");
2112 $stmt->execute(array(
2113 ':description' => $description,
2114 ':gal' => $gal,
2115 ':domain' => $domain
2116 ));
2117 $_SESSION['return'][] = array(
2118 'type' => 'success',
2119 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2120 'msg' => array('domain_modified', htmlspecialchars($domain))
2121 );
2122 }
2123 elseif ($_SESSION['mailcow_cc_role'] == "admin") {
2124 $is_now = mailbox('get', 'domain_details', $domain);
2125 if (!empty($is_now)) {
2126 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
2127 $backupmx = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : $is_now['backupmx'];
2128 $gal = (isset($_data['gal'])) ? intval($_data['gal']) : $is_now['gal'];
2129 $relay_all_recipients = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : $is_now['relay_all_recipients'];
2130 $relay_unknown_only = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : $is_now['relay_unknown_only'];
2131 $relayhost = (isset($_data['relayhost'])) ? intval($_data['relayhost']) : $is_now['relayhost'];
2132 $aliases = (!empty($_data['aliases'])) ? $_data['aliases'] : $is_now['max_num_aliases_for_domain'];
2133 $mailboxes = (isset($_data['mailboxes']) && $_data['mailboxes'] != '') ? intval($_data['mailboxes']) : $is_now['max_num_mboxes_for_domain'];
2134 $defquota = (isset($_data['defquota']) && $_data['defquota'] != '') ? intval($_data['defquota']) : ($is_now['def_quota_for_mbox'] / 1048576);
2135 $maxquota = (!empty($_data['maxquota'])) ? $_data['maxquota'] : ($is_now['max_quota_for_mbox'] / 1048576);
2136 $quota = (!empty($_data['quota'])) ? $_data['quota'] : ($is_now['max_quota_for_domain'] / 1048576);
2137 $description = (!empty($_data['description'])) ? $_data['description'] : $is_now['description'];
2138 if ($relay_all_recipients == '1') {
2139 $backupmx = '1';
2140 }
2141 if ($relay_unknown_only == '1') {
2142 $backupmx = '1';
2143 $relay_all_recipients = '1';
2144 }
2145 }
2146 else {
2147 $_SESSION['return'][] = array(
2148 'type' => 'danger',
2149 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2150 'msg' => 'domain_invalid'
2151 );
2152 continue;
2153 }
2154 // todo: should be using api here
2155 $stmt = $pdo->prepare("SELECT
2156 COUNT(*) AS count,
2157 MAX(COALESCE(ROUND(`quota`/1048576), 0)) AS `biggest_mailbox`,
2158 COALESCE(ROUND(SUM(`quota`)/1048576), 0) AS `quota_all`
2159 FROM `mailbox`
2160 WHERE `kind` NOT REGEXP 'location|thing|group'
2161 AND domain = :domain");
2162 $stmt->execute(array(':domain' => $domain));
2163 $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
2164 // todo: should be using api here
2165 $stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias`
2166 WHERE domain = :domain
2167 AND address NOT IN (
2168 SELECT `username` FROM `mailbox`
2169 )");
2170 $stmt->execute(array(':domain' => $domain));
2171 $AliasData = $stmt->fetch(PDO::FETCH_ASSOC);
2172 if ($defquota > $maxquota) {
2173 $_SESSION['return'][] = array(
2174 'type' => 'danger',
2175 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2176 'msg' => 'mailbox_defquota_exceeds_mailbox_maxquota'
2177 );
2178 continue;
2179 }
2180 if ($defquota == "0" || empty($defquota)) {
2181 $_SESSION['return'][] = array(
2182 'type' => 'danger',
2183 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2184 'msg' => 'defquota_empty'
2185 );
2186 continue;
2187 }
2188 if ($maxquota > $quota) {
2189 $_SESSION['return'][] = array(
2190 'type' => 'danger',
2191 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2192 'msg' => 'mailbox_quota_exceeds_domain_quota'
2193 );
2194 continue;
2195 }
2196 if ($maxquota == "0" || empty($maxquota)) {
2197 $_SESSION['return'][] = array(
2198 'type' => 'danger',
2199 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2200 'msg' => 'maxquota_empty'
2201 );
2202 continue;
2203 }
2204 if ($MailboxData['biggest_mailbox'] > $maxquota) {
2205 $_SESSION['return'][] = array(
2206 'type' => 'danger',
2207 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2208 'msg' => array('max_quota_in_use', $MailboxData['biggest_mailbox'])
2209 );
2210 continue;
2211 }
2212 if ($MailboxData['quota_all'] > $quota) {
2213 $_SESSION['return'][] = array(
2214 'type' => 'danger',
2215 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2216 'msg' => array('domain_quota_m_in_use', $MailboxData['quota_all'])
2217 );
2218 continue;
2219 }
2220 if ($MailboxData['count'] > $mailboxes) {
2221 $_SESSION['return'][] = array(
2222 'type' => 'danger',
2223 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2224 'msg' => array('mailboxes_in_use', $MailboxData['count'])
2225 );
2226 continue;
2227 }
2228 if ($AliasData['count'] > $aliases) {
2229 $_SESSION['return'][] = array(
2230 'type' => 'danger',
2231 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2232 'msg' => array('aliases_in_use', $AliasData['count'])
2233 );
2234 continue;
2235 }
2236 $stmt = $pdo->prepare("UPDATE `domain` SET
2237 `relay_all_recipients` = :relay_all_recipients,
2238 `relay_unknown_only` = :relay_unknown_only,
2239 `backupmx` = :backupmx,
2240 `gal` = :gal,
2241 `active` = :active,
2242 `quota` = :quota,
2243 `defquota` = :defquota,
2244 `maxquota` = :maxquota,
2245 `relayhost` = :relayhost,
2246 `mailboxes` = :mailboxes,
2247 `aliases` = :aliases,
2248 `description` = :description
2249 WHERE `domain` = :domain");
2250 $stmt->execute(array(
2251 ':relay_all_recipients' => $relay_all_recipients,
2252 ':relay_unknown_only' => $relay_unknown_only,
2253 ':backupmx' => $backupmx,
2254 ':gal' => $gal,
2255 ':active' => $active,
2256 ':quota' => $quota,
2257 ':defquota' => $defquota,
2258 ':maxquota' => $maxquota,
2259 ':relayhost' => $relayhost,
2260 ':mailboxes' => $mailboxes,
2261 ':aliases' => $aliases,
2262 ':description' => $description,
2263 ':domain' => $domain
2264 ));
2265 $_SESSION['return'][] = array(
2266 'type' => 'success',
2267 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2268 'msg' => array('domain_modified', htmlspecialchars($domain))
2269 );
2270 }
2271 }
2272 break;
2273 case 'mailbox':
2274 if (!is_array($_data['username'])) {
2275 $usernames = array();
2276 $usernames[] = $_data['username'];
2277 }
2278 else {
2279 $usernames = $_data['username'];
2280 }
2281 foreach ($usernames as $username) {
2282 if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
2283 $_SESSION['return'][] = array(
2284 'type' => 'danger',
2285 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2286 'msg' => array('username_invalid', $username)
2287 );
2288 continue;
2289 }
2290 $is_now = mailbox('get', 'mailbox_details', $username);
2291 if (isset($_data['protocol_access'])) {
2292 $_data['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0;
2293 $_data['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0;
2294 $_data['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0;
2295 }
2296 if (!empty($is_now)) {
2297 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
2298 (int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
2299 (int)$sogo_access = (isset($_data['sogo_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
2300 (int)$imap_access = (isset($_data['imap_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
2301 (int)$pop3_access = (isset($_data['pop3_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
2302 (int)$smtp_access = (isset($_data['smtp_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
2303 (int)$quota_m = (isset_has_content($_data['quota'])) ? intval($_data['quota']) : ($is_now['quota'] / 1048576);
2304 $name = (!empty($_data['name'])) ? ltrim(rtrim($_data['name'], '>'), '<') : $is_now['name'];
2305 $domain = $is_now['domain'];
2306 $quota_b = $quota_m * 1048576;
2307 $password = (!empty($_data['password'])) ? $_data['password'] : null;
2308 $password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
2309 }
2310 else {
2311 $_SESSION['return'][] = array(
2312 'type' => 'danger',
2313 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2314 'msg' => 'access_denied'
2315 );
2316 continue;
2317 }
2318 // if already 0 == ok
2319 if ((!isset($_SESSION['acl']['unlimited_quota']) || $_SESSION['acl']['unlimited_quota'] != "1") && ($quota_m == 0 && $is_now['quota'] != 0)) {
2320 $_SESSION['return'][] = array(
2321 'type' => 'danger',
2322 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2323 'msg' => 'unlimited_quota_acl'
2324 );
2325 return false;
2326 }
2327 $stmt = $pdo->prepare("SELECT `quota`, `maxquota`
2328 FROM `domain`
2329 WHERE `domain` = :domain");
2330 $stmt->execute(array(':domain' => $domain));
2331 $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
2332 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
2333 $_SESSION['return'][] = array(
2334 'type' => 'danger',
2335 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2336 'msg' => 'access_denied'
2337 );
2338 continue;
2339 }
2340 if ($quota_m > $DomainData['maxquota']) {
2341 $_SESSION['return'][] = array(
2342 'type' => 'danger',
2343 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2344 'msg' => array('mailbox_quota_exceeded', $DomainData['maxquota'])
2345 );
2346 continue;
2347 }
2348 if (((($is_now['quota_used'] / 1048576) - $quota_m) + $quota_m) > $DomainData['quota']) {
2349 $_SESSION['return'][] = array(
2350 'type' => 'danger',
2351 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2352 'msg' => array('mailbox_quota_left_exceeded', ($is_now['max_new_quota'] / 1048576))
2353 );
2354 continue;
2355 }
2356 $extra_acls = array();
2357 if (isset($_data['extended_sender_acl'])) {
2358 if (!isset($_SESSION['acl']['extend_sender_acl']) || $_SESSION['acl']['extend_sender_acl'] != "1" ) {
2359 $_SESSION['return'][] = array(
2360 'type' => 'danger',
2361 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2362 'msg' => 'access_denied'
2363 );
2364 return false;
2365 }
2366 $extra_acls = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['extended_sender_acl']));
2367 foreach ($extra_acls as $i => &$extra_acl) {
2368 if (empty($extra_acl)) {
2369 continue;
2370 }
2371 if (substr($extra_acl, 0, 1) === "@") {
2372 $extra_acl = ltrim($extra_acl, '@');
2373 }
2374 if (!filter_var($extra_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($extra_acl)) {
2375 $_SESSION['return'][] = array(
2376 'type' => 'danger',
2377 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2378 'msg' => array('extra_acl_invalid', htmlspecialchars($extra_acl))
2379 );
2380 unset($extra_acls[$i]);
2381 continue;
2382 }
2383 $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
2384 if (filter_var($extra_acl, FILTER_VALIDATE_EMAIL)) {
2385 $extra_acl_domain = idn_to_ascii(substr(strstr($extra_acl, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
2386 if (in_array($extra_acl_domain, $domains)) {
2387 $_SESSION['return'][] = array(
2388 'type' => 'danger',
2389 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2390 'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
2391 );
2392 unset($extra_acls[$i]);
2393 continue;
2394 }
2395 }
2396 else {
2397 if (in_array($extra_acl, $domains)) {
2398 $_SESSION['return'][] = array(
2399 'type' => 'danger',
2400 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2401 'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
2402 );
2403 unset($extra_acls[$i]);
2404 continue;
2405 }
2406 $extra_acl = '@' . $extra_acl;
2407 }
2408 }
2409 $extra_acls = array_filter($extra_acls);
2410 $extra_acls = array_values($extra_acls);
2411 $extra_acls = array_unique($extra_acls);
2412 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `logged_in_as` = :username");
2413 $stmt->execute(array(
2414 ':username' => $username
2415 ));
2416 foreach ($extra_acls as $sender_acl_external) {
2417 $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`, `external`)
2418 VALUES (:sender_acl, :username, 1)");
2419 $stmt->execute(array(
2420 ':sender_acl' => $sender_acl_external,
2421 ':username' => $username
2422 ));
2423 }
2424 }
2425 if (isset($_data['sender_acl'])) {
2426 // Get sender_acl items set by admin
2427 $sender_acl_admin = array_merge(
2428 mailbox('get', 'sender_acl_handles', $username)['sender_acl_domains']['ro'],
2429 mailbox('get', 'sender_acl_handles', $username)['sender_acl_addresses']['ro']
2430 );
2431 // Get sender_acl items from POST array
2432 // Set sender_acl_domain_admin to empty array if sender_acl contains "default" to trigger a reset
2433 // Delete records from sender_acl if sender_acl contains "*" and set to array("*")
2434 $_data['sender_acl'] = (array)$_data['sender_acl'];
2435 if (in_array("*", $_data['sender_acl'])) {
2436 $sender_acl_domain_admin = array('*');
2437 }
2438 elseif (array("default") === $_data['sender_acl']) {
2439 $sender_acl_domain_admin = array();
2440 }
2441 else {
2442 if (array_search('default', $_data['sender_acl']) !== false){
2443 unset($_data['sender_acl'][array_search('default', $_data['sender_acl'])]);
2444 }
2445 $sender_acl_domain_admin = $_data['sender_acl'];
2446 }
2447 if (!empty($sender_acl_domain_admin) || !empty($sender_acl_admin)) {
2448 // Check items in POST array and skip invalid
2449 foreach ($sender_acl_domain_admin as $key => $val) {
2450 // Check for invalid domain or email format or not *
2451 if (!filter_var($val, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name(ltrim($val, '@')) && $val != '*') {
2452 $_SESSION['return'][] = array(
2453 'type' => 'danger',
2454 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2455 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key])
2456 );
2457 unset($sender_acl_domain_admin[$key]);
2458 continue;
2459 }
2460 // Check if user has domain access (if object is domain)
2461 $domain = ltrim($sender_acl_domain_admin[$key], '@');
2462 if (is_valid_domain_name($domain)) {
2463 // Check for- and skip non-mailcow domains
2464 $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
2465 if (!empty($domains)) {
2466 if (!in_array($domain, $domains)) {
2467 $_SESSION['return'][] = array(
2468 'type' => 'danger',
2469 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2470 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key])
2471 );
2472 unset($sender_acl_domain_admin[$key]);
2473 continue;
2474 }
2475 }
2476 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
2477 $_SESSION['return'][] = array(
2478 'type' => 'danger',
2479 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2480 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key])
2481 );
2482 unset($sender_acl_domain_admin[$key]);
2483 continue;
2484 }
2485 }
2486 // Wildcard can only be used if role == admin
2487 if ($val == '*' && $_SESSION['mailcow_cc_role'] != 'admin') {
2488 $_SESSION['return'][] = array(
2489 'type' => 'danger',
2490 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2491 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key])
2492 );
2493 unset($sender_acl_domain_admin[$key]);
2494 continue;
2495 }
2496 // Check if user has alias access (if object is email)
2497 if (filter_var($val, FILTER_VALIDATE_EMAIL)) {
2498 if (!hasAliasObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $val)) {
2499 $_SESSION['return'][] = array(
2500 'type' => 'danger',
2501 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2502 'msg' => array('sender_acl_invalid', $sender_acl_domain_admin[$key])
2503 );
2504 unset($sender_acl_domain_admin[$key]);
2505 continue;
2506 }
2507 }
2508 }
2509 // Merge both arrays
2510 $sender_acl_merged = array_merge($sender_acl_domain_admin, $sender_acl_admin);
2511 // If merged array still contains "*", set it as only value
2512 !in_array('*', $sender_acl_merged) ?: $sender_acl_merged = array('*');
2513 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 0 AND `logged_in_as` = :username");
2514 $stmt->execute(array(
2515 ':username' => $username
2516 ));
2517 $fixed_sender_aliases = mailbox('get', 'sender_acl_handles', $username)['fixed_sender_aliases'];
2518 foreach ($sender_acl_merged as $sender_acl) {
2519 $domain = ltrim($sender_acl, '@');
2520 if (is_valid_domain_name($domain)) {
2521 $sender_acl = '@' . $domain;
2522 }
2523 // Don't add if allowed by alias
2524 if (in_array($sender_acl, $fixed_sender_aliases)) {
2525 continue;
2526 }
2527 $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`)
2528 VALUES (:sender_acl, :username)");
2529 $stmt->execute(array(
2530 ':sender_acl' => $sender_acl,
2531 ':username' => $username
2532 ));
2533 }
2534 }
2535 else {
2536 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 0 AND `logged_in_as` = :username");
2537 $stmt->execute(array(
2538 ':username' => $username
2539 ));
2540 }
2541 }
2542 if (!empty($password) && !empty($password2)) {
2543 if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
2544 $_SESSION['return'][] = array(
2545 'type' => 'danger',
2546 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2547 'msg' => 'password_complexity'
2548 );
2549 continue;
2550 }
2551 if ($password != $password2) {
2552 $_SESSION['return'][] = array(
2553 'type' => 'danger',
2554 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2555 'msg' => 'password_mismatch'
2556 );
2557 continue;
2558 }
2559 // support pre hashed passwords
2560 if (preg_match('/^({SSHA256}|{SSHA}|{SHA512-CRYPT}|{SSHA512}|{MD5-CRYPT}|{PLAIN-MD5})/i', $password)) {
2561 $password_hashed = $password;
2562 }
2563 else {
2564 $password_hashed = hash_password($password);
2565 }
2566 $stmt = $pdo->prepare("UPDATE `mailbox` SET
2567 `password` = :password_hashed
2568 WHERE `username` = :username");
2569 $stmt->execute(array(
2570 ':password_hashed' => $password_hashed,
2571 ':username' => $username
2572 ));
2573 }
2574 // We could either set alias = 1 if alias = 2 or tune the Postfix alias table (that's what we did, TODO: to it the other way)
2575 $stmt = $pdo->prepare("UPDATE `alias` SET
2576 `active` = :active
2577 WHERE `address` = :address");
2578 $stmt->execute(array(
2579 ':address' => $username,
2580 ':active' => $active
2581 ));
2582 $stmt = $pdo->prepare("UPDATE `mailbox` SET
2583 `active` = :active,
2584 `name`= :name,
2585 `quota` = :quota_b,
2586 `attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update),
2587 `attributes` = JSON_SET(`attributes`, '$.sogo_access', :sogo_access),
2588 `attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
2589 `attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
2590 `attributes` = JSON_SET(`attributes`, '$.smtp_access', :smtp_access)
2591 WHERE `username` = :username");
2592 $stmt->execute(array(
2593 ':active' => $active,
2594 ':name' => $name,
2595 ':quota_b' => $quota_b,
2596 ':force_pw_update' => $force_pw_update,
2597 ':sogo_access' => $sogo_access,
2598 ':imap_access' => $imap_access,
2599 ':pop3_access' => $pop3_access,
2600 ':smtp_access' => $smtp_access,
2601 ':username' => $username
2602 ));
2603 $_SESSION['return'][] = array(
2604 'type' => 'success',
2605 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2606 'msg' => array('mailbox_modified', $username)
2607 );
2608 }
2609 break;
2610 case 'resource':
2611 if (!is_array($_data['name'])) {
2612 $names = array();
2613 $names[] = $_data['name'];
2614 }
2615 else {
2616 $names = $_data['name'];
2617 }
2618 foreach ($names as $name) {
2619 $is_now = mailbox('get', 'resource_details', $name);
2620 if (!empty($is_now)) {
2621 $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
2622 $multiple_bookings = (isset($_data['multiple_bookings'])) ? intval($_data['multiple_bookings']) : $is_now['multiple_bookings'];
2623 $description = (!empty($_data['description'])) ? $_data['description'] : $is_now['description'];
2624 $kind = (!empty($_data['kind'])) ? $_data['kind'] : $is_now['kind'];
2625 }
2626 else {
2627 $_SESSION['return'][] = array(
2628 'type' => 'danger',
2629 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2630 'msg' => array('resource_invalid', htmlspecialchars($name))
2631 );
2632 continue;
2633 }
2634 if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
2635 $_SESSION['return'][] = array(
2636 'type' => 'danger',
2637 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2638 'msg' => array('resource_invalid', htmlspecialchars($name))
2639 );
2640 continue;
2641 }
2642 if (!isset($multiple_bookings) || $multiple_bookings < -1) {
2643 $multiple_bookings = -1;
2644 }
2645 if (empty($description)) {
2646 $_SESSION['return'][] = array(
2647 'type' => 'danger',
2648 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2649 'msg' => array('description_invalid', htmlspecialchars($name))
2650 );
2651 continue;
2652 }
2653 if ($kind != 'location' && $kind != 'group' && $kind != 'thing') {
2654 $_SESSION['return'][] = array(
2655 'type' => 'danger',
2656 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2657 'msg' => array('resource_invalid', htmlspecialchars($name))
2658 );
2659 continue;
2660 }
2661 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) {
2662 $_SESSION['return'][] = array(
2663 'type' => 'danger',
2664 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2665 'msg' => 'access_denied'
2666 );
2667 continue;
2668 }
2669 $stmt = $pdo->prepare("UPDATE `mailbox` SET
2670 `active` = :active,
2671 `name`= :description,
2672 `kind`= :kind,
2673 `multiple_bookings`= :multiple_bookings
2674 WHERE `username` = :name");
2675 $stmt->execute(array(
2676 ':active' => $active,
2677 ':description' => $description,
2678 ':multiple_bookings' => $multiple_bookings,
2679 ':kind' => $kind,
2680 ':name' => $name
2681 ));
2682 $_SESSION['return'][] = array(
2683 'type' => 'success',
2684 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
2685 'msg' => array('resource_modified', htmlspecialchars($name))
2686 );
2687 }
2688 break;
2689 }
2690 break;
2691 case 'get':
2692 switch ($_type) {
2693 case 'sender_acl_handles':
2694 if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
2695 return false;
2696 }
2697 $data['sender_acl_domains']['ro'] = array();
2698 $data['sender_acl_domains']['rw'] = array();
2699 $data['sender_acl_domains']['selectable'] = array();
2700 $data['sender_acl_addresses']['ro'] = array();
2701 $data['sender_acl_addresses']['rw'] = array();
2702 $data['sender_acl_addresses']['selectable'] = array();
2703 $data['fixed_sender_aliases'] = array();
2704 $data['external_sender_aliases'] = array();
2705 // Fixed addresses
2706 $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` REGEXP :goto AND `address` NOT LIKE '@%'");
2707 $stmt->execute(array(':goto' => '(^|,)'.$_data.'($|,)'));
2708 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2709 while ($row = array_shift($rows)) {
2710 $data['fixed_sender_aliases'][] = $row['address'];
2711 }
2712 $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias_domain_alias` FROM `mailbox`, `alias_domain`
2713 WHERE `alias_domain`.`target_domain` = `mailbox`.`domain`
2714 AND `mailbox`.`username` = :username");
2715 $stmt->execute(array(':username' => $_data));
2716 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2717 while ($row = array_shift($rows)) {
2718 if (!empty($row['alias_domain_alias'])) {
2719 $data['fixed_sender_aliases'][] = $row['alias_domain_alias'];
2720 }
2721 }
2722 // External addresses
2723 $stmt = $pdo->prepare("SELECT `send_as` as `send_as_external` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND `external` = '1'");
2724 $stmt->execute(array(':logged_in_as' => $_data));
2725 $exernal_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2726 while ($row = array_shift($exernal_rows)) {
2727 if (!empty($row['send_as_external'])) {
2728 $data['external_sender_aliases'][] = $row['send_as_external'];
2729 }
2730 }
2731 // Return array $data['sender_acl_domains/addresses']['ro'] with read-only objects
2732 // Return array $data['sender_acl_domains/addresses']['rw'] with read-write objects (can be deleted)
2733 $stmt = $pdo->prepare("SELECT REPLACE(`send_as`, '@', '') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND `external` = '0' AND (`send_as` LIKE '@%' OR `send_as` = '*')");
2734 $stmt->execute(array(':logged_in_as' => $_data));
2735 $domain_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2736 while ($domain_row = array_shift($domain_rows)) {
2737 if (is_valid_domain_name($domain_row['send_as']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain_row['send_as'])) {
2738 $data['sender_acl_domains']['ro'][] = $domain_row['send_as'];
2739 continue;
2740 }
2741 if (is_valid_domain_name($domain_row['send_as']) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain_row['send_as'])) {
2742 $data['sender_acl_domains']['rw'][] = $domain_row['send_as'];
2743 continue;
2744 }
2745 if ($domain_row['send_as'] == '*' && $_SESSION['mailcow_cc_role'] != 'admin') {
2746 $data['sender_acl_domains']['ro'][] = $domain_row['send_as'];
2747 }
2748 if ($domain_row['send_as'] == '*' && $_SESSION['mailcow_cc_role'] == 'admin') {
2749 $data['sender_acl_domains']['rw'][] = $domain_row['send_as'];
2750 }
2751 }
2752 $stmt = $pdo->prepare("SELECT `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND `external` = '0' AND (`send_as` NOT LIKE '@%' AND `send_as` != '*')");
2753 $stmt->execute(array(':logged_in_as' => $_data));
2754 $address_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2755 while ($address_row = array_shift($address_rows)) {
2756 if (filter_var($address_row['send_as'], FILTER_VALIDATE_EMAIL) && !hasAliasObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $address_row['send_as'])) {
2757 $data['sender_acl_addresses']['ro'][] = $address_row['send_as'];
2758 continue;
2759 }
2760 if (filter_var($address_row['send_as'], FILTER_VALIDATE_EMAIL) && hasAliasObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $address_row['send_as'])) {
2761 $data['sender_acl_addresses']['rw'][] = $address_row['send_as'];
2762 continue;
2763 }
2764 }
2765 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
2766 WHERE `domain` NOT IN (
2767 SELECT REPLACE(`send_as`, '@', '') FROM `sender_acl`
2768 WHERE `logged_in_as` = :logged_in_as1
2769 AND `external` = '0'
2770 AND `send_as` LIKE '@%')
2771 UNION
2772 SELECT '*' FROM `domain`
2773 WHERE '*' NOT IN (
2774 SELECT `send_as` FROM `sender_acl`
2775 WHERE `logged_in_as` = :logged_in_as2
2776 AND `external` = '0'
2777 )");
2778 $stmt->execute(array(
2779 ':logged_in_as1' => $_data,
2780 ':logged_in_as2' => $_data
2781 ));
2782 $rows_domain = $stmt->fetchAll(PDO::FETCH_ASSOC);
2783 while ($row_domain = array_shift($rows_domain)) {
2784 if (is_valid_domain_name($row_domain['domain']) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row_domain['domain'])) {
2785 $data['sender_acl_domains']['selectable'][] = $row_domain['domain'];
2786 continue;
2787 }
2788 if ($row_domain['domain'] == '*' && $_SESSION['mailcow_cc_role'] == 'admin') {
2789 $data['sender_acl_domains']['selectable'][] = $row_domain['domain'];
2790 continue;
2791 }
2792 }
2793 $stmt = $pdo->prepare("SELECT `address` FROM `alias`
2794 WHERE `goto` != :goto
2795 AND `address` NOT IN (
2796 SELECT `send_as` FROM `sender_acl`
2797 WHERE `logged_in_as` = :logged_in_as
2798 AND `external` = '0'
2799 AND `send_as` NOT LIKE '@%')");
2800 $stmt->execute(array(
2801 ':logged_in_as' => $_data,
2802 ':goto' => $_data
2803 ));
2804 $rows_mbox = $stmt->fetchAll(PDO::FETCH_ASSOC);
2805 while ($row = array_shift($rows_mbox)) {
2806 // Aliases are not selectable
2807 if (in_array($row['address'], $data['fixed_sender_aliases'])) {
2808 continue;
2809 }
2810 if (filter_var($row['address'], FILTER_VALIDATE_EMAIL) && hasAliasObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['address'])) {
2811 $data['sender_acl_addresses']['selectable'][] = $row['address'];
2812 }
2813 }
2814 return $data;
2815 break;
2816 case 'mailboxes':
2817 $mailboxes = array();
2818 if (isset($_data) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2819 return false;
2820 }
2821 elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2822 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` = :domain");
2823 $stmt->execute(array(
2824 ':domain' => $_data,
2825 ));
2826 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2827 while($row = array_shift($rows)) {
2828 $mailboxes[] = $row['username'];
2829 }
2830 }
2831 else {
2832 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND (`domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role)");
2833 $stmt->execute(array(
2834 ':username' => $_SESSION['mailcow_cc_username'],
2835 ':role' => $_SESSION['mailcow_cc_role'],
2836 ));
2837 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2838 while($row = array_shift($rows)) {
2839 $mailboxes[] = $row['username'];
2840 }
2841 }
2842 return $mailboxes;
2843 break;
2844 case 'tls_policy':
2845 $attrs = array();
2846 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
2847 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2848 return false;
2849 }
2850 }
2851 else {
2852 $_data = $_SESSION['mailcow_cc_username'];
2853 }
2854 $stmt = $pdo->prepare("SELECT `attributes` FROM `mailbox` WHERE `username` = :username");
2855 $stmt->execute(array(':username' => $_data));
2856 $attrs = $stmt->fetch(PDO::FETCH_ASSOC);
2857 $attrs = json_decode($attrs['attributes'], true);
2858 return array(
2859 'tls_enforce_in' => $attrs['tls_enforce_in'],
2860 'tls_enforce_out' => $attrs['tls_enforce_out']
2861 );
2862 break;
2863 case 'quarantine_notification':
2864 $attrs = array();
2865 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
2866 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2867 return false;
2868 }
2869 }
2870 else {
2871 $_data = $_SESSION['mailcow_cc_username'];
2872 }
2873 $stmt = $pdo->prepare("SELECT `attributes` FROM `mailbox` WHERE `username` = :username");
2874 $stmt->execute(array(':username' => $_data));
2875 $attrs = $stmt->fetch(PDO::FETCH_ASSOC);
2876 $attrs = json_decode($attrs['attributes'], true);
2877 return $attrs['quarantine_notification'];
2878 break;
2879 case 'quarantine_category':
2880 $attrs = array();
2881 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
2882 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2883 return false;
2884 }
2885 }
2886 else {
2887 $_data = $_SESSION['mailcow_cc_username'];
2888 }
2889 $stmt = $pdo->prepare("SELECT `attributes` FROM `mailbox` WHERE `username` = :username");
2890 $stmt->execute(array(':username' => $_data));
2891 $attrs = $stmt->fetch(PDO::FETCH_ASSOC);
2892 $attrs = json_decode($attrs['attributes'], true);
2893 return $attrs['quarantine_category'];
2894 break;
2895 case 'filters':
2896 $filters = array();
2897 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
2898 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2899 return false;
2900 }
2901 }
2902 else {
2903 $_data = $_SESSION['mailcow_cc_username'];
2904 }
2905 $stmt = $pdo->prepare("SELECT `id` FROM `sieve_filters` WHERE `username` = :username");
2906 $stmt->execute(array(':username' => $_data));
2907 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
2908 while($row = array_shift($rows)) {
2909 $filters[] = $row['id'];
2910 }
2911 return $filters;
2912 break;
2913 case 'global_filter_details':
2914 $global_filters = array();
2915 if ($_SESSION['mailcow_cc_role'] != "admin") {
2916 return false;
2917 }
2918 $global_filters['prefilter'] = file_get_contents('/global_sieve/before');
2919 $global_filters['postfilter'] = file_get_contents('/global_sieve/after');
2920 return $global_filters;
2921 break;
2922 case 'filter_details':
2923 $filter_details = array();
2924 if (!is_numeric($_data)) {
2925 return false;
2926 }
2927 $stmt = $pdo->prepare("SELECT CASE `script_name` WHEN 'active' THEN 1 ELSE 0 END AS `active`,
2928 id,
2929 username,
2930 filter_type,
2931 script_data,
2932 script_desc
2933 FROM `sieve_filters`
2934 WHERE `id` = :id");
2935 $stmt->execute(array(':id' => $_data));
2936 $filter_details = $stmt->fetch(PDO::FETCH_ASSOC);
2937 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $filter_details['username'])) {
2938 return false;
2939 }
2940 return $filter_details;
2941 break;
2942 case 'active_user_sieve':
2943 $filter_details = array();
2944 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
2945 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
2946 return false;
2947 }
2948 }
2949 else {
2950 $_data = $_SESSION['mailcow_cc_username'];
2951 }
2952 $exec_fields = array(
2953 'cmd' => 'sieve',
2954 'task' => 'list',
2955 'username' => $_data
2956 );
2957 $filters = docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
2958 $filters = array_filter(preg_split("/(\r\n|\n|\r)/",$filters));
2959 foreach ($filters as $filter) {
2960 if (preg_match('/.+ ACTIVE/i', $filter)) {
2961 $exec_fields = array(
2962 'cmd' => 'sieve',
2963 'task' => 'print',
2964 'script_name' => substr($filter, 0, -7),
2965 'username' => $_data
2966 );
2967 $script = docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
2968 // Remove first line
2969 return preg_replace('/^.+\n/', '', $script);
2970 }
2971 }
2972 return false;
2973 break;
2974 case 'syncjob_details':
2975 $syncjobdetails = array();
2976 if (!is_numeric($_data)) {
2977 return false;
2978 }
2979 if (isset($_extra) && in_array('no_log', $_extra)) {
2980 $field_query = $pdo->query('SHOW FIELDS FROM `imapsync` WHERE FIELD NOT IN ("returned_text", "password1")');
2981 $fields = $field_query->fetchAll(PDO::FETCH_ASSOC);
2982 while($field = array_shift($fields)) {
2983 $shown_fields[] = $field['Field'];
2984 }
2985 $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ",
2986 `active`
2987 FROM `imapsync` WHERE id = :id");
2988 }
2989 elseif (isset($_extra) && in_array('with_password', $_extra)) {
2990 $stmt = $pdo->prepare("SELECT *,
2991 `active`
2992 FROM `imapsync` WHERE id = :id");
2993 }
2994 else {
2995 $field_query = $pdo->query('SHOW FIELDS FROM `imapsync` WHERE FIELD NOT IN ("password1")');
2996 $fields = $field_query->fetchAll(PDO::FETCH_ASSOC);
2997 while($field = array_shift($fields)) {
2998 $shown_fields[] = $field['Field'];
2999 }
3000 $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ",
3001 `active`
3002 FROM `imapsync` WHERE id = :id");
3003 }
3004 $stmt->execute(array(':id' => $_data));
3005 $syncjobdetails = $stmt->fetch(PDO::FETCH_ASSOC);
3006 if (!empty($syncjobdetails['returned_text'])) {
3007 $syncjobdetails['log'] = $syncjobdetails['returned_text'];
3008 }
3009 else {
3010 $syncjobdetails['log'] = '';
3011 }
3012 unset($syncjobdetails['returned_text']);
3013 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $syncjobdetails['user2'])) {
3014 return false;
3015 }
3016 return $syncjobdetails;
3017 break;
3018 case 'syncjobs':
3019 $syncjobdata = array();
3020 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
3021 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3022 return false;
3023 }
3024 }
3025 else {
3026 $_data = $_SESSION['mailcow_cc_username'];
3027 }
3028 $stmt = $pdo->prepare("SELECT `id` FROM `imapsync` WHERE `user2` = :username");
3029 $stmt->execute(array(':username' => $_data));
3030 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3031 while($row = array_shift($rows)) {
3032 $syncjobdata[] = $row['id'];
3033 }
3034 return $syncjobdata;
3035 break;
3036 case 'spam_score':
3037 $curl = curl_init();
3038 curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/var/lib/rspamd/rspamd.sock');
3039 curl_setopt($curl, CURLOPT_URL,"http://rspamd/actions");
3040 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
3041 $default_actions = curl_exec($curl);
3042 if (!curl_errno($curl)) {
3043 $data_array = json_decode($default_actions, true);
3044 curl_close($curl);
3045 foreach ($data_array as $data) {
3046 if ($data['action'] == 'reject') {
3047 $reject = $data['value'];
3048 continue;
3049 }
3050 elseif ($data['action'] == 'add header') {
3051 $add_header = $data['value'];
3052 continue;
3053 }
3054 }
3055 if (empty($add_header) || empty($reject)) {
3056 // Assume default, set warning
3057 $default = "5, 15";
3058 $_SESSION['return'][] = array(
3059 'type' => 'warning',
3060 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3061 'msg' => 'Could not determine servers default spam score, assuming default'
3062 );
3063 }
3064 else {
3065 $default = $add_header . ', ' . $reject;
3066 }
3067 }
3068 else {
3069 // Assume default, set warning
3070 $default = "5, 15";
3071 $_SESSION['return'][] = array(
3072 'type' => 'warning',
3073 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3074 'msg' => 'Could not determine servers default spam score, assuming default'
3075 );
3076 }
3077 curl_close($curl);
3078 $policydata = array();
3079 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
3080 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3081 return false;
3082 }
3083 }
3084 else {
3085 $_data = $_SESSION['mailcow_cc_username'];
3086 }
3087 $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object` = :username AND
3088 (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
3089 $stmt->execute(array(':username' => $_data));
3090 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
3091 if (empty($num_results)) {
3092 return $default;
3093 }
3094 else {
3095 $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'highspamlevel' AND `object` = :username");
3096 $stmt->execute(array(':username' => $_data));
3097 $highspamlevel = $stmt->fetch(PDO::FETCH_ASSOC);
3098 $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'lowspamlevel' AND `object` = :username");
3099 $stmt->execute(array(':username' => $_data));
3100 $lowspamlevel = $stmt->fetch(PDO::FETCH_ASSOC);
3101 return $lowspamlevel['value'].', '.$highspamlevel['value'];
3102 }
3103 break;
3104 case 'time_limited_aliases':
3105 $tladata = array();
3106 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
3107 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3108 return false;
3109 }
3110 }
3111 else {
3112 $_data = $_SESSION['mailcow_cc_username'];
3113 }
3114 $stmt = $pdo->prepare("SELECT `address`,
3115 `goto`,
3116 `validity`
3117 FROM `spamalias`
3118 WHERE `goto` = :username
3119 AND `validity` >= :unixnow");
3120 $stmt->execute(array(':username' => $_data, ':unixnow' => time()));
3121 $tladata = $stmt->fetchAll(PDO::FETCH_ASSOC);
3122 return $tladata;
3123 break;
3124 case 'delimiter_action':
3125 $policydata = array();
3126 if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {
3127 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3128 return false;
3129 }
3130 }
3131 else {
3132 $_data = $_SESSION['mailcow_cc_username'];
3133 }
3134 try {
3135 if ($redis->hGet('RCPT_WANTS_SUBJECT_TAG', $_data)) {
3136 return "subject";
3137 }
3138 elseif ($redis->hGet('RCPT_WANTS_SUBFOLDER_TAG', $_data)) {
3139 return "subfolder";
3140 }
3141 else {
3142 return "none";
3143 }
3144 }
3145 catch (RedisException $e) {
3146 $_SESSION['return'][] = array(
3147 'type' => 'danger',
3148 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3149 'msg' => array('redis_error', $e)
3150 );
3151 return false;
3152 }
3153 break;
3154 case 'resources':
3155 $resources = array();
3156 if (isset($_data) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3157 return false;
3158 }
3159 elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3160 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` = :domain");
3161 $stmt->execute(array(
3162 ':domain' => $_data,
3163 ));
3164 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3165 while($row = array_shift($rows)) {
3166 $resources[] = $row['username'];
3167 }
3168 }
3169 else {
3170 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role");
3171 $stmt->execute(array(
3172 ':username' => $_SESSION['mailcow_cc_username'],
3173 ':role' => $_SESSION['mailcow_cc_role'],
3174 ));
3175 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3176 while($row = array_shift($rows)) {
3177 $resources[] = $row['username'];
3178 }
3179 }
3180 return $resources;
3181 break;
3182 case 'alias_domains':
3183 $aliasdomains = array();
3184 if (isset($_data) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3185 return false;
3186 }
3187 elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3188 $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain");
3189 $stmt->execute(array(
3190 ':domain' => $_data,
3191 ));
3192 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3193 while($row = array_shift($rows)) {
3194 $aliasdomains[] = $row['alias_domain'];
3195 }
3196 }
3197 else {
3198 $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role");
3199 $stmt->execute(array(
3200 ':username' => $_SESSION['mailcow_cc_username'],
3201 ':role' => $_SESSION['mailcow_cc_role'],
3202 ));
3203 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3204 while($row = array_shift($rows)) {
3205 $aliasdomains[] = $row['alias_domain'];
3206 }
3207 }
3208 return $aliasdomains;
3209 break;
3210 case 'aliases':
3211 $aliases = array();
3212 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3213 return false;
3214 }
3215 $stmt = $pdo->prepare("SELECT `id` FROM `alias` WHERE `address` != `goto` AND `domain` = :domain");
3216 $stmt->execute(array(
3217 ':domain' => $_data,
3218 ));
3219 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3220 while($row = array_shift($rows)) {
3221 $aliases[] = $row['id'];
3222 }
3223 return $aliases;
3224 break;
3225 case 'alias_details':
3226 $aliasdata = array();
3227 $stmt = $pdo->prepare("SELECT
3228 `id`,
3229 `domain`,
3230 `goto`,
3231 `address`,
3232 `public_comment`,
3233 `private_comment`,
3234 `active`,
3235 `sogo_visible`,
3236 `created`,
3237 `modified`
3238 FROM `alias`
3239 WHERE (`id` = :id OR `address` = :address) AND `address` != `goto`");
3240 $stmt->execute(array(
3241 ':id' => $_data,
3242 ':address' => $_data,
3243 ));
3244 $row = $stmt->fetch(PDO::FETCH_ASSOC);
3245 $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain");
3246 $stmt->execute(array(
3247 ':domain' => $row['domain'],
3248 ));
3249 $row_alias_domain = $stmt->fetch(PDO::FETCH_ASSOC);
3250 if (isset($row_alias_domain['target_domain']) && !empty($row_alias_domain['target_domain'])) {
3251 $aliasdata['in_primary_domain'] = $row_alias_domain['target_domain'];
3252 }
3253 else {
3254 $aliasdata['in_primary_domain'] = "";
3255 }
3256 $aliasdata['id'] = $row['id'];
3257 $aliasdata['domain'] = $row['domain'];
3258 $aliasdata['public_comment'] = $row['public_comment'];
3259 $aliasdata['private_comment'] = $row['private_comment'];
3260 $aliasdata['domain'] = $row['domain'];
3261 $aliasdata['goto'] = $row['goto'];
3262 $aliasdata['address'] = $row['address'];
3263 (!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0;
3264 $aliasdata['active'] = $row['active'];
3265 $aliasdata['active_int'] = $row['active'];
3266 $aliasdata['sogo_visible'] = $row['sogo_visible'];
3267 $aliasdata['sogo_visible_int'] = $row['sogo_visible'];
3268 $aliasdata['created'] = $row['created'];
3269 $aliasdata['modified'] = $row['modified'];
3270 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdata['domain'])) {
3271 return false;
3272 }
3273 return $aliasdata;
3274 break;
3275 case 'alias_domain_details':
3276 $aliasdomaindata = array();
3277 $rl = ratelimit('get', 'domain', $_data);
3278 $stmt = $pdo->prepare("SELECT
3279 `alias_domain`,
3280 `target_domain`,
3281 `active`,
3282 `created`,
3283 `modified`
3284 FROM `alias_domain`
3285 WHERE `alias_domain` = :aliasdomain");
3286 $stmt->execute(array(
3287 ':aliasdomain' => $_data,
3288 ));
3289 $row = $stmt->fetch(PDO::FETCH_ASSOC);
3290 $stmt = $pdo->prepare("SELECT `backupmx` FROM `domain` WHERE `domain` = :target_domain");
3291 $stmt->execute(array(
3292 ':target_domain' => $row['target_domain']
3293 ));
3294 $row_parent = $stmt->fetch(PDO::FETCH_ASSOC);
3295 $aliasdomaindata['alias_domain'] = $row['alias_domain'];
3296 $aliasdomaindata['parent_is_backupmx'] = $row_parent['backupmx'];
3297 $aliasdomaindata['target_domain'] = $row['target_domain'];
3298 $aliasdomaindata['active'] = $row['active'];
3299 $aliasdomaindata['active_int'] = $row['active'];
3300 $aliasdomaindata['rl'] = $rl;
3301 $aliasdomaindata['created'] = $row['created'];
3302 $aliasdomaindata['modified'] = $row['modified'];
3303 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdomaindata['target_domain'])) {
3304 return false;
3305 }
3306 return $aliasdomaindata;
3307 break;
3308 case 'domains':
3309 $domains = array();
3310 if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
3311 return false;
3312 }
3313 $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
3314 WHERE (`domain` IN (
3315 SELECT `domain` from `domain_admins`
3316 WHERE (`active`='1' AND `username` = :username))
3317 )
3318 OR 'admin'= :role");
3319 $stmt->execute(array(
3320 ':username' => $_SESSION['mailcow_cc_username'],
3321 ':role' => $_SESSION['mailcow_cc_role'],
3322 ));
3323 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
3324 while($row = array_shift($rows)) {
3325 $domains[] = $row['domain'];
3326 }
3327 return $domains;
3328 break;
3329 case 'domain_details':
3330 $domaindata = array();
3331 $_data = idn_to_ascii(strtolower(trim($_data)), 0, INTL_IDNA_VARIANT_UTS46);
3332 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3333 return false;
3334 }
3335 $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain");
3336 $stmt->execute(array(
3337 ':domain' => $_data
3338 ));
3339 $row = $stmt->fetch(PDO::FETCH_ASSOC);
3340 if (!empty($row)) {
3341 $_data = $row['target_domain'];
3342 }
3343 $stmt = $pdo->prepare("SELECT
3344 `domain`,
3345 `description`,
3346 `aliases`,
3347 `mailboxes`,
3348 `defquota`,
3349 `maxquota`,
3350 `quota`,
3351 `relayhost`,
3352 `relay_all_recipients`,
3353 `relay_unknown_only`,
3354 `backupmx`,
3355 `gal`,
3356 `active`
3357 FROM `domain` WHERE `domain`= :domain");
3358 $stmt->execute(array(
3359 ':domain' => $_data
3360 ));
3361 $row = $stmt->fetch(PDO::FETCH_ASSOC);
3362 if (empty($row)) {
3363 return false;
3364 }
3365 $stmt = $pdo->prepare("SELECT COUNT(*) AS `count`,
3366 COALESCE(SUM(`quota`), 0) AS `in_use`
3367 FROM `mailbox`
3368 WHERE `kind` NOT REGEXP 'location|thing|group'
3369 AND `domain` = :domain");
3370 $stmt->execute(array(':domain' => $row['domain']));
3371 $MailboxDataDomain = $stmt->fetch(PDO::FETCH_ASSOC);
3372 $stmt = $pdo->prepare("SELECT SUM(bytes) AS `bytes_total`, SUM(messages) AS `msgs_total` FROM `quota2`
3373 WHERE `username` IN (
3374 SELECT `username` FROM `mailbox`
3375 WHERE `domain` = :domain
3376 );");
3377 $stmt->execute(array(':domain' => $row['domain']));
3378 $SumQuotaInUse = $stmt->fetch(PDO::FETCH_ASSOC);
3379 $rl = ratelimit('get', 'domain', $_data);
3380 $domaindata['max_new_mailbox_quota'] = ($row['quota'] * 1048576) - $MailboxDataDomain['in_use'];
3381 if ($domaindata['max_new_mailbox_quota'] > ($row['maxquota'] * 1048576)) {
3382 $domaindata['max_new_mailbox_quota'] = ($row['maxquota'] * 1048576);
3383 }
3384 $domaindata['def_new_mailbox_quota'] = $domaindata['max_new_mailbox_quota'];
3385 if ($domaindata['def_new_mailbox_quota'] > ($row['defquota'] * 1048576)) {
3386 $domaindata['def_new_mailbox_quota'] = ($row['defquota'] * 1048576);
3387 }
3388 $domaindata['quota_used_in_domain'] = $MailboxDataDomain['in_use'];
3389 if (!empty($SumQuotaInUse['bytes_total'])) {
3390 $domaindata['bytes_total'] = $SumQuotaInUse['bytes_total'];
3391 }
3392 else {
3393 $domaindata['bytes_total'] = 0;
3394 }
3395 if (!empty($SumQuotaInUse['msgs_total'])) {
3396 $domaindata['msgs_total'] = $SumQuotaInUse['msgs_total'];
3397 }
3398 else {
3399 $domaindata['msgs_total'] = 0;
3400 }
3401 $domaindata['mboxes_in_domain'] = $MailboxDataDomain['count'];
3402 $domaindata['mboxes_left'] = $row['mailboxes'] - $MailboxDataDomain['count'];
3403 $domaindata['domain_name'] = $row['domain'];
3404 $domaindata['description'] = $row['description'];
3405 $domaindata['max_num_aliases_for_domain'] = $row['aliases'];
3406 $domaindata['max_num_mboxes_for_domain'] = $row['mailboxes'];
3407 $domaindata['def_quota_for_mbox'] = $row['defquota'] * 1048576;
3408 $domaindata['max_quota_for_mbox'] = $row['maxquota'] * 1048576;
3409 $domaindata['max_quota_for_domain'] = $row['quota'] * 1048576;
3410 $domaindata['relayhost'] = $row['relayhost'];
3411 $domaindata['backupmx'] = $row['backupmx'];
3412 $domaindata['backupmx_int'] = $row['backupmx'];
3413 $domaindata['gal'] = $row['gal'];
3414 $domaindata['gal_int'] = $row['gal'];
3415 $domaindata['rl'] = $rl;
3416 $domaindata['active'] = $row['active'];
3417 $domaindata['active_int'] = $row['active'];
3418 $domaindata['relay_all_recipients'] = $row['relay_all_recipients'];
3419 $domaindata['relay_all_recipients_int'] = $row['relay_all_recipients'];
3420 $domaindata['relay_unknown_only'] = $row['relay_unknown_only'];
3421 $domaindata['relay_unknown_only_int'] = $row['relay_unknown_only'];
3422 $stmt = $pdo->prepare("SELECT COUNT(*) AS `alias_count` FROM `alias`
3423 WHERE (`domain`= :domain OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain2))
3424 AND `address` NOT IN (
3425 SELECT `username` FROM `mailbox`
3426 )");
3427 $stmt->execute(array(
3428 ':domain' => $_data,
3429 ':domain2' => $_data
3430 ));
3431 $AliasDataDomain = $stmt->fetch(PDO::FETCH_ASSOC);
3432 (isset($AliasDataDomain['alias_count'])) ? $domaindata['aliases_in_domain'] = $AliasDataDomain['alias_count'] : $domaindata['aliases_in_domain'] = "0";
3433 $domaindata['aliases_left'] = $row['aliases'] - $AliasDataDomain['alias_count'];
3434 if ($_SESSION['mailcow_cc_role'] == "admin")
3435 {
3436 $stmt = $pdo->prepare("SELECT GROUP_CONCAT(`username` SEPARATOR ', ') AS domain_admins FROM `domain_admins` WHERE `domain` = :domain");
3437 $stmt->execute(array(
3438 ':domain' => $_data
3439 ));
3440 $domain_admins = $stmt->fetch(PDO::FETCH_ASSOC);
3441 (isset($domain_admins['domain_admins'])) ? $domaindata['domain_admins'] = $domain_admins['domain_admins'] : $domaindata['domain_admins'] = "-";
3442 }
3443 return $domaindata;
3444 break;
3445 case 'mailbox_details':
3446 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3447 return false;
3448 }
3449 $mailboxdata = array();
3450 $rl = ratelimit('get', 'mailbox', $_data);
3451 $last_imap_login = $redis->Get('last-login/imap/' . $_data);
3452 $last_smtp_login = $redis->Get('last-login/smtp/' . $_data);
3453 $last_pop3_login = $redis->Get('last-login/pop3/' . $_data);
3454 if ($last_imap_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
3455 $last_imap_login = '0';
3456 }
3457 if ($last_smtp_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
3458 $last_smtp_login = '0';
3459 }
3460 if ($last_pop3_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
3461 $last_pop3_login = '0';
3462 }
3463 if (preg_match('/y|yes/i', getenv('MASTER'))) {
3464 $stmt = $pdo->prepare("SELECT
3465 `domain`.`backupmx`,
3466 `mailbox`.`username`,
3467 `mailbox`.`name`,
3468 `mailbox`.`active`,
3469 `mailbox`.`domain`,
3470 `mailbox`.`local_part`,
3471 `mailbox`.`quota`,
3472 `quota2`.`bytes`,
3473 `attributes`,
3474 `quota2`.`messages`
3475 FROM `mailbox`, `quota2`, `domain`
3476 WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group' AND `mailbox`.`username` = `quota2`.`username` AND `domain`.`domain` = `mailbox`.`domain` AND `mailbox`.`username` = :mailbox");
3477 }
3478 else {
3479 $stmt = $pdo->prepare("SELECT
3480 `domain`.`backupmx`,
3481 `mailbox`.`username`,
3482 `mailbox`.`name`,
3483 `mailbox`.`active`,
3484 `mailbox`.`domain`,
3485 `mailbox`.`local_part`,
3486 `mailbox`.`quota`,
3487 `quota2replica`.`bytes`,
3488 `attributes`,
3489 `quota2replica`.`messages`
3490 FROM `mailbox`, `quota2replica`, `domain`
3491 WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group' AND `mailbox`.`username` = `quota2replica`.`username` AND `domain`.`domain` = `mailbox`.`domain` AND `mailbox`.`username` = :mailbox");
3492 }
3493 $stmt->execute(array(
3494 ':mailbox' => $_data,
3495 ));
3496 $row = $stmt->fetch(PDO::FETCH_ASSOC);
3497 $stmt = $pdo->prepare("SELECT `maxquota`, `quota` FROM `domain` WHERE `domain` = :domain");
3498 $stmt->execute(array(':domain' => $row['domain']));
3499 $DomainQuota = $stmt->fetch(PDO::FETCH_ASSOC);
3500 $stmt = $pdo->prepare("SELECT IFNULL(COUNT(`active`), 0) AS `pushover_active` FROM `pushover` WHERE `username` = :username AND `active` = 1");
3501 $stmt->execute(array(':username' => $_data));
3502 $PushoverActive = $stmt->fetch(PDO::FETCH_ASSOC);
3503 $stmt = $pdo->prepare("SELECT COALESCE(SUM(`quota`), 0) as `in_use` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` = :domain AND `username` != :username");
3504 $stmt->execute(array(':domain' => $row['domain'], ':username' => $_data));
3505 $MailboxUsage = $stmt->fetch(PDO::FETCH_ASSOC);
3506 $stmt = $pdo->prepare("SELECT IFNULL(COUNT(`address`), 0) AS `sa_count` FROM `spamalias` WHERE `goto` = :address AND `validity` >= :unixnow");
3507 $stmt->execute(array(':address' => $_data, ':unixnow' => time()));
3508 $SpamaliasUsage = $stmt->fetch(PDO::FETCH_ASSOC);
3509 $mailboxdata['max_new_quota'] = ($DomainQuota['quota'] * 1048576) - $MailboxUsage['in_use'];
3510 if ($mailboxdata['max_new_quota'] > ($DomainQuota['maxquota'] * 1048576)) {
3511 $mailboxdata['max_new_quota'] = ($DomainQuota['maxquota'] * 1048576);
3512 }
3513 $mailboxdata['username'] = $row['username'];
3514 if (!empty($rl)) {
3515 $mailboxdata['rl'] = $rl;
3516 $mailboxdata['rl_scope'] = 'mailbox';
3517 }
3518 else {
3519 $mailboxdata['rl'] = ratelimit('get', 'domain', $row['domain']);
3520 $mailboxdata['rl_scope'] = 'domain';
3521 }
3522 $mailboxdata['is_relayed'] = $row['backupmx'];
3523 $mailboxdata['name'] = $row['name'];
3524 $mailboxdata['last_imap_login'] = $last_imap_login;
3525 $mailboxdata['last_smtp_login'] = $last_smtp_login;
3526 $mailboxdata['last_pop3_login'] = $last_pop3_login;
3527 $mailboxdata['active'] = $row['active'];
3528 $mailboxdata['active_int'] = $row['active'];
3529 $mailboxdata['domain'] = $row['domain'];
3530 $mailboxdata['local_part'] = $row['local_part'];
3531 $mailboxdata['quota'] = $row['quota'];
3532 $mailboxdata['attributes'] = json_decode($row['attributes'], true);
3533 $mailboxdata['quota_used'] = intval($row['bytes']);
3534 $mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100);
3535 $mailboxdata['messages'] = $row['messages'];
3536 $mailboxdata['spam_aliases'] = $SpamaliasUsage['sa_count'];
3537 $mailboxdata['pushover_active'] = ($PushoverActive['pushover_active'] == 1) ? 1 : 0;
3538 if ($mailboxdata['percent_in_use'] === '- ') {
3539 $mailboxdata['percent_class'] = "info";
3540 }
3541 elseif ($mailboxdata['percent_in_use'] >= 90) {
3542 $mailboxdata['percent_class'] = "danger";
3543 }
3544 elseif ($mailboxdata['percent_in_use'] >= 75) {
3545 $mailboxdata['percent_class'] = "warning";
3546 }
3547 else {
3548 $mailboxdata['percent_class'] = "success";
3549 }
3550 return $mailboxdata;
3551 break;
3552 case 'resource_details':
3553 $resourcedata = array();
3554 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
3555 return false;
3556 }
3557 $stmt = $pdo->prepare("SELECT
3558 `username`,
3559 `name`,
3560 `kind`,
3561 `multiple_bookings`,
3562 `local_part`,
3563 `active`,
3564 `domain`
3565 FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `username` = :resource");
3566 $stmt->execute(array(
3567 ':resource' => $_data,
3568 ));
3569 $row = $stmt->fetch(PDO::FETCH_ASSOC);
3570 $resourcedata['name'] = $row['username'];
3571 $resourcedata['kind'] = $row['kind'];
3572 $resourcedata['multiple_bookings'] = $row['multiple_bookings'];
3573 $resourcedata['description'] = $row['name'];
3574 $resourcedata['active'] = $row['active'];
3575 $resourcedata['active_int'] = $row['active'];
3576 $resourcedata['domain'] = $row['domain'];
3577 $resourcedata['local_part'] = $row['local_part'];
3578 if (!isset($resourcedata['domain']) ||
3579 (isset($resourcedata['domain']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $resourcedata['domain']))) {
3580 return false;
3581 }
3582 return $resourcedata;
3583 break;
3584 }
3585 break;
3586 case 'delete':
3587 switch ($_type) {
3588 case 'syncjob':
3589 if (!is_array($_data['id'])) {
3590 $ids = array();
3591 $ids[] = $_data['id'];
3592 }
3593 else {
3594 $ids = $_data['id'];
3595 }
3596 if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) {
3597 $_SESSION['return'][] = array(
3598 'type' => 'danger',
3599 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3600 'msg' => 'access_denied'
3601 );
3602 return false;
3603 }
3604 foreach ($ids as $id) {
3605 if (!is_numeric($id)) {
3606 return false;
3607 }
3608 $stmt = $pdo->prepare("SELECT `user2` FROM `imapsync` WHERE id = :id");
3609 $stmt->execute(array(':id' => $id));
3610 $user2 = $stmt->fetch(PDO::FETCH_ASSOC)['user2'];
3611 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $user2)) {
3612 $_SESSION['return'][] = array(
3613 'type' => 'danger',
3614 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3615 'msg' => 'access_denied'
3616 );
3617 continue;
3618 }
3619 $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `id`= :id");
3620 $stmt->execute(array(':id' => $id));
3621 $_SESSION['return'][] = array(
3622 'type' => 'success',
3623 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3624 'msg' => array('deleted_syncjob', $id)
3625 );
3626 }
3627 break;
3628 case 'filter':
3629 if (!is_array($_data['id'])) {
3630 $ids = array();
3631 $ids[] = $_data['id'];
3632 }
3633 else {
3634 $ids = $_data['id'];
3635 }
3636 if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) {
3637 $_SESSION['return'][] = array(
3638 'type' => 'danger',
3639 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3640 'msg' => 'access_denied'
3641 );
3642 return false;
3643 }
3644 foreach ($ids as $id) {
3645 if (!is_numeric($id)) {
3646 continue;
3647 }
3648 $stmt = $pdo->prepare("SELECT `username` FROM `sieve_filters` WHERE id = :id");
3649 $stmt->execute(array(':id' => $id));
3650 $usr = $stmt->fetch(PDO::FETCH_ASSOC)['username'];
3651 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $usr)) {
3652 $_SESSION['return'][] = array(
3653 'type' => 'danger',
3654 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3655 'msg' => 'access_denied'
3656 );
3657 continue;
3658 }
3659 $stmt = $pdo->prepare("DELETE FROM `sieve_filters` WHERE `id`= :id");
3660 $stmt->execute(array(':id' => $id));
3661 $_SESSION['return'][] = array(
3662 'type' => 'success',
3663 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3664 'msg' => array('delete_filter', $id)
3665 );
3666 }
3667 break;
3668 case 'time_limited_alias':
3669 if (!is_array($_data['address'])) {
3670 $addresses = array();
3671 $addresses[] = $_data['address'];
3672 }
3673 else {
3674 $addresses = $_data['address'];
3675 }
3676 if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) {
3677 $_SESSION['return'][] = array(
3678 'type' => 'danger',
3679 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3680 'msg' => 'access_denied'
3681 );
3682 return false;
3683 }
3684 foreach ($addresses as $address) {
3685 $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address");
3686 $stmt->execute(array(':address' => $address));
3687 $goto = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
3688 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $goto)) {
3689 $_SESSION['return'][] = array(
3690 'type' => 'danger',
3691 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3692 'msg' => 'access_denied'
3693 );
3694 continue;
3695 }
3696 $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username AND `address` = :item");
3697 $stmt->execute(array(
3698 ':username' => $goto,
3699 ':item' => $address
3700 ));
3701 $_SESSION['return'][] = array(
3702 'type' => 'success',
3703 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3704 'msg' => array('mailbox_modified', htmlspecialchars($goto))
3705 );
3706 }
3707 break;
3708 case 'eas_cache':
3709 if (!is_array($_data['username'])) {
3710 $usernames = array();
3711 $usernames[] = $_data['username'];
3712 }
3713 else {
3714 $usernames = $_data['username'];
3715 }
3716 if (!isset($_SESSION['acl']['eas_reset']) || $_SESSION['acl']['eas_reset'] != "1" ) {
3717 $_SESSION['return'][] = array(
3718 'type' => 'danger',
3719 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3720 'msg' => 'access_denied'
3721 );
3722 return false;
3723 }
3724 foreach ($usernames as $username) {
3725 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
3726 $_SESSION['return'][] = array(
3727 'type' => 'danger',
3728 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3729 'msg' => 'access_denied'
3730 );
3731 continue;
3732 }
3733 $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
3734 $stmt->execute(array(
3735 ':username' => $username
3736 ));
3737 $_SESSION['return'][] = array(
3738 'type' => 'success',
3739 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3740 'msg' => array('eas_reset', htmlspecialchars($username))
3741 );
3742 }
3743 break;
3744 case 'sogo_profile':
3745 if (!is_array($_data['username'])) {
3746 $usernames = array();
3747 $usernames[] = $_data['username'];
3748 }
3749 else {
3750 $usernames = $_data['username'];
3751 }
3752 if (!isset($_SESSION['acl']['sogo_profile_reset']) || $_SESSION['acl']['sogo_profile_reset'] != "1" ) {
3753 $_SESSION['return'][] = array(
3754 'type' => 'danger',
3755 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3756 'msg' => 'access_denied'
3757 );
3758 return false;
3759 }
3760 foreach ($usernames as $username) {
3761 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
3762 $_SESSION['return'][] = array(
3763 'type' => 'danger',
3764 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3765 'msg' => 'access_denied'
3766 );
3767 continue;
3768 }
3769 $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
3770 $stmt->execute(array(
3771 ':username' => $username
3772 ));
3773 $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
3774 $stmt->execute(array(
3775 ':username' => $username
3776 ));
3777 $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $username . "/%' OR `c_uid` = :username");
3778 $stmt->execute(array(
3779 ':username' => $username
3780 ));
3781 $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
3782 $stmt->execute(array(
3783 ':username' => $username
3784 ));
3785 $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
3786 $stmt->execute(array(
3787 ':username' => $username
3788 ));
3789 $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
3790 $stmt->execute(array(
3791 ':username' => $username
3792 ));
3793 $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
3794 $stmt->execute(array(
3795 ':username' => $username
3796 ));
3797 $_SESSION['return'][] = array(
3798 'type' => 'success',
3799 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3800 'msg' => array('sogo_profile_reset', htmlspecialchars($username))
3801 );
3802 }
3803 break;
3804 case 'domain':
3805 if (!is_array($_data['domain'])) {
3806 $domains = array();
3807 $domains[] = $_data['domain'];
3808 }
3809 else {
3810 $domains = $_data['domain'];
3811 }
3812 if ($_SESSION['mailcow_cc_role'] != "admin") {
3813 $_SESSION['return'][] = array(
3814 'type' => 'danger',
3815 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3816 'msg' => 'access_denied'
3817 );
3818 return false;
3819 }
3820 foreach ($domains as $domain) {
3821 if (!is_valid_domain_name($domain)) {
3822 $_SESSION['return'][] = array(
3823 'type' => 'danger',
3824 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3825 'msg' => 'domain_invalid'
3826 );
3827 continue;
3828 }
3829 $domain = idn_to_ascii(strtolower(trim($domain)), 0, INTL_IDNA_VARIANT_UTS46);
3830 $stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
3831 WHERE `domain` = :domain");
3832 $stmt->execute(array(':domain' => $domain));
3833 $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
3834 if ($num_results != 0 || !empty($num_results)) {
3835 $_SESSION['return'][] = array(
3836 'type' => 'danger',
3837 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3838 'msg' => array('domain_not_empty', $domain)
3839 );
3840 continue;
3841 }
3842 $exec_fields = array('cmd' => 'maildir', 'task' => 'cleanup', 'maildir' => $domain);
3843 $maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
3844 if ($maildir_gc['type'] != 'success') {
3845 $_SESSION['return'][] = array(
3846 'type' => 'warning',
3847 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3848 'msg' => 'Could not move mail storage to garbage collector: ' . $maildir_gc['msg']
3849 );
3850 }
3851 $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain");
3852 $stmt->execute(array(
3853 ':domain' => $domain,
3854 ));
3855 $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `domain` = :domain");
3856 $stmt->execute(array(
3857 ':domain' => $domain,
3858 ));
3859 $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :domain");
3860 $stmt->execute(array(
3861 ':domain' => $domain,
3862 ));
3863 $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `target_domain` = :domain");
3864 $stmt->execute(array(
3865 ':domain' => $domain,
3866 ));
3867 $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `domain` = :domain");
3868 $stmt->execute(array(
3869 ':domain' => $domain,
3870 ));
3871 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` LIKE :domain");
3872 $stmt->execute(array(
3873 ':domain' => '%@'.$domain,
3874 ));
3875 $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` LIKE :domain");
3876 $stmt->execute(array(
3877 ':domain' => '%@'.$domain,
3878 ));
3879 $stmt = $pdo->prepare("DELETE FROM `pushover` WHERE `username` LIKE :domain");
3880 $stmt->execute(array(
3881 ':domain' => '%@'.$domain,
3882 ));
3883 $stmt = $pdo->prepare("DELETE FROM `quota2replica` WHERE `username` LIKE :domain");
3884 $stmt->execute(array(
3885 ':domain' => '%@'.$domain,
3886 ));
3887 $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` LIKE :domain");
3888 $stmt->execute(array(
3889 ':domain' => '%@'.$domain,
3890 ));
3891 $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain");
3892 $stmt->execute(array(
3893 ':domain' => $domain,
3894 ));
3895 $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain");
3896 $stmt->execute(array(
3897 ':domain' => $domain,
3898 ));
3899 $stmt = $pdo->query("DELETE FROM `admin` WHERE `superadmin` = 0 AND `username` NOT IN (SELECT `username`FROM `domain_admins`);");
3900 $stmt = $pdo->query("DELETE FROM `da_acl` WHERE `username` NOT IN (SELECT `username`FROM `domain_admins`);");
3901 try {
3902 $redis->hDel('DOMAIN_MAP', $domain);
3903 $redis->hDel('RL_VALUE', $domain);
3904 }
3905 catch (RedisException $e) {
3906 $_SESSION['return'][] = array(
3907 'type' => 'danger',
3908 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3909 'msg' => array('redis_error', $e)
3910 );
3911 continue;
3912 }
3913 $_SESSION['return'][] = array(
3914 'type' => 'success',
3915 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3916 'msg' => array('domain_removed', htmlspecialchars($domain))
3917 );
3918 }
3919 break;
3920 case 'alias':
3921 if (!is_array($_data['id'])) {
3922 $ids = array();
3923 $ids[] = $_data['id'];
3924 }
3925 else {
3926 $ids = $_data['id'];
3927 }
3928 foreach ($ids as $id) {
3929 $alias_data = mailbox('get', 'alias_details', $id);
3930 if (empty($alias_data)) {
3931 $_SESSION['return'][] = array(
3932 'type' => 'danger',
3933 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3934 'msg' => 'access_denied'
3935 );
3936 continue;
3937 }
3938 $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `id` = :id");
3939 $stmt->execute(array(
3940 ':id' => $alias_data['id']
3941 ));
3942 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `send_as` = :alias_address");
3943 $stmt->execute(array(
3944 ':alias_address' => $alias_data['address']
3945 ));
3946 $_SESSION['return'][] = array(
3947 'type' => 'success',
3948 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3949 'msg' => array('alias_removed', htmlspecialchars($alias_data['address']))
3950 );
3951 }
3952 break;
3953 case 'alias_domain':
3954 if (!is_array($_data['alias_domain'])) {
3955 $alias_domains = array();
3956 $alias_domains[] = $_data['alias_domain'];
3957 }
3958 else {
3959 $alias_domains = $_data['alias_domain'];
3960 }
3961 foreach ($alias_domains as $alias_domain) {
3962 if (!is_valid_domain_name($alias_domain)) {
3963 $_SESSION['return'][] = array(
3964 'type' => 'danger',
3965 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3966 'msg' => 'domain_invalid'
3967 );
3968 continue;
3969 }
3970 $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
3971 WHERE `alias_domain`= :alias_domain");
3972 $stmt->execute(array(':alias_domain' => $alias_domain));
3973 $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
3974 if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) {
3975 $_SESSION['return'][] = array(
3976 'type' => 'danger',
3977 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
3978 'msg' => 'access_denied'
3979 );
3980 continue;
3981 }
3982 $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `alias_domain` = :alias_domain");
3983 $stmt->execute(array(
3984 ':alias_domain' => $alias_domain,
3985 ));
3986 $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :alias_domain");
3987 $stmt->execute(array(
3988 ':alias_domain' => $alias_domain,
3989 ));
3990 $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :alias_domain");
3991 $stmt->execute(array(
3992 ':alias_domain' => $alias_domain,
3993 ));
3994 try {
3995 $redis->hDel('DOMAIN_MAP', $alias_domain);
3996 $redis->hDel('RL_VALUE', $domain);
3997 }
3998 catch (RedisException $e) {
3999 $_SESSION['return'][] = array(
4000 'type' => 'danger',
4001 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4002 'msg' => array('redis_error', $e)
4003 );
4004 continue;
4005 }
4006 $_SESSION['return'][] = array(
4007 'type' => 'success',
4008 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4009 'msg' => array('alias_domain_removed', htmlspecialchars($alias_domain))
4010 );
4011 }
4012 break;
4013 case 'mailbox':
4014 if (!is_array($_data['username'])) {
4015 $usernames = array();
4016 $usernames[] = $_data['username'];
4017 }
4018 else {
4019 $usernames = $_data['username'];
4020 }
4021 foreach ($usernames as $username) {
4022 if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
4023 $_SESSION['return'][] = array(
4024 'type' => 'danger',
4025 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4026 'msg' => 'access_denied'
4027 );
4028 continue;
4029 }
4030 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
4031 $_SESSION['return'][] = array(
4032 'type' => 'danger',
4033 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4034 'msg' => 'access_denied'
4035 );
4036 continue;
4037 }
4038 $mailbox_details = mailbox('get', 'mailbox_details', $username);
4039 if (!empty($mailbox_details['domain']) && !empty($mailbox_details['local_part'])) {
4040 $maildir = $mailbox_details['domain'] . '/' . $mailbox_details['local_part'];
4041 $exec_fields = array('cmd' => 'maildir', 'task' => 'cleanup', 'maildir' => $maildir);
4042 $maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
4043 if ($maildir_gc['type'] != 'success') {
4044 $_SESSION['return'][] = array(
4045 'type' => 'warning',
4046 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4047 'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg']
4048 );
4049 }
4050 }
4051 else {
4052 $_SESSION['return'][] = array(
4053 'type' => 'warning',
4054 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4055 'msg' => 'Could not move maildir to garbage collector: variables local_part and/or domain empty'
4056 );
4057 }
4058 if (strtolower(getenv('SKIP_SOLR')) == 'n') {
4059 $curl = curl_init();
4060 curl_setopt($curl, CURLOPT_URL, 'http://solr:8983/solr/dovecot-fts/update?commit=true');
4061 curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: text/xml'));
4062 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
4063 curl_setopt($curl, CURLOPT_POST, 1);
4064 curl_setopt($curl, CURLOPT_POSTFIELDS, '<delete><query>user:' . $username . '</query></delete>');
4065 curl_setopt($curl, CURLOPT_TIMEOUT, 30);
4066 $response = curl_exec($curl);
4067 if ($response === false) {
4068 $err = curl_error($curl);
4069 $_SESSION['return'][] = array(
4070 'type' => 'warning',
4071 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4072 'msg' => 'Could not remove Solr index: ' . print_r($err, true)
4073 );
4074 }
4075 curl_close($curl);
4076 }
4077 $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
4078 $stmt->execute(array(
4079 ':username' => $username
4080 ));
4081 $stmt = $pdo->prepare("DELETE FROM `pushover` WHERE `username` = :username");
4082 $stmt->execute(array(
4083 ':username' => $username
4084 ));
4085 $stmt = $pdo->prepare("DELETE FROM `quarantine` WHERE `rcpt` = :username");
4086 $stmt->execute(array(
4087 ':username' => $username
4088 ));
4089 $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :username");
4090 $stmt->execute(array(
4091 ':username' => $username
4092 ));
4093 $stmt = $pdo->prepare("DELETE FROM `quota2replica` WHERE `username` = :username");
4094 $stmt->execute(array(
4095 ':username' => $username
4096 ));
4097 $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
4098 $stmt->execute(array(
4099 ':username' => $username
4100 ));
4101 $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
4102 $stmt->execute(array(
4103 ':username' => $username
4104 ));
4105 // fk, better safe than sorry
4106 $stmt = $pdo->prepare("DELETE FROM `user_acl` WHERE `username` = :username");
4107 $stmt->execute(array(
4108 ':username' => $username
4109 ));
4110 $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
4111 $stmt->execute(array(
4112 ':username' => $username
4113 ));
4114 $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `user2` = :username");
4115 $stmt->execute(array(
4116 ':username' => $username
4117 ));
4118 $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username");
4119 $stmt->execute(array(
4120 ':username' => $username
4121 ));
4122 $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
4123 $stmt->execute(array(
4124 ':username' => $username
4125 ));
4126 $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
4127 $stmt->execute(array(
4128 ':username' => $username
4129 ));
4130 $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . str_replace('%', '\%', $username) . "/%' OR `c_uid` = :username");
4131 $stmt->execute(array(
4132 ':username' => $username
4133 ));
4134 $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
4135 $stmt->execute(array(
4136 ':username' => $username
4137 ));
4138 $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
4139 $stmt->execute(array(
4140 ':username' => $username
4141 ));
4142 $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
4143 $stmt->execute(array(
4144 ':username' => $username
4145 ));
4146 $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
4147 $stmt->execute(array(
4148 ':username' => $username
4149 ));
4150 $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :username");
4151 $stmt->execute(array(
4152 ':username' => $username
4153 ));
4154 $stmt = $pdo->prepare("DELETE FROM `oauth_access_tokens` WHERE `user_id` = :username");
4155 $stmt->execute(array(
4156 ':username' => $username
4157 ));
4158 $stmt = $pdo->prepare("DELETE FROM `oauth_refresh_tokens` WHERE `user_id` = :username");
4159 $stmt->execute(array(
4160 ':username' => $username
4161 ));
4162 $stmt = $pdo->prepare("DELETE FROM `oauth_authorization_codes` WHERE `user_id` = :username");
4163 $stmt->execute(array(
4164 ':username' => $username
4165 ));
4166 $stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
4167 WHERE `goto` REGEXP :username");
4168 $stmt->execute(array(':username' => '(^|,)'.$username.'($|,)'));
4169 $GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC);
4170 foreach ($GotoData as $gotos) {
4171 $goto_exploded = explode(',', $gotos['goto']);
4172 if (($key = array_search($username, $goto_exploded)) !== false) {
4173 unset($goto_exploded[$key]);
4174 }
4175 $gotos_rebuild = implode(',', $goto_exploded);
4176 $stmt = $pdo->prepare("UPDATE `alias` SET
4177 `goto` = :goto
4178 WHERE `address` = :address");
4179 $stmt->execute(array(
4180 ':goto' => $gotos_rebuild,
4181 ':address' => $gotos['address']
4182 ));
4183 }
4184 try {
4185 $redis->hDel('RL_VALUE', $username);
4186 }
4187 catch (RedisException $e) {
4188 $_SESSION['return'][] = array(
4189 'type' => 'danger',
4190 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4191 'msg' => array('redis_error', $e)
4192 );
4193 continue;
4194 }
4195 $_SESSION['return'][] = array(
4196 'type' => 'success',
4197 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4198 'msg' => array('mailbox_removed', htmlspecialchars($username))
4199 );
4200 }
4201 break;
4202 case 'resource':
4203 if (!is_array($_data['name'])) {
4204 $names = array();
4205 $names[] = $_data['name'];
4206 }
4207 else {
4208 $names = $_data['name'];
4209 }
4210 foreach ($names as $name) {
4211 if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
4212 $_SESSION['return'][] = array(
4213 'type' => 'danger',
4214 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4215 'msg' => 'access_denied'
4216 );
4217 continue;
4218 }
4219 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) {
4220 $_SESSION['return'][] = array(
4221 'type' => 'danger',
4222 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4223 'msg' => 'access_denied'
4224 );
4225 continue;
4226 }
4227 $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
4228 $stmt->execute(array(
4229 ':username' => $name
4230 ));
4231 $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
4232 $stmt->execute(array(
4233 ':username' => $name
4234 ));
4235 $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
4236 $stmt->execute(array(
4237 ':username' => $name
4238 ));
4239 $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $name . "/%' OR `c_uid` = :username");
4240 $stmt->execute(array(
4241 ':username' => $name
4242 ));
4243 $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
4244 $stmt->execute(array(
4245 ':username' => $name
4246 ));
4247 $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
4248 $stmt->execute(array(
4249 ':username' => $name
4250 ));
4251 $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
4252 $stmt->execute(array(
4253 ':username' => $name
4254 ));
4255 $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
4256 $stmt->execute(array(
4257 ':username' => $name
4258 ));
4259 $_SESSION['return'][] = array(
4260 'type' => 'success',
4261 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
4262 'msg' => array('resource_removed', htmlspecialchars($name))
4263 );
4264 }
4265 break;
4266 }
4267 break;
4268 }
4269 if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource'))) {
4270 update_sogo_static_view();
4271 }
4272}