functions.inc.php 75 KB

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