functions.inc.php 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575
  1. <?php
  2. function hash_password($password) {
  3. $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
  4. return "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str);
  5. }
  6. function hasDomainAccess($username, $role, $domain) {
  7. global $pdo;
  8. if (!filter_var($username, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
  9. return false;
  10. }
  11. if (!is_valid_domain_name($domain)) {
  12. return false;
  13. }
  14. try {
  15. $stmt = $pdo->prepare("SELECT `domain` FROM `domain_admins`
  16. WHERE (
  17. `active`='1'
  18. AND `username` = :username
  19. AND `domain` = :domain
  20. )
  21. OR 'admin' = :role");
  22. $stmt->execute(array(':username' => $username, ':domain' => $domain, ':role' => $role));
  23. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  24. } catch(PDOException $e) {
  25. error_log($e);
  26. return false;
  27. }
  28. if ($num_results != 0 && !empty($num_results)) {
  29. return true;
  30. }
  31. return false;
  32. }
  33. function verify_ssha256($hash, $password) {
  34. // Remove tag if any
  35. $hash = ltrim($hash, '{SSHA256}');
  36. // Decode hash
  37. $dhash = base64_decode($hash);
  38. // Get first 32 bytes of binary which equals a SHA256 hash
  39. $ohash = substr($dhash, 0, 32);
  40. // Remove SHA256 hash from decoded hash to get original salt string
  41. $osalt = str_replace($ohash, '', $dhash);
  42. // Check single salted SHA256 hash against extracted hash
  43. if (hash('sha256', $password . $osalt, true) == $ohash) {
  44. return true;
  45. }
  46. else {
  47. return false;
  48. }
  49. }
  50. function doveadm_authenticate($hash, $algorithm, $password) {
  51. $descr = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
  52. $pipes = array();
  53. $process = proc_open("/usr/bin/doveadm pw -s ".$algorithm." -t '".$hash."'", $descr, $pipes);
  54. if (is_resource($process)) {
  55. fputs($pipes[0], $password);
  56. fclose($pipes[0]);
  57. while ($f = fgets($pipes[1])) {
  58. if (preg_match('/(verified)/', $f)) {
  59. proc_close($process);
  60. return true;
  61. }
  62. return false;
  63. }
  64. fclose($pipes[1]);
  65. while ($f = fgets($pipes[2])) {
  66. proc_close($process);
  67. return false;
  68. }
  69. fclose($pipes[2]);
  70. proc_close($process);
  71. }
  72. return false;
  73. }
  74. function check_login($user, $pass) {
  75. global $pdo;
  76. if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
  77. return false;
  78. }
  79. $user = strtolower(trim($user));
  80. $stmt = $pdo->prepare("SELECT `password` FROM `admin`
  81. WHERE `superadmin` = '1'
  82. AND `username` = :user");
  83. $stmt->execute(array(':user' => $user));
  84. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  85. foreach ($rows as $row) {
  86. if (verify_ssha256($row['password'], $pass) !== false) {
  87. unset($_SESSION['ldelay']);
  88. return "admin";
  89. }
  90. }
  91. $stmt = $pdo->prepare("SELECT `password` FROM `admin`
  92. WHERE `superadmin` = '0'
  93. AND `active`='1'
  94. AND `username` = :user");
  95. $stmt->execute(array(':user' => $user));
  96. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  97. foreach ($rows as $row) {
  98. if (verify_ssha256($row['password'], $pass) !== false) {
  99. unset($_SESSION['ldelay']);
  100. return "domainadmin";
  101. }
  102. }
  103. $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
  104. WHERE `active`='1'
  105. AND `username` = :user");
  106. $stmt->execute(array(':user' => $user));
  107. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  108. foreach ($rows as $row) {
  109. if (verify_ssha256($row['password'], $pass) !== false) {
  110. unset($_SESSION['ldelay']);
  111. return "user";
  112. }
  113. }
  114. if (!isset($_SESSION['ldelay'])) {
  115. $_SESSION['ldelay'] = "0";
  116. }
  117. elseif (!isset($_SESSION['mailcow_cc_username'])) {
  118. $_SESSION['ldelay'] = $_SESSION['ldelay']+0.5;
  119. }
  120. sleep($_SESSION['ldelay']);
  121. }
  122. function formatBytes($size, $precision = 2) {
  123. if(!is_numeric($size)) {
  124. return "0";
  125. }
  126. $base = log($size, 1024);
  127. $suffixes = array(' Byte', ' KiB', ' MiB', ' GiB', ' TiB');
  128. if ($size == "0") {
  129. return "0";
  130. }
  131. return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
  132. }
  133. function dkim_table($action, $item) {
  134. global $lang;
  135. switch ($action) {
  136. case "delete":
  137. $domain = preg_replace('/[^A-Za-z0-9._\-]/', '_', $item['dkim']['domain']);
  138. $selector = preg_replace('/[^A-Za-z0-9._\-]/', '_', $item['dkim']['selector']);
  139. if (!ctype_alnum($selector) || !is_valid_domain_name($domain)) {
  140. $_SESSION['return'] = array(
  141. 'type' => 'danger',
  142. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  143. );
  144. break;
  145. }
  146. exec('rm ' . escapeshellarg($GLOBALS['MC_DKIM_TXTS'] . '/' . $selector . '_' . $domain), $out, $return);
  147. if ($return != "0") {
  148. $_SESSION['return'] = array(
  149. 'type' => 'danger',
  150. 'msg' => sprintf($lang['danger']['dkim_remove_failed'])
  151. );
  152. break;
  153. }
  154. exec('rm ' . escapeshellarg($GLOBALS['MC_DKIM_KEYS'] . '/' . $domain . '.' . $selector), $out, $return);
  155. if ($return != "0") {
  156. $_SESSION['return'] = array(
  157. 'type' => 'danger',
  158. 'msg' => sprintf($lang['danger']['dkim_remove_failed'])
  159. );
  160. break;
  161. }
  162. $_SESSION['return'] = array(
  163. 'type' => 'success',
  164. 'msg' => sprintf($lang['success']['dkim_removed'])
  165. );
  166. break;
  167. case "add":
  168. $domain = preg_replace('/[^A-Za-z0-9._\-]/', '_', $item['dkim']['domain']);
  169. $selector = preg_replace('/[^A-Za-z0-9._\-]/', '_', $item['dkim']['selector']);
  170. $key_length = intval($item['dkim']['key_size']);
  171. if (!ctype_alnum($selector) || !is_valid_domain_name($domain) || !is_numeric($key_length)) {
  172. $_SESSION['return'] = array(
  173. 'type' => 'danger',
  174. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  175. );
  176. break;
  177. }
  178. if (file_exists($GLOBALS['MC_DKIM_TXTS'] . '/' . $selector . '_' . $domain) ||
  179. file_exists($GLOBALS['MC_DKIM_KEYS'] . '/' . $domain . '.' . $selector)) {
  180. $_SESSION['return'] = array(
  181. 'type' => 'danger',
  182. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  183. );
  184. break;
  185. }
  186. $config = array(
  187. "digest_alg" => "sha256",
  188. "private_key_bits" => $key_length,
  189. "private_key_type" => OPENSSL_KEYTYPE_RSA,
  190. );
  191. $keypair_ressource = openssl_pkey_new($config);
  192. $key_details = openssl_pkey_get_details($keypair_ressource);
  193. $pubKey = implode(array_slice(
  194. array_filter(
  195. explode(PHP_EOL, $key_details['key'])
  196. ), 1, -1)
  197. );
  198. // Save public key to file
  199. file_put_contents($GLOBALS['MC_DKIM_TXTS'] . '/' . $selector . '_' . $domain, $pubKey);
  200. // Save private key to file
  201. openssl_pkey_export_to_file($keypair_ressource, $GLOBALS['MC_DKIM_KEYS'] . '/' . $domain . '.' . $selector);
  202. $_SESSION['return'] = array(
  203. 'type' => 'success',
  204. 'msg' => sprintf($lang['success']['dkim_added'])
  205. );
  206. break;
  207. }
  208. }
  209. function mailbox_add_domain($postarray) {
  210. global $pdo;
  211. global $lang;
  212. if ($_SESSION['mailcow_cc_role'] != "admin") {
  213. $_SESSION['return'] = array(
  214. 'type' => 'danger',
  215. 'msg' => sprintf($lang['danger']['access_denied'])
  216. );
  217. return false;
  218. }
  219. $domain = idn_to_ascii(strtolower(trim($postarray['domain'])));
  220. $description = $postarray['description'];
  221. $aliases = $postarray['aliases'];
  222. $mailboxes = $postarray['mailboxes'];
  223. $maxquota = $postarray['maxquota'];
  224. $quota = $postarray['quota'];
  225. if ($maxquota > $quota) {
  226. $_SESSION['return'] = array(
  227. 'type' => 'danger',
  228. 'msg' => sprintf($lang['danger']['mailbox_quota_exceeds_domain_quota'])
  229. );
  230. return false;
  231. }
  232. isset($postarray['active']) ? $active = '1' : $active = '0';
  233. isset($postarray['relay_all_recipients']) ? $relay_all_recipients = '1' : $relay_all_recipients = '0';
  234. isset($postarray['backupmx']) ? $backupmx = '1' : $backupmx = '0';
  235. isset($postarray['relay_all_recipients']) ? $backupmx = '1' : true;
  236. if (!is_valid_domain_name($domain)) {
  237. $_SESSION['return'] = array(
  238. 'type' => 'danger',
  239. 'msg' => sprintf($lang['danger']['domain_invalid'])
  240. );
  241. return false;
  242. }
  243. foreach (array($quota, $maxquota, $mailboxes, $aliases) as $data) {
  244. if (!is_numeric($data)) {
  245. $_SESSION['return'] = array(
  246. 'type' => 'danger',
  247. 'msg' => sprintf($lang['danger']['object_is_not_numeric'], htmlspecialchars($data))
  248. );
  249. return false;
  250. }
  251. }
  252. try {
  253. $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
  254. WHERE `domain` = :domain");
  255. $stmt->execute(array(':domain' => $domain));
  256. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  257. }
  258. catch(PDOException $e) {
  259. $_SESSION['return'] = array(
  260. 'type' => 'danger',
  261. 'msg' => 'MySQL: '.$e
  262. );
  263. return false;
  264. }
  265. if ($num_results != 0) {
  266. $_SESSION['return'] = array(
  267. 'type' => 'danger',
  268. 'msg' => sprintf($lang['danger']['domain_exists'], htmlspecialchars($domain))
  269. );
  270. return false;
  271. }
  272. try {
  273. $stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `maxquota`, `quota`, `transport`, `backupmx`, `created`, `modified`, `active`, `relay_all_recipients`)
  274. VALUES (:domain, :description, :aliases, :mailboxes, :maxquota, :quota, 'virtual', :backupmx, :created, :modified, :active, :relay_all_recipients)");
  275. $stmt->execute(array(
  276. ':domain' => $domain,
  277. ':description' => $description,
  278. ':aliases' => $aliases,
  279. ':mailboxes' => $mailboxes,
  280. ':maxquota' => $maxquota,
  281. ':quota' => $quota,
  282. ':backupmx' => $backupmx,
  283. ':active' => $active,
  284. ':created' => date('Y-m-d H:i:s'),
  285. ':modified' => date('Y-m-d H:i:s'),
  286. ':relay_all_recipients' => $relay_all_recipients
  287. ));
  288. $_SESSION['return'] = array(
  289. 'type' => 'success',
  290. 'msg' => sprintf($lang['success']['domain_added'], htmlspecialchars($domain))
  291. );
  292. }
  293. catch (PDOException $e) {
  294. $_SESSION['return'] = array(
  295. 'type' => 'danger',
  296. 'msg' => 'MySQL: '.$e
  297. );
  298. return false;
  299. }
  300. }
  301. function mailbox_add_alias($postarray) {
  302. global $lang;
  303. global $pdo;
  304. $addresses = array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['address']));
  305. $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['goto']));
  306. isset($postarray['active']) ? $active = '1' : $active = '0';
  307. if (empty($addresses[0])) {
  308. $_SESSION['return'] = array(
  309. 'type' => 'danger',
  310. 'msg' => sprintf($lang['danger']['alias_empty'])
  311. );
  312. return false;
  313. }
  314. if (empty($gotos[0])) {
  315. $_SESSION['return'] = array(
  316. 'type' => 'danger',
  317. 'msg' => sprintf($lang['danger']['goto_empty'])
  318. );
  319. return false;
  320. }
  321. foreach ($addresses as $address) {
  322. if (empty($address)) {
  323. continue;
  324. }
  325. $domain = idn_to_ascii(substr(strstr($address, '@'), 1));
  326. $local_part = strstr($address, '@', true);
  327. $address = $local_part.'@'.$domain;
  328. if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) {
  329. $_SESSION['return'] = array(
  330. 'type' => 'danger',
  331. 'msg' => sprintf($lang['danger']['alias_invalid'])
  332. );
  333. return false;
  334. }
  335. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  336. $_SESSION['return'] = array(
  337. 'type' => 'danger',
  338. 'msg' => sprintf($lang['danger']['access_denied'])
  339. );
  340. return false;
  341. }
  342. try {
  343. $stmt = $pdo->prepare("SELECT `address` FROM `alias`
  344. WHERE `address`= :address");
  345. $stmt->execute(array(':address' => $address));
  346. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  347. }
  348. catch(PDOException $e) {
  349. $_SESSION['return'] = array(
  350. 'type' => 'danger',
  351. 'msg' => 'MySQL: '.$e
  352. );
  353. return false;
  354. }
  355. if ($num_results != 0) {
  356. $_SESSION['return'] = array(
  357. 'type' => 'danger',
  358. 'msg' => sprintf($lang['danger']['is_alias_or_mailbox'], htmlspecialchars($address))
  359. );
  360. return false;
  361. }
  362. try {
  363. $stmt = $pdo->prepare("SELECT `address` FROM `spamalias`
  364. WHERE `address`= :address");
  365. $stmt->execute(array(':address' => $address));
  366. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  367. }
  368. catch(PDOException $e) {
  369. $_SESSION['return'] = array(
  370. 'type' => 'danger',
  371. 'msg' => 'MySQL: '.$e
  372. );
  373. return false;
  374. }
  375. if ($num_results != 0) {
  376. $_SESSION['return'] = array(
  377. 'type' => 'danger',
  378. 'msg' => sprintf($lang['danger']['is_spam_alias'], htmlspecialchars($address))
  379. );
  380. return false;
  381. }
  382. foreach ($gotos as &$goto) {
  383. if (empty($goto)) {
  384. continue;
  385. }
  386. $goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1));
  387. $goto_local_part = strstr($goto, '@', true);
  388. $goto = $goto_local_part.'@'.$goto_domain;
  389. if (!filter_var($goto, FILTER_VALIDATE_EMAIL) === true) {
  390. $_SESSION['return'] = array(
  391. 'type' => 'danger',
  392. 'msg' => sprintf($lang['danger']['goto_invalid'])
  393. );
  394. return false;
  395. }
  396. if ($goto == $address) {
  397. $_SESSION['return'] = array(
  398. 'type' => 'danger',
  399. 'msg' => sprintf($lang['danger']['alias_goto_identical'])
  400. );
  401. return false;
  402. }
  403. }
  404. $gotos = array_filter($gotos);
  405. $goto = implode(",", $gotos);
  406. try {
  407. $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `created`, `modified`, `active`)
  408. VALUES (:address, :goto, :domain, :created, :modified, :active)");
  409. if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) {
  410. $stmt->execute(array(
  411. ':address' => '@'.$domain,
  412. ':goto' => $goto,
  413. ':domain' => $domain,
  414. ':created' => date('Y-m-d H:i:s'),
  415. ':modified' => date('Y-m-d H:i:s'),
  416. ':active' => $active
  417. ));
  418. }
  419. else {
  420. $stmt->execute(array(
  421. ':address' => $address,
  422. ':goto' => $goto,
  423. ':domain' => $domain,
  424. ':created' => date('Y-m-d H:i:s'),
  425. ':modified' => date('Y-m-d H:i:s'),
  426. ':active' => $active
  427. ));
  428. }
  429. $_SESSION['return'] = array(
  430. 'type' => 'success',
  431. 'msg' => sprintf($lang['success']['alias_added'])
  432. );
  433. }
  434. catch (PDOException $e) {
  435. $_SESSION['return'] = array(
  436. 'type' => 'danger',
  437. 'msg' => 'MySQL: '.$e
  438. );
  439. return false;
  440. }
  441. }
  442. $_SESSION['return'] = array(
  443. 'type' => 'success',
  444. 'msg' => sprintf($lang['success']['alias_added'])
  445. );
  446. }
  447. function mailbox_add_alias_domain($postarray) {
  448. global $lang;
  449. global $pdo;
  450. isset($postarray['active']) ? $active = '1' : $active = '0';
  451. if (!is_valid_domain_name($postarray['alias_domain'])) {
  452. $_SESSION['return'] = array(
  453. 'type' => 'danger',
  454. 'msg' => sprintf($lang['danger']['alias_domain_invalid'])
  455. );
  456. return false;
  457. }
  458. if (!is_valid_domain_name($postarray['target_domain'])) {
  459. $_SESSION['return'] = array(
  460. 'type' => 'danger',
  461. 'msg' => sprintf($lang['danger']['target_domain_invalid'])
  462. );
  463. return false;
  464. }
  465. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['target_domain'])) {
  466. $_SESSION['return'] = array(
  467. 'type' => 'danger',
  468. 'msg' => sprintf($lang['danger']['access_denied'])
  469. );
  470. return false;
  471. }
  472. if ($postarray['alias_domain'] == $postarray['target_domain']) {
  473. $_SESSION['return'] = array(
  474. 'type' => 'danger',
  475. 'msg' => sprintf($lang['danger']['aliasd_targetd_identical'])
  476. );
  477. return false;
  478. }
  479. $alias_domain = strtolower(trim($postarray['alias_domain']));
  480. $target_domain = strtolower(trim($postarray['target_domain']));
  481. try {
  482. $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
  483. WHERE `domain`= :target_domain");
  484. $stmt->execute(array(':target_domain' => $target_domain));
  485. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  486. }
  487. catch(PDOException $e) {
  488. $_SESSION['return'] = array(
  489. 'type' => 'danger',
  490. 'msg' => 'MySQL: '.$e
  491. );
  492. return false;
  493. }
  494. if ($num_results == 0) {
  495. $_SESSION['return'] = array(
  496. 'type' => 'danger',
  497. 'msg' => sprintf($lang['danger']['targetd_not_found'])
  498. );
  499. return false;
  500. }
  501. try {
  502. $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain`= :alias_domain
  503. UNION
  504. SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain`= :alias_domain_in_domain");
  505. $stmt->execute(array(':alias_domain' => $alias_domain, ':alias_domain_in_domain' => $alias_domain));
  506. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  507. }
  508. catch(PDOException $e) {
  509. $_SESSION['return'] = array(
  510. 'type' => 'danger',
  511. 'msg' => 'MySQL: '.$e
  512. );
  513. return false;
  514. }
  515. if ($num_results != 0) {
  516. $_SESSION['return'] = array(
  517. 'type' => 'danger',
  518. 'msg' => sprintf($lang['danger']['aliasd_exists'])
  519. );
  520. return false;
  521. }
  522. try {
  523. $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `created`, `modified`, `active`)
  524. VALUES (:alias_domain, :target_domain, :created, :modified, :active)");
  525. $stmt->execute(array(
  526. ':alias_domain' => $alias_domain,
  527. ':target_domain' => $target_domain,
  528. ':created' => date('Y-m-d H:i:s'),
  529. ':modified' => date('Y-m-d H:i:s'),
  530. ':active' => $active
  531. ));
  532. $_SESSION['return'] = array(
  533. 'type' => 'success',
  534. 'msg' => sprintf($lang['success']['aliasd_added'], htmlspecialchars($alias_domain))
  535. );
  536. }
  537. catch (PDOException $e) {
  538. $_SESSION['return'] = array(
  539. 'type' => 'danger',
  540. 'msg' => 'MySQL: '.$e
  541. );
  542. return false;
  543. }
  544. }
  545. function mailbox_edit_alias_domain($postarray) {
  546. global $lang;
  547. global $pdo;
  548. isset($postarray['active']) ? $active = '1' : $active = '0';
  549. $alias_domain = idn_to_ascii($postarray['alias_domain']);
  550. $alias_domain = strtolower(trim($alias_domain));
  551. $alias_domain_now = strtolower(trim($postarray['alias_domain_now']));
  552. if (!is_valid_domain_name($alias_domain)) {
  553. $_SESSION['return'] = array(
  554. 'type' => 'danger',
  555. 'msg' => sprintf($lang['danger']['alias_domain_invalid'])
  556. );
  557. return false;
  558. }
  559. if (!is_valid_domain_name($alias_domain_now)) {
  560. $_SESSION['return'] = array(
  561. 'type' => 'danger',
  562. 'msg' => sprintf($lang['danger']['alias_domain_invalid'])
  563. );
  564. return false;
  565. }
  566. try {
  567. $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
  568. WHERE `alias_domain`= :alias_domain_now");
  569. $stmt->execute(array(':alias_domain_now' => $alias_domain_now));
  570. $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
  571. }
  572. catch(PDOException $e) {
  573. $_SESSION['return'] = array(
  574. 'type' => 'danger',
  575. 'msg' => 'MySQL: '.$e
  576. );
  577. return false;
  578. }
  579. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) {
  580. $_SESSION['return'] = array(
  581. 'type' => 'danger',
  582. 'msg' => sprintf($lang['danger']['access_denied'])
  583. );
  584. return false;
  585. }
  586. try {
  587. $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
  588. WHERE `target_domain`= :alias_domain");
  589. $stmt->execute(array(':alias_domain' => $alias_domain));
  590. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  591. }
  592. catch(PDOException $e) {
  593. $_SESSION['return'] = array(
  594. 'type' => 'danger',
  595. 'msg' => 'MySQL: '.$e
  596. );
  597. return false;
  598. }
  599. if ($num_results != 0) {
  600. $_SESSION['return'] = array(
  601. 'type' => 'danger',
  602. 'msg' => sprintf($lang['danger']['aliasd_targetd_identical'])
  603. );
  604. return false;
  605. }
  606. try {
  607. $stmt = $pdo->prepare("UPDATE `alias_domain` SET `alias_domain` = :alias_domain, `active` = :active WHERE `alias_domain` = :alias_domain_now");
  608. $stmt->execute(array(
  609. ':alias_domain' => $alias_domain,
  610. ':alias_domain_now' => $alias_domain_now,
  611. ':active' => $active
  612. ));
  613. }
  614. catch (PDOException $e) {
  615. $_SESSION['return'] = array(
  616. 'type' => 'danger',
  617. 'msg' => 'MySQL: '.$e
  618. );
  619. return false;
  620. }
  621. $_SESSION['return'] = array(
  622. 'type' => 'success',
  623. 'msg' => sprintf($lang['success']['aliasd_modified'], htmlspecialchars($alias_domain))
  624. );
  625. }
  626. function mailbox_add_mailbox($postarray) {
  627. global $pdo;
  628. global $lang;
  629. $username = strtolower(trim($postarray['local_part'])).'@'.strtolower(trim($postarray['domain']));
  630. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  631. $_SESSION['return'] = array(
  632. 'type' => 'danger',
  633. 'msg' => sprintf($lang['danger']['mailbox_invalid'])
  634. );
  635. return false;
  636. }
  637. if (empty($postarray['local_part'])) {
  638. $_SESSION['return'] = array(
  639. 'type' => 'danger',
  640. 'msg' => sprintf($lang['danger']['mailbox_invalid'])
  641. );
  642. return false;
  643. }
  644. $domain = strtolower(trim($postarray['domain']));
  645. $password = $postarray['password'];
  646. $password2 = $postarray['password2'];
  647. $local_part = strtolower(trim($postarray['local_part']));
  648. $name = $postarray['name'];
  649. $quota_m = $postarray['quota'];
  650. if (empty($name)) {
  651. $name = $local_part;
  652. }
  653. isset($postarray['active']) ? $active = '1' : $active = '0';
  654. $quota_b = ($quota_m * 1048576);
  655. $maildir = $domain."/".$local_part."/";
  656. if (!is_valid_domain_name($domain)) {
  657. $_SESSION['return'] = array(
  658. 'type' => 'danger',
  659. 'msg' => sprintf($lang['danger']['domain_invalid'])
  660. );
  661. return false;
  662. }
  663. try {
  664. $stmt = $pdo->prepare("SELECT `mailboxes`, `maxquota`, `quota` FROM `domain`
  665. WHERE `domain` = :domain");
  666. $stmt->execute(array(':domain' => $domain));
  667. $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
  668. }
  669. catch(PDOException $e) {
  670. $_SESSION['return'] = array(
  671. 'type' => 'danger',
  672. 'msg' => 'MySQL: '.$e
  673. );
  674. return false;
  675. }
  676. try {
  677. $stmt = $pdo->prepare("SELECT
  678. COUNT(*) as count,
  679. COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota`
  680. FROM `mailbox`
  681. WHERE `domain` = :domain");
  682. $stmt->execute(array(':domain' => $domain));
  683. $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
  684. }
  685. catch(PDOException $e) {
  686. $_SESSION['return'] = array(
  687. 'type' => 'danger',
  688. 'msg' => 'MySQL: '.$e
  689. );
  690. return false;
  691. }
  692. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  693. $_SESSION['return'] = array(
  694. 'type' => 'danger',
  695. 'msg' => sprintf($lang['danger']['access_denied'])
  696. );
  697. return false;
  698. }
  699. try {
  700. $stmt = $pdo->prepare("SELECT `local_part` FROM `mailbox` WHERE `local_part` = :local_part and `domain`= :domain");
  701. $stmt->execute(array(':local_part' => $local_part, ':domain' => $domain));
  702. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  703. }
  704. catch(PDOException $e) {
  705. $_SESSION['return'] = array(
  706. 'type' => 'danger',
  707. 'msg' => 'MySQL: '.$e
  708. );
  709. return false;
  710. }
  711. if ($num_results != 0) {
  712. $_SESSION['return'] = array(
  713. 'type' => 'danger',
  714. 'msg' => sprintf($lang['danger']['object_exists'], htmlspecialchars($username))
  715. );
  716. return false;
  717. }
  718. try {
  719. $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE address= :username");
  720. $stmt->execute(array(':username' => $username));
  721. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  722. }
  723. catch(PDOException $e) {
  724. $_SESSION['return'] = array(
  725. 'type' => 'danger',
  726. 'msg' => 'MySQL: '.$e
  727. );
  728. return false;
  729. }
  730. if ($num_results != 0) {
  731. $_SESSION['return'] = array(
  732. 'type' => 'danger',
  733. 'msg' => sprintf($lang['danger']['is_alias'], htmlspecialchars($username))
  734. );
  735. return false;
  736. }
  737. try {
  738. $stmt = $pdo->prepare("SELECT `address` FROM `spamalias` WHERE `address`= :username");
  739. $stmt->execute(array(':username' => $username));
  740. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  741. }
  742. catch(PDOException $e) {
  743. $_SESSION['return'] = array(
  744. 'type' => 'danger',
  745. 'msg' => 'MySQL: '.$e
  746. );
  747. return false;
  748. }
  749. if ($num_results != 0) {
  750. $_SESSION['return'] = array(
  751. 'type' => 'danger',
  752. 'msg' => sprintf($lang['danger']['is_spam_alias'], htmlspecialchars($username))
  753. );
  754. return false;
  755. }
  756. if (!is_numeric($quota_m) || $quota_m == "0") {
  757. $_SESSION['return'] = array(
  758. 'type' => 'danger',
  759. 'msg' => sprintf($lang['danger']['quota_not_0_not_numeric'])
  760. );
  761. return false;
  762. }
  763. if (!empty($password) && !empty($password2)) {
  764. if ($password != $password2) {
  765. $_SESSION['return'] = array(
  766. 'type' => 'danger',
  767. 'msg' => sprintf($lang['danger']['password_mismatch'])
  768. );
  769. return false;
  770. }
  771. $password_hashed = hash_password($password);
  772. }
  773. else {
  774. $_SESSION['return'] = array(
  775. 'type' => 'danger',
  776. 'msg' => sprintf($lang['danger']['password_empty'])
  777. );
  778. return false;
  779. }
  780. if ($MailboxData['count'] >= $DomainData['mailboxes']) {
  781. $_SESSION['return'] = array(
  782. 'type' => 'danger',
  783. 'msg' => sprintf($lang['danger']['max_mailbox_exceeded'], $MailboxData['count'], $DomainData['mailboxes'])
  784. );
  785. return false;
  786. }
  787. try {
  788. $stmt = $pdo->prepare("SELECT `domain` FROM `domain` WHERE `domain`= :domain");
  789. $stmt->execute(array(':domain' => $domain));
  790. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  791. }
  792. catch(PDOException $e) {
  793. $_SESSION['return'] = array(
  794. 'type' => 'danger',
  795. 'msg' => 'MySQL: '.$e
  796. );
  797. return false;
  798. }
  799. if ($num_results == 0) {
  800. $_SESSION['return'] = array(
  801. 'type' => 'danger',
  802. 'msg' => $lang['danger']['domain_not_found']
  803. );
  804. return false;
  805. }
  806. if ($quota_m > $DomainData['maxquota']) {
  807. $_SESSION['return'] = array(
  808. 'type' => 'danger',
  809. 'msg' => sprintf($lang['danger']['mailbox_quota_exceeded'], $DomainData['maxquota'])
  810. );
  811. return false;
  812. }
  813. if (($MailboxData['quota'] + $quota_m) > $DomainData['quota']) {
  814. $quota_left_m = ($DomainData['quota'] - $MailboxData['quota']);
  815. $_SESSION['return'] = array(
  816. 'type' => 'danger',
  817. 'msg' => sprintf($lang['danger']['mailbox_quota_left_exceeded'], $quota_left_m)
  818. );
  819. return false;
  820. }
  821. try {
  822. $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `created`, `modified`, `active`)
  823. VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, :created, :modified, :active)");
  824. $stmt->execute(array(
  825. ':username' => $username,
  826. ':password_hashed' => $password_hashed,
  827. ':name' => $name,
  828. ':maildir' => $maildir,
  829. ':quota_b' => $quota_b,
  830. ':local_part' => $local_part,
  831. ':domain' => $domain,
  832. ':created' => date('Y-m-d H:i:s'),
  833. ':modified' => date('Y-m-d H:i:s'),
  834. ':active' => $active
  835. ));
  836. $stmt = $pdo->prepare("INSERT INTO `quota2` (`username`, `bytes`, `messages`)
  837. VALUES (:username, '0', '0')");
  838. $stmt->execute(array(':username' => $username));
  839. $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `created`, `modified`, `active`)
  840. VALUES (:username1, :username2, :domain, :created, :modified, :active)");
  841. $stmt->execute(array(
  842. ':username1' => $username,
  843. ':username2' => $username,
  844. ':domain' => $domain,
  845. ':created' => date('Y-m-d H:i:s'),
  846. ':modified' => date('Y-m-d H:i:s'),
  847. ':active' => $active
  848. ));
  849. $_SESSION['return'] = array(
  850. 'type' => 'success',
  851. 'msg' => sprintf($lang['success']['mailbox_added'], htmlspecialchars($username))
  852. );
  853. }
  854. catch (PDOException $e) {
  855. $_SESSION['return'] = array(
  856. 'type' => 'danger',
  857. 'msg' => 'MySQL: '.$e
  858. );
  859. return false;
  860. }
  861. }
  862. function mailbox_edit_alias($postarray) {
  863. global $lang;
  864. global $pdo;
  865. $address = $postarray['address'];
  866. $domain = idn_to_ascii(substr(strstr($address, '@'), 1));
  867. $local_part = strstr($address, '@', true);
  868. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  869. $_SESSION['return'] = array(
  870. 'type' => 'danger',
  871. 'msg' => sprintf($lang['danger']['access_denied'])
  872. );
  873. return false;
  874. }
  875. if (empty($postarray['goto'])) {
  876. $_SESSION['return'] = array(
  877. 'type' => 'danger',
  878. 'msg' => sprintf($lang['danger']['goto_empty'])
  879. );
  880. return false;
  881. }
  882. $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['goto']));
  883. foreach ($gotos as &$goto) {
  884. if (empty($goto)) {
  885. continue;
  886. }
  887. if (!filter_var($goto, FILTER_VALIDATE_EMAIL)) {
  888. $_SESSION['return'] = array(
  889. 'type' => 'danger',
  890. 'msg' =>sprintf($lang['danger']['goto_invalid'])
  891. );
  892. return false;
  893. }
  894. if ($goto == $address) {
  895. $_SESSION['return'] = array(
  896. 'type' => 'danger',
  897. 'msg' => sprintf($lang['danger']['alias_goto_identical'])
  898. );
  899. return false;
  900. }
  901. }
  902. $gotos = array_filter($gotos);
  903. $goto = implode(",", $gotos);
  904. isset($postarray['active']) ? $active = '1' : $active = '0';
  905. if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) {
  906. $_SESSION['return'] = array(
  907. 'type' => 'danger',
  908. 'msg' => sprintf($lang['danger']['alias_invalid'])
  909. );
  910. return false;
  911. }
  912. try {
  913. $stmt = $pdo->prepare("UPDATE `alias` SET `goto` = :goto, `active`= :active WHERE `address` = :address");
  914. $stmt->execute(array(
  915. ':goto' => $goto,
  916. ':active' => $active,
  917. ':address' => $address
  918. ));
  919. $_SESSION['return'] = array(
  920. 'type' => 'success',
  921. 'msg' => sprintf($lang['success']['alias_modified'], htmlspecialchars($address))
  922. );
  923. }
  924. catch (PDOException $e) {
  925. $_SESSION['return'] = array(
  926. 'type' => 'danger',
  927. 'msg' => 'MySQL: '.$e
  928. );
  929. return false;
  930. }
  931. }
  932. function mailbox_edit_domain($postarray) {
  933. global $lang;
  934. global $pdo;
  935. $domain = $postarray['domain'];
  936. $description = $postarray['description'];
  937. $aliases = filter_var($postarray['aliases'], FILTER_SANITIZE_NUMBER_FLOAT);
  938. $mailboxes = filter_var($postarray['mailboxes'], FILTER_SANITIZE_NUMBER_FLOAT);
  939. $maxquota = filter_var($postarray['maxquota'], FILTER_SANITIZE_NUMBER_FLOAT);
  940. $quota = filter_var($postarray['quota'], FILTER_SANITIZE_NUMBER_FLOAT);
  941. isset($postarray['relay_all_recipients']) ? $relay_all_recipients = '1' : $relay_all_recipients = '0';
  942. isset($postarray['backupmx']) ? $backupmx = '1' : $backupmx = '0';
  943. isset($postarray['relay_all_recipients']) ? $backupmx = '1' : true;
  944. isset($postarray['active']) ? $active = '1' : $active = '0';
  945. try {
  946. $stmt = $pdo->prepare("SELECT
  947. COUNT(*) AS count,
  948. MAX(COALESCE(ROUND(`quota`/1048576), 0)) AS `maxquota`,
  949. COALESCE(ROUND(SUM(`quota`)/1048576), 0) AS `quota`
  950. FROM `mailbox`
  951. WHERE domain= :domain");
  952. $stmt->execute(array(':domain' => $domain));
  953. $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
  954. }
  955. catch(PDOException $e) {
  956. $_SESSION['return'] = array(
  957. 'type' => 'danger',
  958. 'msg' => 'MySQL: '.$e
  959. );
  960. return false;
  961. }
  962. try {
  963. $stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias`
  964. WHERE domain = :domain
  965. AND address NOT IN (
  966. SELECT `username` FROM `mailbox`
  967. )");
  968. $stmt->execute(array(':domain' => $domain));
  969. $AliasData = $stmt->fetch(PDO::FETCH_ASSOC);
  970. }
  971. catch(PDOException $e) {
  972. $_SESSION['return'] = array(
  973. 'type' => 'danger',
  974. 'msg' => 'MySQL: '.$e
  975. );
  976. return false;
  977. }
  978. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  979. $_SESSION['return'] = array(
  980. 'type' => 'danger',
  981. 'msg' => sprintf($lang['danger']['access_denied'])
  982. );
  983. return false;
  984. }
  985. if ($maxquota > $quota) {
  986. $_SESSION['return'] = array(
  987. 'type' => 'danger',
  988. 'msg' => sprintf($lang['danger']['mailbox_quota_exceeds_domain_quota'])
  989. );
  990. return false;
  991. }
  992. if ($MailboxData['maxquota'] > $maxquota) {
  993. $_SESSION['return'] = array(
  994. 'type' => 'danger',
  995. 'msg' => sprintf($lang['danger']['max_quota_in_use'], $MailboxData['maxquota'])
  996. );
  997. return false;
  998. }
  999. if ($MailboxData['quota'] > $quota) {
  1000. $_SESSION['return'] = array(
  1001. 'type' => 'danger',
  1002. 'msg' => sprintf($lang['danger']['domain_quota_m_in_use'], $MailboxData['quota'])
  1003. );
  1004. return false;
  1005. }
  1006. if ($MailboxData['count'] > $mailboxes) {
  1007. $_SESSION['return'] = array(
  1008. 'type' => 'danger',
  1009. 'msg' => sprintf($lang['danger']['mailboxes_in_use'], $MailboxData['count'])
  1010. );
  1011. return false;
  1012. }
  1013. if ($AliasData['count'] > $aliases) {
  1014. $_SESSION['return'] = array(
  1015. 'type' => 'danger',
  1016. 'msg' => sprintf($lang['danger']['aliases_in_use'], $AliasData['count'])
  1017. );
  1018. return false;
  1019. }
  1020. if (!is_valid_domain_name($domain)) {
  1021. $_SESSION['return'] = array(
  1022. 'type' => 'danger',
  1023. 'msg' => sprintf($lang['danger']['domain_invalid'])
  1024. );
  1025. return false;
  1026. }
  1027. try {
  1028. $stmt = $pdo->prepare("UPDATE `domain` SET
  1029. `modified`= :modified,
  1030. `relay_all_recipients` = :relay_all_recipients,
  1031. `backupmx` = :backupmx,
  1032. `active` = :active,
  1033. `quota` = :quota,
  1034. `maxquota` = :maxquota,
  1035. `mailboxes` = :mailboxes,
  1036. `aliases` = :aliases,
  1037. `description` = :description
  1038. WHERE `domain` = :domain");
  1039. $stmt->execute(array(
  1040. ':relay_all_recipients' => $relay_all_recipients,
  1041. ':backupmx' => $backupmx,
  1042. ':active' => $active,
  1043. ':quota' => $quota,
  1044. ':maxquota' => $maxquota,
  1045. ':mailboxes' => $mailboxes,
  1046. ':aliases' => $aliases,
  1047. ':modified' => date('Y-m-d H:i:s'),
  1048. ':description' => $description,
  1049. ':domain' => $domain
  1050. ));
  1051. $_SESSION['return'] = array(
  1052. 'type' => 'success',
  1053. 'msg' => sprintf($lang['success']['domain_modified'], htmlspecialchars($domain))
  1054. );
  1055. }
  1056. catch (PDOException $e) {
  1057. $_SESSION['return'] = array(
  1058. 'type' => 'danger',
  1059. 'msg' => 'MySQL: '.$e
  1060. );
  1061. return false;
  1062. }
  1063. }
  1064. function edit_domain_admin($postarray) {
  1065. global $lang;
  1066. global $pdo;
  1067. $username = $postarray['username'];
  1068. $password = $postarray['password'];
  1069. $password2 = $postarray['password2'];
  1070. isset($postarray['active']) ? $active = '1' : $active = '0';
  1071. if ($_SESSION['mailcow_cc_role'] != "admin") {
  1072. $_SESSION['return'] = array(
  1073. 'type' => 'danger',
  1074. 'msg' => sprintf($lang['danger']['access_denied'])
  1075. );
  1076. return false;
  1077. }
  1078. foreach ($postarray['domain'] as $domain) {
  1079. if (!is_valid_domain_name($domain)) {
  1080. $_SESSION['return'] = array(
  1081. 'type' => 'danger',
  1082. 'msg' => sprintf($lang['danger']['domain_invalid'])
  1083. );
  1084. return false;
  1085. }
  1086. }
  1087. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
  1088. $_SESSION['return'] = array(
  1089. 'type' => 'danger',
  1090. 'msg' => sprintf($lang['danger']['username_invalid'])
  1091. );
  1092. return false;
  1093. }
  1094. try {
  1095. $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
  1096. $stmt->execute(array(
  1097. ':username' => $username,
  1098. ));
  1099. }
  1100. catch (PDOException $e) {
  1101. $_SESSION['return'] = array(
  1102. 'type' => 'danger',
  1103. 'msg' => 'MySQL: '.$e
  1104. );
  1105. return false;
  1106. }
  1107. foreach ($postarray['domain'] as $domain) {
  1108. try {
  1109. $stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
  1110. VALUES (:username, :domain, :created, :active)");
  1111. $stmt->execute(array(
  1112. ':username' => $username,
  1113. ':domain' => $domain,
  1114. ':created' => date('Y-m-d H:i:s'),
  1115. ':active' => $active
  1116. ));
  1117. }
  1118. catch (PDOException $e) {
  1119. $_SESSION['return'] = array(
  1120. 'type' => 'danger',
  1121. 'msg' => 'MySQL: '.$e
  1122. );
  1123. return false;
  1124. }
  1125. }
  1126. if (!empty($password) && !empty($password2)) {
  1127. if ($password != $password2) {
  1128. $_SESSION['return'] = array(
  1129. 'type' => 'danger',
  1130. 'msg' => sprintf($lang['danger']['password_mismatch'])
  1131. );
  1132. return false;
  1133. }
  1134. $password_hashed = hash_password($password);
  1135. try {
  1136. $stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
  1137. $stmt->execute(array(
  1138. ':password_hashed' => $password_hashed,
  1139. ':username' => $username,
  1140. ':modified' => date('Y-m-d H:i:s'),
  1141. ':active' => $active
  1142. ));
  1143. }
  1144. catch (PDOException $e) {
  1145. $_SESSION['return'] = array(
  1146. 'type' => 'danger',
  1147. 'msg' => 'MySQL: '.$e
  1148. );
  1149. return false;
  1150. }
  1151. }
  1152. else {
  1153. try {
  1154. $stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `active` = :active WHERE `username` = :username");
  1155. $stmt->execute(array(
  1156. ':username' => $username,
  1157. ':modified' => date('Y-m-d H:i:s'),
  1158. ':active' => $active
  1159. ));
  1160. }
  1161. catch (PDOException $e) {
  1162. $_SESSION['return'] = array(
  1163. 'type' => 'danger',
  1164. 'msg' => 'MySQL: '.$e
  1165. );
  1166. return false;
  1167. }
  1168. }
  1169. $_SESSION['return'] = array(
  1170. 'type' => 'success',
  1171. 'msg' => sprintf($lang['success']['domain_admin_modified'], htmlspecialchars($username))
  1172. );
  1173. }
  1174. function mailbox_edit_mailbox($postarray) {
  1175. global $lang;
  1176. global $pdo;
  1177. isset($postarray['active']) ? $active = '1' : $active = '0';
  1178. if (!filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  1179. $_SESSION['return'] = array(
  1180. 'type' => 'danger',
  1181. 'msg' => sprintf($lang['danger']['username_invalid'])
  1182. );
  1183. return false;
  1184. }
  1185. $quota_m = $postarray['quota'];
  1186. $quota_b = $quota_m*1048576;
  1187. $username = $postarray['username'];
  1188. $name = $postarray['name'];
  1189. $password = $postarray['password'];
  1190. $password2 = $postarray['password2'];
  1191. try {
  1192. $stmt = $pdo->prepare("SELECT `domain`
  1193. FROM `mailbox`
  1194. WHERE username = :username");
  1195. $stmt->execute(array(':username' => $username));
  1196. $MailboxData1 = $stmt->fetch(PDO::FETCH_ASSOC);
  1197. $stmt = $pdo->prepare("SELECT
  1198. COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota_m_now`
  1199. FROM `mailbox`
  1200. WHERE `username` = :username");
  1201. $stmt->execute(array(':username' => $username));
  1202. $MailboxData2 = $stmt->fetch(PDO::FETCH_ASSOC);
  1203. $stmt = $pdo->prepare("SELECT
  1204. COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota_m_in_use`
  1205. FROM `mailbox`
  1206. WHERE `domain` = :domain");
  1207. $stmt->execute(array(':domain' => $MailboxData1['domain']));
  1208. $MailboxData3 = $stmt->fetch(PDO::FETCH_ASSOC);
  1209. $stmt = $pdo->prepare("SELECT `quota`, `maxquota`
  1210. FROM `domain`
  1211. WHERE `domain` = :domain");
  1212. $stmt->execute(array(':domain' => $MailboxData1['domain']));
  1213. $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
  1214. }
  1215. catch(PDOException $e) {
  1216. $_SESSION['return'] = array(
  1217. 'type' => 'danger',
  1218. 'msg' => 'MySQL: '.$e
  1219. );
  1220. return false;
  1221. }
  1222. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $MailboxData1['domain'])) {
  1223. $_SESSION['return'] = array(
  1224. 'type' => 'danger',
  1225. 'msg' => sprintf($lang['danger']['access_denied'])
  1226. );
  1227. return false;
  1228. }
  1229. if (!is_numeric($quota_m) || $quota_m == "0") {
  1230. $_SESSION['return'] = array(
  1231. 'type' => 'danger',
  1232. 'msg' => sprintf($lang['danger']['quota_not_0_not_numeric'], htmlspecialchars($quota_m))
  1233. );
  1234. return false;
  1235. }
  1236. if ($quota_m > $DomainData['maxquota']) {
  1237. $_SESSION['return'] = array(
  1238. 'type' => 'danger',
  1239. 'msg' => sprintf($lang['danger']['mailbox_quota_exceeded'], $DomainData['maxquota'])
  1240. );
  1241. return false;
  1242. }
  1243. if (($MailboxData3['quota_m_in_use'] - $MailboxData2['quota_m_now'] + $quota_m) > $DomainData['quota']) {
  1244. $quota_left_m = ($DomainData['quota'] - $MailboxData3['quota_m_in_use'] + $MailboxData2['quota_m_now']);
  1245. $_SESSION['return'] = array(
  1246. 'type' => 'danger',
  1247. 'msg' => sprintf($lang['danger']['mailbox_quota_left_exceeded'], $quota_left_m)
  1248. );
  1249. return false;
  1250. }
  1251. try {
  1252. $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
  1253. $stmt->execute(array(
  1254. ':username' => $username
  1255. ));
  1256. }
  1257. catch (PDOException $e) {
  1258. $_SESSION['return'] = array(
  1259. 'type' => 'danger',
  1260. 'msg' => 'MySQL: '.$e
  1261. );
  1262. return false;
  1263. }
  1264. if (isset($postarray['sender_acl']) && is_array($postarray['sender_acl'])) {
  1265. foreach ($postarray['sender_acl'] as $sender_acl) {
  1266. if (!filter_var($sender_acl, FILTER_VALIDATE_EMAIL) &&
  1267. !is_valid_domain_name(str_replace('@', '', $sender_acl))) {
  1268. $_SESSION['return'] = array(
  1269. 'type' => 'danger',
  1270. 'msg' => sprintf($lang['danger']['sender_acl_invalid'])
  1271. );
  1272. return false;
  1273. }
  1274. }
  1275. foreach ($postarray['sender_acl'] as $sender_acl) {
  1276. try {
  1277. $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`)
  1278. VALUES (:sender_acl, :username)");
  1279. $stmt->execute(array(
  1280. ':sender_acl' => $sender_acl,
  1281. ':username' => $username
  1282. ));
  1283. }
  1284. catch (PDOException $e) {
  1285. $_SESSION['return'] = array(
  1286. 'type' => 'danger',
  1287. 'msg' => 'MySQL: '.$e
  1288. );
  1289. return false;
  1290. }
  1291. }
  1292. }
  1293. if (!empty($password) && !empty($password2)) {
  1294. if ($password != $password2) {
  1295. $_SESSION['return'] = array(
  1296. 'type' => 'danger',
  1297. 'msg' => sprintf($lang['danger']['password_mismatch'])
  1298. );
  1299. return false;
  1300. }
  1301. $password_hashed = hash_password($password);
  1302. try {
  1303. $stmt = $pdo->prepare("UPDATE `alias` SET
  1304. `modified` = :modified,
  1305. `active` = :active
  1306. WHERE `address` = :address");
  1307. $stmt->execute(array(
  1308. ':address' => $username,
  1309. ':modified' => date('Y-m-d H:i:s'),
  1310. ':active' => $active
  1311. ));
  1312. $stmt = $pdo->prepare("UPDATE `mailbox` SET
  1313. `modified` = :modified,
  1314. `active` = :active,
  1315. `password` = :password_hashed,
  1316. `name`= :name,
  1317. `quota` = :quota_b
  1318. WHERE `username` = :username");
  1319. $stmt->execute(array(
  1320. ':modified' => date('Y-m-d H:i:s'),
  1321. ':password_hashed' => $password_hashed,
  1322. ':active' => $active,
  1323. ':name' => $name,
  1324. ':quota_b' => $quota_b,
  1325. ':username' => $username
  1326. ));
  1327. $_SESSION['return'] = array(
  1328. 'type' => 'success',
  1329. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1330. );
  1331. return true;
  1332. }
  1333. catch (PDOException $e) {
  1334. $_SESSION['return'] = array(
  1335. 'type' => 'danger',
  1336. 'msg' => 'MySQL: '.$e
  1337. );
  1338. return false;
  1339. }
  1340. }
  1341. try {
  1342. $stmt = $pdo->prepare("UPDATE `alias` SET
  1343. `modified` = :modified,
  1344. `active` = :active
  1345. WHERE `address` = :address");
  1346. $stmt->execute(array(
  1347. ':address' => $username,
  1348. ':modified' => date('Y-m-d H:i:s'),
  1349. ':active' => $active
  1350. ));
  1351. $stmt = $pdo->prepare("UPDATE `mailbox` SET
  1352. `modified` = :modified,
  1353. `active` = :active,
  1354. `name`= :name,
  1355. `quota` = :quota_b
  1356. WHERE `username` = :username");
  1357. $stmt->execute(array(
  1358. ':active' => $active,
  1359. ':modified' => date('Y-m-d H:i:s'),
  1360. ':name' => $name,
  1361. ':quota_b' => $quota_b,
  1362. ':username' => $username
  1363. ));
  1364. $_SESSION['return'] = array(
  1365. 'type' => 'success',
  1366. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1367. );
  1368. return true;
  1369. }
  1370. catch (PDOException $e) {
  1371. $_SESSION['return'] = array(
  1372. 'type' => 'danger',
  1373. 'msg' => 'MySQL: '.$e
  1374. );
  1375. return false;
  1376. }
  1377. }
  1378. function mailbox_delete_domain($postarray) {
  1379. global $lang;
  1380. global $pdo;
  1381. $domain = $postarray['domain'];
  1382. if ($_SESSION['mailcow_cc_role'] != "admin") {
  1383. $_SESSION['return'] = array(
  1384. 'type' => 'danger',
  1385. 'msg' => sprintf($lang['danger']['access_denied'])
  1386. );
  1387. return false;
  1388. }
  1389. if (!is_valid_domain_name($domain)) {
  1390. $_SESSION['return'] = array(
  1391. 'type' => 'danger',
  1392. 'msg' => sprintf($lang['danger']['domain_invalid'])
  1393. );
  1394. return false;
  1395. }
  1396. $domain = strtolower(trim($domain));
  1397. try {
  1398. $stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
  1399. WHERE `domain` = :domain");
  1400. $stmt->execute(array(':domain' => $domain));
  1401. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  1402. }
  1403. catch(PDOException $e) {
  1404. $_SESSION['return'] = array(
  1405. 'type' => 'danger',
  1406. 'msg' => 'MySQL: '.$e
  1407. );
  1408. return false;
  1409. }
  1410. if ($num_results != 0 || !empty($num_results)) {
  1411. $_SESSION['return'] = array(
  1412. 'type' => 'danger',
  1413. 'msg' => sprintf($lang['danger']['domain_not_empty'])
  1414. );
  1415. return false;
  1416. }
  1417. try {
  1418. $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain");
  1419. $stmt->execute(array(
  1420. ':domain' => $domain,
  1421. ));
  1422. $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `domain` = :domain");
  1423. $stmt->execute(array(
  1424. ':domain' => $domain,
  1425. ));
  1426. $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :domain");
  1427. $stmt->execute(array(
  1428. ':domain' => $domain,
  1429. ));
  1430. $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `target_domain` = :domain");
  1431. $stmt->execute(array(
  1432. ':domain' => $domain,
  1433. ));
  1434. $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `domain` = :domain");
  1435. $stmt->execute(array(
  1436. ':domain' => $domain,
  1437. ));
  1438. $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` LIKE :domain");
  1439. $stmt->execute(array(
  1440. ':domain' => '%@'.$domain,
  1441. ));
  1442. $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain");
  1443. $stmt->execute(array(
  1444. ':domain' => '%@'.$domain,
  1445. ));
  1446. $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain");
  1447. $stmt->execute(array(
  1448. ':domain' => '%@'.$domain,
  1449. ));
  1450. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain");
  1451. $stmt->execute(array(
  1452. ':domain' => '%@'.$domain,
  1453. ));
  1454. }
  1455. catch (PDOException $e) {
  1456. $_SESSION['return'] = array(
  1457. 'type' => 'danger',
  1458. 'msg' => 'MySQL: '.$e
  1459. );
  1460. return false;
  1461. }
  1462. $_SESSION['return'] = array(
  1463. 'type' => 'success',
  1464. 'msg' => sprintf($lang['success']['domain_removed'], htmlspecialchars($domain))
  1465. );
  1466. return true;
  1467. }
  1468. function mailbox_delete_alias($postarray) {
  1469. global $lang;
  1470. global $pdo;
  1471. $address = $postarray['address'];
  1472. $local_part = strstr($address, '@', true);
  1473. $domain = substr(strrchr($address, "@"), 1);
  1474. try {
  1475. $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :address");
  1476. $stmt->execute(array(':address' => $address));
  1477. $gotos = $stmt->fetch(PDO::FETCH_ASSOC);
  1478. }
  1479. catch(PDOException $e) {
  1480. $_SESSION['return'] = array(
  1481. 'type' => 'danger',
  1482. 'msg' => 'MySQL: '.$e
  1483. );
  1484. return false;
  1485. }
  1486. $goto_array = explode(',', $gotos['goto']);
  1487. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  1488. $_SESSION['return'] = array(
  1489. 'type' => 'danger',
  1490. 'msg' => sprintf($lang['danger']['access_denied'])
  1491. );
  1492. return false;
  1493. }
  1494. try {
  1495. $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `address` = :address AND `address` NOT IN (SELECT `username` FROM `mailbox`)");
  1496. $stmt->execute(array(
  1497. ':address' => $address
  1498. ));
  1499. }
  1500. catch (PDOException $e) {
  1501. $_SESSION['return'] = array(
  1502. 'type' => 'danger',
  1503. 'msg' => 'MySQL: '.$e
  1504. );
  1505. return false;
  1506. }
  1507. $_SESSION['return'] = array(
  1508. 'type' => 'success',
  1509. 'msg' => sprintf($lang['success']['alias_removed'], htmlspecialchars($address))
  1510. );
  1511. }
  1512. function mailbox_delete_alias_domain($postarray) {
  1513. global $lang;
  1514. global $pdo;
  1515. if (!is_valid_domain_name($postarray['alias_domain'])) {
  1516. $_SESSION['return'] = array(
  1517. 'type' => 'danger',
  1518. 'msg' => sprintf($lang['danger']['domain_invalid'])
  1519. );
  1520. return false;
  1521. }
  1522. $alias_domain = $postarray['alias_domain'];
  1523. try {
  1524. $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
  1525. WHERE `alias_domain`= :alias_domain");
  1526. $stmt->execute(array(':alias_domain' => $alias_domain));
  1527. $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
  1528. }
  1529. catch(PDOException $e) {
  1530. $_SESSION['return'] = array(
  1531. 'type' => 'danger',
  1532. 'msg' => 'MySQL: '.$e
  1533. );
  1534. return false;
  1535. }
  1536. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) {
  1537. $_SESSION['return'] = array(
  1538. 'type' => 'danger',
  1539. 'msg' => sprintf($lang['danger']['access_denied'])
  1540. );
  1541. return false;
  1542. }
  1543. try {
  1544. $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `alias_domain` = :alias_domain");
  1545. $stmt->execute(array(
  1546. ':alias_domain' => $alias_domain,
  1547. ));
  1548. }
  1549. catch (PDOException $e) {
  1550. $_SESSION['return'] = array(
  1551. 'type' => 'danger',
  1552. 'msg' => 'MySQL: '.$e
  1553. );
  1554. return false;
  1555. }
  1556. $_SESSION['return'] = array(
  1557. 'type' => 'success',
  1558. 'msg' => sprintf($lang['success']['alias_domain_removed'], htmlspecialchars($alias_domain))
  1559. );
  1560. }
  1561. function mailbox_delete_mailbox($postarray) {
  1562. global $lang;
  1563. global $pdo;
  1564. $domain = substr(strrchr($postarray['username'], "@"), 1);
  1565. $username = $postarray['username'];
  1566. if (!filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  1567. $_SESSION['return'] = array(
  1568. 'type' => 'danger',
  1569. 'msg' => sprintf($lang['danger']['access_denied'])
  1570. );
  1571. return false;
  1572. }
  1573. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  1574. $_SESSION['return'] = array(
  1575. 'type' => 'danger',
  1576. 'msg' => sprintf($lang['danger']['access_denied'])
  1577. );
  1578. return false;
  1579. }
  1580. try {
  1581. $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
  1582. $stmt->execute(array(
  1583. ':username' => $username
  1584. ));
  1585. $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :username");
  1586. $stmt->execute(array(
  1587. ':username' => $username
  1588. ));
  1589. $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
  1590. $stmt->execute(array(
  1591. ':username' => $username
  1592. ));
  1593. $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
  1594. $stmt->execute(array(
  1595. ':username' => $username
  1596. ));
  1597. $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
  1598. $stmt->execute(array(
  1599. ':username' => $username
  1600. ));
  1601. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username");
  1602. $stmt->execute(array(
  1603. ':username' => $username
  1604. ));
  1605. $stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
  1606. WHERE `goto` LIKE :username");
  1607. $stmt->execute(array(':username' => '%'.$username.'%'));
  1608. $GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1609. foreach ($GotoData as $gotos) {
  1610. $goto_exploded = explode(',', $gotos['goto']);
  1611. if (($key = array_search($username, $goto_exploded)) !== false) {
  1612. unset($goto_exploded[$key]);
  1613. }
  1614. $gotos_rebuild = implode(',', $goto_exploded);
  1615. $stmt = $pdo->prepare("UPDATE `alias` SET `goto` = :goto WHERE `address` = :address");
  1616. $stmt->execute(array(
  1617. ':goto' => $gotos_rebuild,
  1618. ':address' => $gotos['address']
  1619. ));
  1620. }
  1621. }
  1622. catch (PDOException $e) {
  1623. $_SESSION['return'] = array(
  1624. 'type' => 'danger',
  1625. 'msg' => 'MySQL: '.$e
  1626. );
  1627. return false;
  1628. }
  1629. $_SESSION['return'] = array(
  1630. 'type' => 'success',
  1631. 'msg' => sprintf($lang['success']['mailbox_removed'], htmlspecialchars($username))
  1632. );
  1633. }
  1634. function set_admin_account($postarray) {
  1635. global $lang;
  1636. global $pdo;
  1637. if ($_SESSION['mailcow_cc_role'] != "admin") {
  1638. $_SESSION['return'] = array(
  1639. 'type' => 'danger',
  1640. 'msg' => sprintf($lang['danger']['access_denied'])
  1641. );
  1642. return false;
  1643. }
  1644. $name = $postarray['admin_user'];
  1645. $name_now = $postarray['admin_user_now'];
  1646. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $name)) || empty ($name)) {
  1647. $_SESSION['return'] = array(
  1648. 'type' => 'danger',
  1649. 'msg' => sprintf($lang['danger']['username_invalid'])
  1650. );
  1651. return false;
  1652. }
  1653. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $name_now)) || empty ($name_now)) {
  1654. $_SESSION['return'] = array(
  1655. 'type' => 'danger',
  1656. 'msg' => sprintf($lang['danger']['username_invalid'])
  1657. );
  1658. return false;
  1659. }
  1660. if (!empty($postarray['admin_pass']) && !empty($postarray['admin_pass2'])) {
  1661. if ($postarray['admin_pass'] != $postarray['admin_pass2']) {
  1662. $_SESSION['return'] = array(
  1663. 'type' => 'danger',
  1664. 'msg' => sprintf($lang['danger']['password_mismatch'])
  1665. );
  1666. return false;
  1667. }
  1668. $password_hashed = hash_password($postarray['admin_pass']);
  1669. try {
  1670. $stmt = $pdo->prepare("UPDATE `admin` SET
  1671. `modified` = :modified,
  1672. `password` = :password_hashed,
  1673. `username` = :name
  1674. WHERE `username` = :username");
  1675. $stmt->execute(array(
  1676. ':password_hashed' => $password_hashed,
  1677. ':modified' => date('Y-m-d H:i:s'),
  1678. ':name' => $name,
  1679. ':username' => $name_now
  1680. ));
  1681. }
  1682. catch (PDOException $e) {
  1683. $_SESSION['return'] = array(
  1684. 'type' => 'danger',
  1685. 'msg' => 'MySQL: '.$e
  1686. );
  1687. return false;
  1688. }
  1689. }
  1690. else {
  1691. try {
  1692. $stmt = $pdo->prepare("UPDATE `admin` SET
  1693. `modified` = :modified,
  1694. `username` = :name
  1695. WHERE `username` = :name_now");
  1696. $stmt->execute(array(
  1697. ':name' => $name,
  1698. ':modified' => date('Y-m-d H:i:s'),
  1699. ':name_now' => $name_now
  1700. ));
  1701. }
  1702. catch (PDOException $e) {
  1703. $_SESSION['return'] = array(
  1704. 'type' => 'danger',
  1705. 'msg' => 'MySQL: '.$e
  1706. );
  1707. return false;
  1708. }
  1709. }
  1710. try {
  1711. $stmt = $pdo->prepare("UPDATE `domain_admins` SET
  1712. `domain` = :domain,
  1713. `username` = :name
  1714. WHERE `username` = :name_now");
  1715. $stmt->execute(array(
  1716. ':domain' => 'ALL',
  1717. ':name' => $name,
  1718. ':name_now' => $name_now
  1719. ));
  1720. }
  1721. catch (PDOException $e) {
  1722. $_SESSION['return'] = array(
  1723. 'type' => 'danger',
  1724. 'msg' => 'MySQL: '.$e
  1725. );
  1726. return false;
  1727. }
  1728. $_SESSION['return'] = array(
  1729. 'type' => 'success',
  1730. 'msg' => sprintf($lang['success']['admin_modified'])
  1731. );
  1732. }
  1733. function set_time_limited_aliases($postarray) {
  1734. global $lang;
  1735. global $pdo;
  1736. $username = $_SESSION['mailcow_cc_username'];
  1737. $domain = substr($username, strpos($username, '@'));
  1738. if (($_SESSION['mailcow_cc_role'] != "user" &&
  1739. $_SESSION['mailcow_cc_role'] != "domainadmin") ||
  1740. empty($username) ||
  1741. empty($domain)) {
  1742. $_SESSION['return'] = array(
  1743. 'type' => 'danger',
  1744. 'msg' => sprintf($lang['danger']['access_denied'])
  1745. );
  1746. return false;
  1747. }
  1748. switch ($postarray["trigger_set_time_limited_aliases"]) {
  1749. case "generate":
  1750. if (!is_numeric($postarray["validity"]) || $postarray["validity"] > 672) {
  1751. $_SESSION['return'] = array(
  1752. 'type' => 'danger',
  1753. 'msg' => sprintf($lang['danger']['validity_missing'])
  1754. );
  1755. return false;
  1756. }
  1757. $validity = strtotime("+".$postarray["validity"]." hour");
  1758. $letters = 'abcefghijklmnopqrstuvwxyz1234567890';
  1759. $random_name = substr(str_shuffle($letters), 0, 24);
  1760. try {
  1761. $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES
  1762. (:address, :goto, :validity)");
  1763. $stmt->execute(array(
  1764. ':address' => $random_name.$domain,
  1765. ':goto' => $username,
  1766. ':validity' => $validity
  1767. ));
  1768. }
  1769. catch (PDOException $e) {
  1770. $_SESSION['return'] = array(
  1771. 'type' => 'danger',
  1772. 'msg' => 'MySQL: '.$e
  1773. );
  1774. return false;
  1775. }
  1776. $_SESSION['return'] = array(
  1777. 'type' => 'success',
  1778. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  1779. );
  1780. break;
  1781. case "delete":
  1782. try {
  1783. $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
  1784. $stmt->execute(array(
  1785. ':username' => $username
  1786. ));
  1787. }
  1788. catch (PDOException $e) {
  1789. $_SESSION['return'] = array(
  1790. 'type' => 'danger',
  1791. 'msg' => 'MySQL: '.$e
  1792. );
  1793. return false;
  1794. }
  1795. $_SESSION['return'] = array(
  1796. 'type' => 'success',
  1797. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  1798. );
  1799. break;
  1800. case "extend":
  1801. try {
  1802. $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = (`validity` + 3600)
  1803. WHERE `goto` = :username
  1804. AND `validity` >= :validity");
  1805. $stmt->execute(array(
  1806. ':username' => $username,
  1807. ':validity' => time(),
  1808. ));
  1809. }
  1810. catch (PDOException $e) {
  1811. $_SESSION['return'] = array(
  1812. 'type' => 'danger',
  1813. 'msg' => 'MySQL: '.$e
  1814. );
  1815. return false;
  1816. }
  1817. $_SESSION['return'] = array(
  1818. 'type' => 'success',
  1819. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  1820. );
  1821. break;
  1822. }
  1823. }
  1824. function set_user_account($postarray) {
  1825. global $lang;
  1826. global $pdo;
  1827. $username = $_SESSION['mailcow_cc_username'];
  1828. $password_old = $postarray['user_old_pass'];
  1829. isset($postarray['togglePwNew']) ? $pwnew_active = '1' : $pwnew_active = '0';
  1830. if (isset($pwnew_active) && $pwnew_active == "1") {
  1831. $password_new = $postarray['user_new_pass'];
  1832. $password_new2 = $postarray['user_new_pass2'];
  1833. }
  1834. if (!check_login($username, $password_old) == "user") {
  1835. $_SESSION['return'] = array(
  1836. 'type' => 'danger',
  1837. 'msg' => sprintf($lang['danger']['access_denied'])
  1838. );
  1839. return false;
  1840. }
  1841. if ($_SESSION['mailcow_cc_role'] != "user" &&
  1842. $_SESSION['mailcow_cc_role'] != "domainadmin") {
  1843. $_SESSION['return'] = array(
  1844. 'type' => 'danger',
  1845. 'msg' => sprintf($lang['danger']['access_denied'])
  1846. );
  1847. return false;
  1848. }
  1849. if (isset($password_new) && isset($password_new2)) {
  1850. if (!empty($password_new2) && !empty($password_new)) {
  1851. if ($password_new2 != $password_new) {
  1852. $_SESSION['return'] = array(
  1853. 'type' => 'danger',
  1854. 'msg' => sprintf($lang['danger']['password_mismatch'])
  1855. );
  1856. return false;
  1857. }
  1858. if (strlen($password_new) < "6" ||
  1859. !preg_match('/[A-Za-z]/', $password_new) ||
  1860. !preg_match('/[0-9]/', $password_new)) {
  1861. $_SESSION['return'] = array(
  1862. 'type' => 'danger',
  1863. 'msg' => sprintf($lang['danger']['password_complexity'])
  1864. );
  1865. return false;
  1866. }
  1867. $password_hashed = hash_password($password_new);
  1868. try {
  1869. $stmt = $pdo->prepare("UPDATE `mailbox` SET `modified` = :modified, `password` = :password_hashed WHERE `username` = :username");
  1870. $stmt->execute(array(
  1871. ':password_hashed' => $password_hashed,
  1872. ':modified' => date('Y-m-d H:i:s'),
  1873. ':username' => $username
  1874. ));
  1875. }
  1876. catch (PDOException $e) {
  1877. $_SESSION['return'] = array(
  1878. 'type' => 'danger',
  1879. 'msg' => 'MySQL: '.$e
  1880. );
  1881. return false;
  1882. }
  1883. }
  1884. }
  1885. $_SESSION['return'] = array(
  1886. 'type' => 'success',
  1887. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1888. );
  1889. }
  1890. function add_domain_admin($postarray) {
  1891. global $lang;
  1892. global $pdo;
  1893. $username = strtolower(trim($postarray['username']));
  1894. $password = $postarray['password'];
  1895. $password2 = $postarray['password2'];
  1896. isset($postarray['active']) ? $active = '1' : $active = '0';
  1897. if ($_SESSION['mailcow_cc_role'] != "admin") {
  1898. $_SESSION['return'] = array(
  1899. 'type' => 'danger',
  1900. 'msg' => sprintf($lang['danger']['access_denied'])
  1901. );
  1902. return false;
  1903. }
  1904. if (empty($postarray['domain'])) {
  1905. $_SESSION['return'] = array(
  1906. 'type' => 'danger',
  1907. 'msg' => sprintf($lang['danger']['domain_invalid'])
  1908. );
  1909. return false;
  1910. }
  1911. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) {
  1912. $_SESSION['return'] = array(
  1913. 'type' => 'danger',
  1914. 'msg' => sprintf($lang['danger']['username_invalid'])
  1915. );
  1916. return false;
  1917. }
  1918. try {
  1919. $stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
  1920. WHERE `username` = :username");
  1921. $stmt->execute(array(':username' => $username));
  1922. $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  1923. $stmt = $pdo->prepare("SELECT `username` FROM `admin`
  1924. WHERE `username` = :username");
  1925. $stmt->execute(array(':username' => $username));
  1926. $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  1927. $stmt = $pdo->prepare("SELECT `username` FROM `domain_admins`
  1928. WHERE `username` = :username");
  1929. $stmt->execute(array(':username' => $username));
  1930. $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  1931. }
  1932. catch(PDOException $e) {
  1933. $_SESSION['return'] = array(
  1934. 'type' => 'danger',
  1935. 'msg' => 'MySQL: '.$e
  1936. );
  1937. return false;
  1938. }
  1939. foreach ($num_results as $num_results_each) {
  1940. if ($num_results_each != 0) {
  1941. $_SESSION['return'] = array(
  1942. 'type' => 'danger',
  1943. 'msg' => sprintf($lang['danger']['object_exists'], htmlspecialchars($username))
  1944. );
  1945. return false;
  1946. }
  1947. }
  1948. if (!empty($password) && !empty($password2)) {
  1949. if ($password != $password2) {
  1950. $_SESSION['return'] = array(
  1951. 'type' => 'danger',
  1952. 'msg' => sprintf($lang['danger']['password_mismatch'])
  1953. );
  1954. return false;
  1955. }
  1956. $password_hashed = hash_password($password);
  1957. foreach ($postarray['domain'] as $domain) {
  1958. if (!is_valid_domain_name($domain)) {
  1959. $_SESSION['return'] = array(
  1960. 'type' => 'danger',
  1961. 'msg' => sprintf($lang['danger']['domain_invalid'])
  1962. );
  1963. return false;
  1964. }
  1965. try {
  1966. $stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
  1967. VALUES (:username, :domain, :created, :active)");
  1968. $stmt->execute(array(
  1969. ':username' => $username,
  1970. ':domain' => $domain,
  1971. ':created' => date('Y-m-d H:i:s'),
  1972. ':active' => $active
  1973. ));
  1974. }
  1975. catch (PDOException $e) {
  1976. $_SESSION['return'] = array(
  1977. 'type' => 'danger',
  1978. 'msg' => 'MySQL: '.$e
  1979. );
  1980. return false;
  1981. }
  1982. }
  1983. try {
  1984. $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `created`, `modified`, `active`)
  1985. VALUES (:username, :password_hashed, '0', :created, :modified, :active)");
  1986. $stmt->execute(array(
  1987. ':username' => $username,
  1988. ':password_hashed' => $password_hashed,
  1989. ':created' => date('Y-m-d H:i:s'),
  1990. ':modified' => date('Y-m-d H:i:s'),
  1991. ':active' => $active
  1992. ));
  1993. }
  1994. catch (PDOException $e) {
  1995. $_SESSION['return'] = array(
  1996. 'type' => 'danger',
  1997. 'msg' => 'MySQL: '.$e
  1998. );
  1999. return false;
  2000. }
  2001. }
  2002. else {
  2003. $_SESSION['return'] = array(
  2004. 'type' => 'danger',
  2005. 'msg' => sprintf($lang['danger']['password_empty'])
  2006. );
  2007. return false;
  2008. }
  2009. $_SESSION['return'] = array(
  2010. 'type' => 'success',
  2011. 'msg' => sprintf($lang['success']['domain_admin_added'], htmlspecialchars($username))
  2012. );
  2013. }
  2014. function delete_domain_admin($postarray) {
  2015. global $pdo;
  2016. global $lang;
  2017. if ($_SESSION['mailcow_cc_role'] != "admin") {
  2018. $_SESSION['return'] = array(
  2019. 'type' => 'danger',
  2020. 'msg' => sprintf($lang['danger']['access_denied'])
  2021. );
  2022. return false;
  2023. }
  2024. $username = $postarray['username'];
  2025. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
  2026. $_SESSION['return'] = array(
  2027. 'type' => 'danger',
  2028. 'msg' => sprintf($lang['danger']['username_invalid'])
  2029. );
  2030. return false;
  2031. }
  2032. try {
  2033. $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
  2034. $stmt->execute(array(
  2035. ':username' => $username,
  2036. ));
  2037. $stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
  2038. $stmt->execute(array(
  2039. ':username' => $username,
  2040. ));
  2041. }
  2042. catch (PDOException $e) {
  2043. $_SESSION['return'] = array(
  2044. 'type' => 'danger',
  2045. 'msg' => 'MySQL: '.$e
  2046. );
  2047. return false;
  2048. }
  2049. $_SESSION['return'] = array(
  2050. 'type' => 'success',
  2051. 'msg' => sprintf($lang['success']['domain_admin_removed'], htmlspecialchars($username))
  2052. );
  2053. }
  2054. function get_spam_score($username) {
  2055. global $pdo;
  2056. $default = "5, 15";
  2057. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  2058. return $default;
  2059. }
  2060. try {
  2061. $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object` = :username AND
  2062. (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
  2063. $stmt->execute(array(':username' => $username));
  2064. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  2065. }
  2066. catch(PDOException $e) {
  2067. $_SESSION['return'] = array(
  2068. 'type' => 'danger',
  2069. 'msg' => 'MySQL: '.$e
  2070. );
  2071. return false;
  2072. }
  2073. if ($num_results == 0 || empty ($num_results)) {
  2074. return $default;
  2075. }
  2076. else {
  2077. try {
  2078. $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'highspamlevel' AND `object` = :username");
  2079. $stmt->execute(array(':username' => $username));
  2080. $highspamlevel = $stmt->fetch(PDO::FETCH_ASSOC);
  2081. $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'lowspamlevel' AND `object` = :username");
  2082. $stmt->execute(array(':username' => $username));
  2083. $lowspamlevel = $stmt->fetch(PDO::FETCH_ASSOC);
  2084. return $lowspamlevel['value'].', '.$highspamlevel['value'];
  2085. }
  2086. catch(PDOException $e) {
  2087. $_SESSION['return'] = array(
  2088. 'type' => 'danger',
  2089. 'msg' => 'MySQL: '.$e
  2090. );
  2091. return false;
  2092. }
  2093. }
  2094. }
  2095. function set_spam_score($postarray) {
  2096. global $lang;
  2097. global $pdo;
  2098. $username = $_SESSION['mailcow_cc_username'];
  2099. $lowspamlevel = explode(',', $postarray['score'])[0];
  2100. $highspamlevel = explode(',', $postarray['score'])[1];
  2101. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  2102. $_SESSION['return'] = array(
  2103. 'type' => 'danger',
  2104. 'msg' => sprintf($lang['danger']['username_invalid'])
  2105. );
  2106. return false;
  2107. }
  2108. if (!is_numeric($lowspamlevel) || !is_numeric($highspamlevel)) {
  2109. $_SESSION['return'] = array(
  2110. 'type' => 'danger',
  2111. 'msg' => sprintf($lang['danger']['access_denied'])
  2112. );
  2113. return false;
  2114. }
  2115. try {
  2116. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
  2117. AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
  2118. $stmt->execute(array(
  2119. ':username' => $username
  2120. ));
  2121. $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`)
  2122. VALUES (:username, 'highspamlevel', :highspamlevel)");
  2123. $stmt->execute(array(
  2124. ':username' => $username,
  2125. ':highspamlevel' => $highspamlevel
  2126. ));
  2127. $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`)
  2128. VALUES (:username, 'lowspamlevel', :lowspamlevel)");
  2129. $stmt->execute(array(
  2130. ':username' => $username,
  2131. ':lowspamlevel' => $lowspamlevel
  2132. ));
  2133. }
  2134. catch (PDOException $e) {
  2135. $_SESSION['return'] = array(
  2136. 'type' => 'danger',
  2137. 'msg' => 'MySQL: '.$e
  2138. );
  2139. return false;
  2140. }
  2141. $_SESSION['return'] = array(
  2142. 'type' => 'success',
  2143. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  2144. );
  2145. }
  2146. function set_policy_list($postarray) {
  2147. global $lang;
  2148. global $pdo;
  2149. (isset($postarray['domain'])) ? $object = $postarray['domain'] : $object = $_SESSION['mailcow_cc_username'];
  2150. ($postarray['object_list'] == "bl") ? $object_list = "blacklist_from" : $object_list = "whitelist_from";
  2151. $object_from = preg_replace('/\.+/', '.', rtrim(preg_replace("/\.\*/", "*", trim(strtolower($postarray['object_from']))), '.'));
  2152. if (!filter_var($object, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($object)) {
  2153. $_SESSION['return'] = array(
  2154. 'type' => 'danger',
  2155. 'msg' => sprintf($lang['danger']['username_invalid'])
  2156. );
  2157. return false;
  2158. }
  2159. if (is_valid_domain_name($object)) {
  2160. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  2161. $_SESSION['return'] = array(
  2162. 'type' => 'danger',
  2163. 'msg' => sprintf($lang['danger']['access_denied'])
  2164. );
  2165. return false;
  2166. }
  2167. }
  2168. if (isset($postarray['prefid'])) {
  2169. if (!is_numeric($postarray['prefid'])) {
  2170. $_SESSION['return'] = array(
  2171. 'type' => 'danger',
  2172. 'msg' => sprintf($lang['danger']['access_denied'])
  2173. );
  2174. return false;
  2175. }
  2176. try {
  2177. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :object AND `prefid` = :prefid");
  2178. $stmt->execute(array(
  2179. ':object' => $object,
  2180. ':prefid' => $postarray['prefid']
  2181. ));
  2182. }
  2183. catch (PDOException $e) {
  2184. $_SESSION['return'] = array(
  2185. 'type' => 'danger',
  2186. 'msg' => 'MySQL: '.$e
  2187. );
  2188. return false;
  2189. }
  2190. $_SESSION['return'] = array(
  2191. 'type' => 'success',
  2192. 'msg' => sprintf($lang['success']['mailbox_modified'], $object)
  2193. );
  2194. return true;
  2195. }
  2196. if (!ctype_alnum(str_replace(array('@', '.', '-', '*'), '', $object_from))) {
  2197. $_SESSION['return'] = array(
  2198. 'type' => 'danger',
  2199. 'msg' => sprintf($lang['danger']['policy_list_from_invalid'])
  2200. );
  2201. return false;
  2202. }
  2203. try {
  2204. $stmt = $pdo->prepare("SELECT `object` FROM `filterconf`
  2205. WHERE (`option` = 'whitelist_from' OR `option` = 'blacklist_from')
  2206. AND `object` = :object
  2207. AND `value` = :object_from");
  2208. $stmt->execute(array(':object' => $object, ':object_from' => $object_from));
  2209. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  2210. }
  2211. catch(PDOException $e) {
  2212. $_SESSION['return'] = array(
  2213. 'type' => 'danger',
  2214. 'msg' => 'MySQL: '.$e
  2215. );
  2216. return false;
  2217. }
  2218. if ($num_results != 0) {
  2219. $_SESSION['return'] = array(
  2220. 'type' => 'danger',
  2221. 'msg' => sprintf($lang['danger']['policy_list_from_exists'])
  2222. );
  2223. return false;
  2224. }
  2225. try {
  2226. $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option` ,`value`)
  2227. VALUES (:object, :object_list, :object_from)");
  2228. $stmt->execute(array(
  2229. ':object' => $object,
  2230. ':object_list' => $object_list,
  2231. ':object_from' => $object_from
  2232. ));
  2233. }
  2234. catch (PDOException $e) {
  2235. $_SESSION['return'] = array(
  2236. 'type' => 'danger',
  2237. 'msg' => 'MySQL: '.$e
  2238. );
  2239. return false;
  2240. }
  2241. $_SESSION['return'] = array(
  2242. 'type' => 'success',
  2243. 'msg' => sprintf($lang['success']['mailbox_modified'], $object)
  2244. );
  2245. }
  2246. function set_tls_policy($postarray) {
  2247. global $lang;
  2248. global $pdo;
  2249. isset($postarray['tls_in']) ? $tls_in = '1' : $tls_in = '0';
  2250. isset($postarray['tls_out']) ? $tls_out = '1' : $tls_out = '0';
  2251. $username = $_SESSION['mailcow_cc_username'];
  2252. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  2253. $_SESSION['return'] = array(
  2254. 'type' => 'danger',
  2255. 'msg' => sprintf($lang['danger']['username_invalid'])
  2256. );
  2257. return false;
  2258. }
  2259. try {
  2260. $stmt = $pdo->prepare("UPDATE `mailbox` SET `tls_enforce_out` = :tls_out, `tls_enforce_in` = :tls_in WHERE `username` = :username");
  2261. $stmt->execute(array(
  2262. ':tls_out' => $tls_out,
  2263. ':tls_in' => $tls_in,
  2264. ':username' => $username
  2265. ));
  2266. }
  2267. catch (PDOException $e) {
  2268. $_SESSION['return'] = array(
  2269. 'type' => 'danger',
  2270. 'msg' => 'MySQL: '.$e
  2271. );
  2272. return false;
  2273. }
  2274. $_SESSION['return'] = array(
  2275. 'type' => 'success',
  2276. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  2277. );
  2278. }
  2279. function get_tls_policy($username) {
  2280. global $lang;
  2281. global $pdo;
  2282. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  2283. $_SESSION['return'] = array(
  2284. 'type' => 'danger',
  2285. 'msg' => sprintf($lang['danger']['username_invalid'])
  2286. );
  2287. return false;
  2288. }
  2289. try {
  2290. $stmt = $pdo->prepare("SELECT `tls_enforce_out`, `tls_enforce_in` FROM `mailbox` WHERE `username` = :username");
  2291. $stmt->execute(array(':username' => $username));
  2292. $TLSData = $stmt->fetch(PDO::FETCH_ASSOC);
  2293. }
  2294. catch(PDOException $e) {
  2295. $_SESSION['return'] = array(
  2296. 'type' => 'danger',
  2297. 'msg' => 'MySQL: '.$e
  2298. );
  2299. return false;
  2300. }
  2301. return $TLSData;
  2302. }
  2303. function remaining_specs($domain, $object = null, $js = null) {
  2304. // left_m without object given = MiB left in domain
  2305. // left_m with object given = Max. MiB we can assign to given object
  2306. // limit_m = Domain limit in MiB
  2307. // left_c = Mailboxes we can create depending on domain quota
  2308. global $pdo;
  2309. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
  2310. return false;
  2311. }
  2312. try {
  2313. $stmt = $pdo->prepare("SELECT `mailboxes`, `maxquota`, `quota` FROM `domain` WHERE `domain` = :domain");
  2314. $stmt->execute(array(':domain' => $domain));
  2315. $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
  2316. $stmt = $pdo->prepare("SELECT COUNT(*) AS `count`, COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `in_use_m` FROM `mailbox` WHERE `domain` = :domain AND `username` != :object");
  2317. $stmt->execute(array(':domain' => $domain, ':object' => $object));
  2318. $MailboxDataDomain = $stmt->fetch(PDO::FETCH_ASSOC);
  2319. $quota_left_m = $DomainData['quota'] - $MailboxDataDomain['in_use_m'];
  2320. $mboxs_left = $DomainData['mailboxes'] - $MailboxDataDomain['count'];
  2321. if ($quota_left_m > $DomainData['maxquota']) {
  2322. $quota_left_m = $DomainData['maxquota'];
  2323. }
  2324. }
  2325. catch (PDOException $e) {
  2326. return false;
  2327. }
  2328. if (is_numeric($quota_left_m)) {
  2329. $spec['left_m'] = $quota_left_m;
  2330. $spec['limit_m'] = $DomainData['maxquota'];
  2331. }
  2332. if (is_numeric($mboxs_left)) {
  2333. $spec['left_c'] = $mboxs_left;
  2334. }
  2335. if (!empty($js)) {
  2336. echo $quota_left_m;
  2337. exit;
  2338. }
  2339. return $spec;
  2340. }
  2341. function get_sender_acl_handles($mailbox, $which) {
  2342. global $pdo;
  2343. if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
  2344. return false;
  2345. }
  2346. switch ($which) {
  2347. case "preselected":
  2348. try {
  2349. $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` = :goto AND `address` NOT LIKE '@%'");
  2350. $stmt->execute(array(':goto' => $mailbox));
  2351. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  2352. return $rows;
  2353. }
  2354. catch(PDOException $e) {
  2355. $_SESSION['return'] = array(
  2356. 'type' => 'danger',
  2357. 'msg' => 'MySQL: '.$e
  2358. );
  2359. return false;
  2360. }
  2361. break;
  2362. case "selected":
  2363. try {
  2364. $stmt = $pdo->prepare("SELECT `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as");
  2365. $stmt->execute(array(':logged_in_as' => $mailbox));
  2366. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  2367. return $rows;
  2368. }
  2369. catch(PDOException $e) {
  2370. $_SESSION['return'] = array(
  2371. 'type' => 'danger',
  2372. 'msg' => 'MySQL: '.$e
  2373. );
  2374. return false;
  2375. }
  2376. break;
  2377. case "unselected-domains":
  2378. try {
  2379. if ($_SESSION['mailcow_cc_role'] == "admin" ) {
  2380. $stmt = $pdo->prepare("SELECT DISTINCT `domain` FROM `domain`
  2381. WHERE `domain` NOT IN (
  2382. SELECT REPLACE(`send_as`, '@', '') FROM `sender_acl`
  2383. WHERE `logged_in_as` = :logged_in_as)
  2384. AND `domain` NOT IN (
  2385. SELECT REPLACE(`address`, '@', '') FROM `alias`
  2386. WHERE `goto` = :goto)");
  2387. $stmt->execute(array(
  2388. ':logged_in_as' => $mailbox,
  2389. ':goto' => $mailbox,
  2390. ));
  2391. }
  2392. else {
  2393. $stmt = $pdo->prepare("SELECT DISTINCT `domain` FROM `domain_admins`
  2394. WHERE `username` = :username
  2395. AND `domain` != 'ALL'
  2396. AND `domain` NOT IN (
  2397. SELECT REPLACE(`send_as`, '@', '') FROM `sender_acl`
  2398. WHERE `logged_in_as` = :logged_in_as)");
  2399. $stmt->execute(array(
  2400. ':logged_in_as' => $mailbox,
  2401. ':username' => $_SESSION['mailcow_cc_username']
  2402. ));
  2403. }
  2404. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  2405. return $rows;
  2406. }
  2407. catch(PDOException $e) {
  2408. $_SESSION['return'] = array(
  2409. 'type' => 'danger',
  2410. 'msg' => 'MySQL: '.$e
  2411. );
  2412. return false;
  2413. }
  2414. break;
  2415. case "unselected-addresses":
  2416. try {
  2417. if ($_SESSION['mailcow_cc_role'] == "admin" ) {
  2418. $stmt = $pdo->prepare("SELECT `address` FROM `alias`
  2419. WHERE `goto` != :goto
  2420. AND `address` NOT IN (
  2421. SELECT `send_as` FROM `sender_acl`
  2422. WHERE `logged_in_as` = :logged_in_as)");
  2423. $stmt->execute(array(
  2424. ':logged_in_as' => $mailbox,
  2425. ':goto' => $mailbox
  2426. ));
  2427. }
  2428. else {
  2429. $stmt = $pdo->prepare("SELECT `address` FROM `alias`
  2430. WHERE `goto` != :goto
  2431. AND `domain` IN (
  2432. SELECT `domain` FROM `domain_admins`
  2433. WHERE `username` = :username)
  2434. AND `address` NOT IN (
  2435. SELECT `send_as` FROM `sender_acl`
  2436. WHERE `logged_in_as` = :logged_in_as)");
  2437. $stmt->execute(array(
  2438. ':logged_in_as' => $mailbox,
  2439. ':goto' => $mailbox,
  2440. ':username' => $_SESSION['mailcow_cc_username']
  2441. ));
  2442. }
  2443. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  2444. return $rows;
  2445. }
  2446. catch(PDOException $e) {
  2447. $_SESSION['return'] = array(
  2448. 'type' => 'danger',
  2449. 'msg' => 'MySQL: '.$e
  2450. );
  2451. return false;
  2452. }
  2453. break;
  2454. }
  2455. return false;
  2456. }
  2457. function is_valid_domain_name($domain_name) {
  2458. if (empty($domain_name)) {
  2459. return false;
  2460. }
  2461. $domain_name = idn_to_ascii($domain_name);
  2462. return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
  2463. && preg_match("/^.{1,253}$/", $domain_name)
  2464. && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
  2465. }
  2466. ?>