functions.address_rewriting.inc.php 16 KB

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