functions.inc.php 75 KB

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