functions.address_rewriting.inc.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  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. if (!filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) {
  137. $_SESSION['return'][] = array(
  138. 'type' => 'danger',
  139. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  140. 'msg' => array('bcc_must_be_email', $bcc_dest)
  141. );
  142. continue;
  143. }
  144. if (empty($bcc_dest)) {
  145. $_SESSION['return'][] = array(
  146. 'type' => 'danger',
  147. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  148. 'msg' => array('bcc_must_be_email', $bcc_dest)
  149. );
  150. continue;
  151. }
  152. $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps`
  153. WHERE `local_dest` = :local_dest AND `type` = :type");
  154. $stmt->execute(array(':local_dest' => $local_dest, ':type' => $type));
  155. $id_now = $stmt->fetch(PDO::FETCH_ASSOC)['id'];
  156. if (isset($id_now) && $id_now != $id) {
  157. $_SESSION['return'][] = array(
  158. 'type' => 'danger',
  159. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  160. 'msg' => array('bcc_exists', htmlspecialchars($local_dest), $type)
  161. );
  162. continue;
  163. }
  164. $stmt = $pdo->prepare("UPDATE `bcc_maps` SET `bcc_dest` = :bcc_dest, `active` = :active, `type` = :type WHERE `id`= :id");
  165. $stmt->execute(array(
  166. ':bcc_dest' => $bcc_dest,
  167. ':active' => $active,
  168. ':type' => $type,
  169. ':id' => $id
  170. ));
  171. $_SESSION['return'][] = array(
  172. 'type' => 'success',
  173. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  174. 'msg' => array('bcc_edited', $bcc_dest)
  175. );
  176. }
  177. break;
  178. case 'details':
  179. $bccdata = array();
  180. $id = intval($_data);
  181. $stmt = $pdo->prepare("SELECT `id`,
  182. `local_dest`,
  183. `bcc_dest`,
  184. `active`,
  185. `type`,
  186. `created`,
  187. `domain`,
  188. `modified` FROM `bcc_maps`
  189. WHERE `id` = :id");
  190. $stmt->execute(array(':id' => $id));
  191. $bccdata = $stmt->fetch(PDO::FETCH_ASSOC);
  192. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $bccdata['domain'])) {
  193. $bccdata = null;
  194. return false;
  195. }
  196. return $bccdata;
  197. break;
  198. case 'get':
  199. $bccdata = array();
  200. $all_items = array();
  201. $id = intval($_data);
  202. $stmt = $pdo->query("SELECT `id`, `domain` FROM `bcc_maps`");
  203. $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
  204. foreach ($all_items as $i) {
  205. if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $i['domain'])) {
  206. $bccdata[] = $i['id'];
  207. }
  208. }
  209. $all_items = null;
  210. return $bccdata;
  211. break;
  212. case 'delete':
  213. if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
  214. $_SESSION['return'][] = array(
  215. 'type' => 'danger',
  216. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  217. 'msg' => 'access_denied'
  218. );
  219. return false;
  220. }
  221. $ids = (array)$_data['id'];
  222. foreach ($ids as $id) {
  223. if (!is_numeric($id)) {
  224. return false;
  225. }
  226. $stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id");
  227. $stmt->execute(array(':id' => $id));
  228. $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain'];
  229. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  230. $_SESSION['return'][] = array(
  231. 'type' => 'danger',
  232. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  233. 'msg' => 'access_denied'
  234. );
  235. continue;
  236. }
  237. $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `id`= :id");
  238. $stmt->execute(array(':id' => $id));
  239. $_SESSION['return'][] = array(
  240. 'type' => 'success',
  241. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  242. 'msg' => array('bcc_deleted', $id)
  243. );
  244. }
  245. break;
  246. }
  247. }
  248. function recipient_map($_action, $_data = null, $attr = null) {
  249. global $pdo;
  250. global $lang;
  251. if ($_SESSION['mailcow_cc_role'] != "admin") {
  252. return false;
  253. }
  254. switch ($_action) {
  255. case 'add':
  256. $old_dest = strtolower(trim($_data['recipient_map_old']));
  257. if (substr($old_dest, 0, 1) == '@') {
  258. $old_dest = substr($old_dest, 1);
  259. }
  260. $new_dest = strtolower(trim($_data['recipient_map_new']));
  261. $active = intval($_data['active']);
  262. if (is_valid_domain_name($old_dest)) {
  263. $old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
  264. }
  265. elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
  266. $old_dest_sane = $old_dest;
  267. }
  268. else {
  269. $_SESSION['return'][] = array(
  270. 'type' => 'danger',
  271. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  272. 'msg' => array('invalid_recipient_map_old', htmlspecialchars($old_dest))
  273. );
  274. return false;
  275. }
  276. if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
  277. $_SESSION['return'][] = array(
  278. 'type' => 'danger',
  279. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  280. 'msg' => array('invalid_recipient_map_new', htmlspecialchars($new_dest))
  281. );
  282. return false;
  283. }
  284. $rmaps = recipient_map('get');
  285. foreach ($rmaps as $rmap) {
  286. if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) {
  287. $_SESSION['return'][] = array(
  288. 'type' => 'danger',
  289. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  290. 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane))
  291. );
  292. return false;
  293. }
  294. }
  295. $stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES
  296. (:old_dest, :new_dest, :active)");
  297. $stmt->execute(array(
  298. ':old_dest' => $old_dest_sane,
  299. ':new_dest' => $new_dest,
  300. ':active' => $active
  301. ));
  302. $_SESSION['return'][] = array(
  303. 'type' => 'success',
  304. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  305. 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest_sane))
  306. );
  307. break;
  308. case 'edit':
  309. $ids = (array)$_data['id'];
  310. foreach ($ids as $id) {
  311. $is_now = recipient_map('details', $id);
  312. if (!empty($is_now)) {
  313. $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
  314. $new_dest = (!empty($_data['recipient_map_new'])) ? $_data['recipient_map_new'] : $is_now['recipient_map_new'];
  315. $old_dest = (!empty($_data['recipient_map_old'])) ? $_data['recipient_map_old'] : $is_now['recipient_map_old'];
  316. if (substr($old_dest, 0, 1) == '@') {
  317. $old_dest = substr($old_dest, 1);
  318. }
  319. }
  320. else {
  321. $_SESSION['return'][] = array(
  322. 'type' => 'danger',
  323. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  324. 'msg' => 'access_denied'
  325. );
  326. continue;
  327. }
  328. if (is_valid_domain_name($old_dest)) {
  329. $old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
  330. }
  331. elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
  332. $old_dest_sane = $old_dest;
  333. }
  334. else {
  335. $_SESSION['return'][] = array(
  336. 'type' => 'danger',
  337. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  338. 'msg' => array('invalid_recipient_map_old', htmlspecialchars($old_dest))
  339. );
  340. continue;
  341. }
  342. if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
  343. $_SESSION['return'][] = array(
  344. 'type' => 'danger',
  345. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  346. 'msg' => array('invalid_recipient_map_new', htmlspecialchars($new_dest))
  347. );
  348. continue;
  349. }
  350. $rmaps = recipient_map('get');
  351. foreach ($rmaps as $rmap) {
  352. if ($rmap == $id) { continue; }
  353. if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) {
  354. $_SESSION['return'][] = array(
  355. 'type' => 'danger',
  356. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  357. 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane))
  358. );
  359. return false;
  360. }
  361. }
  362. $stmt = $pdo->prepare("UPDATE `recipient_maps` SET
  363. `old_dest` = :old_dest,
  364. `new_dest` = :new_dest,
  365. `active` = :active
  366. WHERE `id`= :id");
  367. $stmt->execute(array(
  368. ':old_dest' => $old_dest_sane,
  369. ':new_dest' => $new_dest,
  370. ':active' => $active,
  371. ':id' => $id
  372. ));
  373. $_SESSION['return'][] = array(
  374. 'type' => 'success',
  375. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  376. 'msg' => array('recipient_map_entry_saved', htmlspecialchars($old_dest_sane))
  377. );
  378. }
  379. break;
  380. case 'details':
  381. $mapdata = array();
  382. $id = intval($_data);
  383. $stmt = $pdo->prepare("SELECT `id`,
  384. `old_dest` AS `recipient_map_old`,
  385. `new_dest` AS `recipient_map_new`,
  386. `active`,
  387. `created`,
  388. `modified` FROM `recipient_maps`
  389. WHERE `id` = :id");
  390. $stmt->execute(array(':id' => $id));
  391. $mapdata = $stmt->fetch(PDO::FETCH_ASSOC);
  392. return $mapdata;
  393. break;
  394. case 'get':
  395. $mapdata = array();
  396. $all_items = array();
  397. $id = intval($_data);
  398. $stmt = $pdo->query("SELECT `id` FROM `recipient_maps`");
  399. $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
  400. foreach ($all_items as $i) {
  401. $mapdata[] = $i['id'];
  402. }
  403. $all_items = null;
  404. return $mapdata;
  405. break;
  406. case 'delete':
  407. $ids = (array)$_data['id'];
  408. foreach ($ids as $id) {
  409. if (!is_numeric($id)) {
  410. return false;
  411. }
  412. $stmt = $pdo->prepare("DELETE FROM `recipient_maps` WHERE `id`= :id");
  413. $stmt->execute(array(':id' => $id));
  414. $_SESSION['return'][] = array(
  415. 'type' => 'success',
  416. 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
  417. 'msg' => array('recipient_map_entry_deleted', htmlspecialchars($id))
  418. );
  419. }
  420. break;
  421. }
  422. }