functions.inc.php 90 KB

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