From 4146cec3b9abf44227c9c8b0e4f47ee0b722fdd3 Mon Sep 17 00:00:00 2001
From: andryyy <andre.peters@debinux.de>
Date: Sun, 15 Jan 2017 17:39:17 +0100
Subject: [PATCH] Some changes in functions

---
 data/web/add.php                   |  14 +-
 data/web/edit.php                  |  14 +-
 data/web/inc/functions.inc.php     | 871 ++++++++++++++++++++++-------
 data/web/inc/header.inc.php        |   6 +-
 data/web/inc/init.sql              | 259 ++++-----
 data/web/inc/prerequisites.inc.php |  17 +-
 data/web/inc/triggers.inc.php      |  14 +
 data/web/js/user.js                |   5 +-
 data/web/lang/lang.de.php          |  11 +-
 data/web/lang/lang.en.php          |   9 +-
 data/web/mailbox.php               | 334 ++++-------
 data/web/user.php                  |  72 ++-
 12 files changed, 1010 insertions(+), 616 deletions(-)

diff --git a/data/web/add.php b/data/web/add.php
index e7b73d13..276082df 100644
--- a/data/web/add.php
+++ b/data/web/add.php
@@ -259,7 +259,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 	<?php
 	}
 }
-if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "user")) {
+elseif (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "user")) {
   if (isset($_GET['syncjob'])) {
 ?>
 				<h4><?=$lang['add']['syncjob'];?></h4>
@@ -305,6 +305,18 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "use
               <input type="number" class="form-control" name="mins_interval" min="10" max="3600" value="20" required>
 						</div>
 					</div>
+					<div class="form-group">
+						<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
+						<div class="col-sm-10">
+						<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="External">
+						</div>
+					</div>
+					<div class="form-group">
+						<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
+						<div class="col-sm-10">
+						<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="0">
+						</div>
+					</div>
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
 						<div class="col-sm-10">
diff --git a/data/web/edit.php b/data/web/edit.php
index b89ba1cd..3ab5fff0 100644
--- a/data/web/edit.php
+++ b/data/web/edit.php
@@ -517,7 +517,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 	<?php
 	}
 }
-if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "user")) {
+elseif (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "user")) {
 	if (isset($_GET['syncjob']) &&
     is_numeric($_GET["syncjob"]) &&
     filter_var($_SESSION['mailcow_cc_username'], FILTER_VALIDATE_EMAIL)) {
@@ -582,6 +582,18 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "use
               <input type="number" class="form-control" name="mins_interval" min="10" max="3600" value="<?=htmlspecialchars($result['mins_interval'], ENT_QUOTES, 'UTF-8');?>" required>
 						</div>
 					</div>
+					<div class="form-group">
+						<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
+						<div class="col-sm-10">
+						<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="<?=htmlspecialchars($result['subfolder2'], ENT_QUOTES, 'UTF-8');?>">
+						</div>
+					</div>
+					<div class="form-group">
+						<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
+						<div class="col-sm-10">
+						<input type="number" class="form-control" name="maxage" id="maxage" value="<?=htmlspecialchars($result['maxage'], ENT_QUOTES, 'UTF-8');?>">
+						</div>
+					</div>
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="exclude"><?=$lang['edit']['exclude'];?></label>
 						<div class="col-sm-10">
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index 5ed427b2..c21b6d2a 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -36,7 +36,7 @@ function hasDomainAccess($username, $role, $domain) {
 function init_db_schema() {
 	global $pdo;
 	try {
-		$stmt = $pdo->prepare("SELECT `username` FROM `admin`");
+		$stmt = $pdo->prepare("SELECT NULL FROM `admin`, `imapsync`");
 		$stmt->execute();
 	}
 	catch (Exception $e) {
@@ -84,30 +84,6 @@ function init_db_schema() {
   if ($num_results == 0) {
     $pdo->query("ALTER TABLE `mailbox` ADD `wants_tagged_subject` tinyint(1) NOT NULL DEFAULT '0'");
   }
-  $stmt = $pdo->query("SELECT * FROM information_schema.TABLES WHERE TABLE_NAME = 'imapsync'");
-  $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
-
-  if ($num_results == 0) {
-    $pdo->query("CREATE TABLE IF NOT EXISTS `imapsync` (
-      `id` int NOT NULL AUTO_INCREMENT,
-      `user2` VARCHAR(255) NOT NULL,
-      `host1` VARCHAR(255) NOT NULL,
-      `authmech1` ENUM('PLAIN','LOGIN','CRAM-MD5') DEFAULT 'PLAIN',
-      `user1` VARCHAR(255) NOT NULL,
-      `exclude` VARCHAR(500) NOT NULL DEFAULT '',
-      `password1` VARCHAR(255) NOT NULL,
-      `mins_interval` VARCHAR(50) NOT NULL,
-      `port1` SMALLINT NOT NULL,
-      `enc1` ENUM('TLS','SSL','PLAIN') DEFAULT 'TLS',
-      `delete2duplicates` TINYINT(1) NOT NULL DEFAULT '1',
-      `returned_text` TEXT,
-      `last_run` TIMESTAMP NULL DEFAULT NULL,
-      `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-      `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-      `active` TINYINT(1) NOT NULL DEFAULT '0',
-      PRIMARY KEY (`id`)
-    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;");
-  }
 }
 function verify_ssha256($hash, $password) {
 	// Remove tag if any
@@ -286,6 +262,16 @@ function dkim_table($action, $item) {
 	}
 }
 function mailbox_add_domain($postarray) {
+  // Array elements
+  // domain                 string
+  // description            string
+  // aliases                int
+  // mailboxes              int
+  // maxquota               int
+  // quota                  int
+  // active                 int
+  // relay_all_recipients   int
+  // backupmx               int
 	global $pdo;
 	global $lang;
 	if ($_SESSION['mailcow_cc_role'] != "admin") {
@@ -296,9 +282,9 @@ function mailbox_add_domain($postarray) {
 		return false;
 	}
 	$domain				= idn_to_ascii(strtolower(trim($postarray['domain'])));
-	$description		= $postarray['description'];
+	$description  = $postarray['description'];
 	$aliases			= $postarray['aliases'];
-	$mailboxes			= $postarray['mailboxes'];
+	$mailboxes    = $postarray['mailboxes'];
 	$maxquota			= $postarray['maxquota'];
 	$quota				= $postarray['quota'];
 
@@ -310,10 +296,10 @@ function mailbox_add_domain($postarray) {
 		return false;
 	}
 
-	isset($postarray['active'])					? $active = '1' : $active = '0';
-	isset($postarray['relay_all_recipients'])	? $relay_all_recipients = '1' : $relay_all_recipients = '0';
-	isset($postarray['backupmx'])				? $backupmx = '1' : $backupmx = '0';
-	isset($postarray['relay_all_recipients'])	? $backupmx = '1' : true;
+	isset($postarray['active'])               ? $active = '1'                 : $active = '0';
+	isset($postarray['relay_all_recipients'])	? $relay_all_recipients = '1'   : $relay_all_recipients = '0';
+	isset($postarray['backupmx'])             ? $backupmx = '1'               : $backupmx = '0';
+	isset($postarray['relay_all_recipients']) ? $backupmx = '1'               : true;
 
 	if (!is_valid_domain_name($domain)) {
 		$_SESSION['return'] = array(
@@ -374,12 +360,6 @@ function mailbox_add_domain($postarray) {
 			':modified' => date('Y-m-d H:i:s'),
 			':relay_all_recipients' => $relay_all_recipients
 		));
-		//
-		// PoC for a restart with supervisord unix socket
-		// * $sock = stream_socket_client("unix:///var/run/controller/supervisord.sock", $errno, $errstr, 30);
-		// * fwrite($sock, "GET ?processname=sogo&action=restart HTTP/1.0\r\nAccept: */*\r\n\r\n");
-		// * fclose($sock);
-		//
 		$_SESSION['return'] = array(
 			'type' => 'success',
 			'msg' => sprintf($lang['success']['domain_added'], htmlspecialchars($domain))
@@ -394,10 +374,14 @@ function mailbox_add_domain($postarray) {
 	}
 }
 function mailbox_add_alias($postarray) {
+  // Array elements
+  // address  string  (separated by " ", "," ";" "\n") - email address or domain
+  // goto     string  (separated by " ", "," ";" "\n")
+  // active   int
 	global $lang;
 	global $pdo;
-	$addresses		= array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['address']));
-	$gotos			= array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['goto']));
+	$addresses  = array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['address']));
+	$gotos      = array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['goto']));
 	isset($postarray['active']) ? $active = '1' : $active = '0';
 	if (empty($addresses[0])) {
 		$_SESSION['return'] = array(
@@ -420,9 +404,30 @@ function mailbox_add_alias($postarray) {
 			continue;
 		}
 
-		$domain			= idn_to_ascii(substr(strstr($address, '@'), 1));
-		$local_part		= strstr($address, '@', true);
-		$address		= $local_part.'@'.$domain;
+		$domain       = idn_to_ascii(substr(strstr($address, '@'), 1));
+		$local_part   = strstr($address, '@', true);
+		$address      = $local_part.'@'.$domain;
+
+		try {
+			$stmt = $pdo->prepare("SELECT `domain` FROM `domain`
+				WHERE `domain`= :domain");
+			$stmt->execute(array(':domain' => $domain));
+			$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+		}
+		catch(PDOException $e) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => 'MySQL: '.$e
+			);
+			return false;
+		}
+		if ($num_results == 0) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => sprintf($lang['danger']['domain_not_found'], $domain)
+			);
+			return false;
+		}
 
 		if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) {
 			$_SESSION['return'] = array(
@@ -553,11 +558,17 @@ function mailbox_add_alias($postarray) {
 	);
 }
 function mailbox_add_alias_domain($postarray) {
+  // Array elements
+  // active         int
+  // alias_domain   string
+  // target_domain  string
 	global $lang;
 	global $pdo;
 	isset($postarray['active']) ? $active = '1' : $active = '0';
+	$alias_domain     = idn_to_ascii(strtolower(trim($postarray['alias_domain'])));
+	$target_domain    = idn_to_ascii(strtolower(trim($postarray['target_domain'])));
 
-	if (!is_valid_domain_name($postarray['alias_domain'])) {
+	if (!is_valid_domain_name($alias_domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'msg' => sprintf($lang['danger']['alias_domain_invalid'])
@@ -565,7 +576,7 @@ function mailbox_add_alias_domain($postarray) {
 		return false;
 	}
 
-	if (!is_valid_domain_name($postarray['target_domain'])) {
+	if (!is_valid_domain_name($target_domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'msg' => sprintf($lang['danger']['target_domain_invalid'])
@@ -573,7 +584,7 @@ function mailbox_add_alias_domain($postarray) {
 		return false;
 	}
 
-	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['target_domain'])) {
+	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $target_domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'msg' => sprintf($lang['danger']['access_denied'])
@@ -581,7 +592,7 @@ function mailbox_add_alias_domain($postarray) {
 		return false;
 	}
 
-	if ($postarray['alias_domain'] == $postarray['target_domain']) {
+	if ($alias_domain == $target_domain) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'msg' => sprintf($lang['danger']['aliasd_targetd_identical'])
@@ -589,9 +600,6 @@ function mailbox_add_alias_domain($postarray) {
 		return false;
 	}
 
-	$alias_domain	= strtolower(trim($postarray['alias_domain']));
-	$target_domain	= strtolower(trim($postarray['target_domain']));
-
 	try {
 		$stmt = $pdo->prepare("SELECT `domain` FROM `domain`
 			WHERE `domain`= :target_domain");
@@ -660,12 +668,15 @@ function mailbox_add_alias_domain($postarray) {
 
 }
 function mailbox_edit_alias_domain($postarray) {
+  // Array elements
+  // active             int
+  // alias_domain_now   string
+  // alias_domain       string
 	global $lang;
 	global $pdo;
 	isset($postarray['active']) ? $active = '1' : $active = '0';
-	$alias_domain		= idn_to_ascii($postarray['alias_domain']);
-	$alias_domain		= strtolower(trim($alias_domain));
-	$alias_domain_now	= strtolower(trim($postarray['alias_domain_now']));
+	$alias_domain       = idn_to_ascii(strtolower(trim($postarray['alias_domain'])));
+	$alias_domain_now   = strtolower(trim($postarray['alias_domain_now']));
 	if (!is_valid_domain_name($alias_domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
@@ -746,9 +757,21 @@ function mailbox_edit_alias_domain($postarray) {
 	);
 }
 function mailbox_add_mailbox($postarray) {
+  // Array elements
+  // active             int
+  // local_part         string
+  // domain             string
+  // name               string    (username if empty)
+  // password           string
+  // password2          string
+  // quota              int       (MiB)
+  // active             int
+
 	global $pdo;
 	global $lang;
-	$username = strtolower(trim($postarray['local_part'])).'@'.strtolower(trim($postarray['domain']));
+	$local_part   = strtolower(trim($postarray['local_part']));
+	$domain       = idn_to_ascii(strtolower(trim($postarray['domain'])));
+  $username     = $local_part . '@' . $domain;
 	if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
@@ -763,12 +786,10 @@ function mailbox_add_mailbox($postarray) {
 		);
 		return false;
 	}
-	$domain			= strtolower(trim($postarray['domain']));
-	$password		= $postarray['password'];
-	$password2		= $postarray['password2'];
-	$local_part		= strtolower(trim($postarray['local_part']));
-	$name			= $postarray['name'];
-	$quota_m		= $postarray['quota'];
+	$password     = $postarray['password'];
+	$password2    = $postarray['password2'];
+	$name         = $postarray['name'];
+  $quota_m			= filter_var($postarray['quota'], FILTER_SANITIZE_NUMBER_FLOAT);
 
 	if (empty($name)) {
 		$name = $local_part;
@@ -935,7 +956,7 @@ function mailbox_add_mailbox($postarray) {
 	if ($num_results == 0) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
-			'msg' => $lang['danger']['domain_not_found']
+      'msg' => sprintf($lang['danger']['domain_not_found'], $domain)
 		);
 		return false;
 	}
@@ -1002,11 +1023,15 @@ function mailbox_add_mailbox($postarray) {
 	}
 }
 function mailbox_edit_alias($postarray) {
+  // Array elements
+  // address            string
+  // goto               string    (separated by " ", "," ";" "\n") - email address or domain
+  // active             int
 	global $lang;
 	global $pdo;
-	$address	= $postarray['address'];
-	$domain		= idn_to_ascii(substr(strstr($address, '@'), 1));
-	$local_part	= strstr($address, '@', true);
+	$address      = $postarray['address'];
+	$domain       = idn_to_ascii(substr(strstr($address, '@'), 1));
+	$local_part   = strstr($address, '@', true);
 	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
@@ -1073,13 +1098,25 @@ function mailbox_edit_alias($postarray) {
 	}
 }
 function mailbox_edit_domain($postarray) {
+  // Array elements
+  // domain                 string
+  // description            string
+  // active                 int
+  // relay_all_recipients   int
+  // backupmx               int
+  // aliases                float
+  // mailboxes              float
+  // maxquota               float
+  // quota                  float     (Byte)
+  // active                 int
+
 	global $lang;
 	global $pdo;
-	$domain			= $postarray['domain'];
-	$description	= $postarray['description'];
+	$domain       = idn_to_ascii($postarray['domain']);
+	$description  = $postarray['description'];
 
 	$aliases		= filter_var($postarray['aliases'], FILTER_SANITIZE_NUMBER_FLOAT);
-	$mailboxes		= filter_var($postarray['mailboxes'], FILTER_SANITIZE_NUMBER_FLOAT);
+	$mailboxes  = filter_var($postarray['mailboxes'], FILTER_SANITIZE_NUMBER_FLOAT);
 	$maxquota		= filter_var($postarray['maxquota'], FILTER_SANITIZE_NUMBER_FLOAT);
 	$quota			= filter_var($postarray['quota'], FILTER_SANITIZE_NUMBER_FLOAT);
 
@@ -1217,122 +1254,337 @@ function mailbox_edit_domain($postarray) {
 	}
 
 }
-function edit_domain_admin($postarray) {
+function mailbox_get_mailboxes($domain) {
 	global $lang;
 	global $pdo;
-	$username		= $postarray['username'];
-	$password		= $postarray['password'];
-	$password2		= $postarray['password2'];
-	isset($postarray['active']) ? $active = '1' : $active = '0';
-
-	if ($_SESSION['mailcow_cc_role'] != "admin") {
+  $mailboxes = array();
+	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
 			'msg' => sprintf($lang['danger']['access_denied'])
 		);
 		return false;
 	}
-	
-	foreach ($postarray['domain'] as $domain) {
-		if (!is_valid_domain_name($domain)) {
-			$_SESSION['return'] = array(
-				'type' => 'danger',
-				'msg' => sprintf($lang['danger']['domain_invalid'])
-			);
-			return false;
-		}
-	}
-
-	if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
+  try {
+    $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `domain` != 'ALL' AND `domain` = :domain");
+    $stmt->execute(array(
+      ':domain' => $domain,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $mailboxes[] = $row['username'];
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  return $mailboxes;
+}
+function mailbox_get_alias_domains($domain) {
+	global $lang;
+	global $pdo;
+  $aliasdomains = array();
+	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['username_invalid'])
+			'msg' => sprintf($lang['danger']['access_denied'])
 		);
 		return false;
 	}
 
-	try {
-		$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
-		$stmt->execute(array(
-			':username' => $username,
-		));
-	}
-	catch (PDOException $e) {
+  try {
+    $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain");
+    $stmt->execute(array(
+      ':domain' => $domain,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $aliasdomains[] = $row['alias_domain'];
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  return $aliasdomains;
+}
+function mailbox_get_aliases($domain) {
+	global $lang;
+	global $pdo;
+  $aliases = array();
+	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
+			'msg' => sprintf($lang['danger']['access_denied'])
 		);
 		return false;
 	}
 
-	foreach ($postarray['domain'] as $domain) {
-		try {
-			$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
-				VALUES (:username, :domain, :created, :active)");
-			$stmt->execute(array(
-				':username' => $username,
-				':domain' => $domain,
-				':created' => date('Y-m-d H:i:s'),
-				':active' => $active
-			));
-		}
-		catch (PDOException $e) {
-			$_SESSION['return'] = array(
-				'type' => 'danger',
-				'msg' => 'MySQL: '.$e
-			);
-			return false;
-		}
+  try {
+    $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `address` != `goto` AND `domain` = :domain");
+    $stmt->execute(array(
+      ':domain' => $domain,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $aliases[] = $row['address'];
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  return $aliases;
+}
+function mailbox_get_alias_details($address) {
+	global $lang;
+	global $pdo;
+  $aliasdata = array();
+  try {
+    $stmt = $pdo->prepare("SELECT
+      `domain`,
+      `goto`,
+      `address`,
+      CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
+      `created`,
+      `modified`
+        FROM `alias`
+            WHERE `address` = :address AND `address` != `goto`");
+    $stmt->execute(array(
+      ':address' => $address,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $aliasdata['domain'] = $row['domain'];
+      $aliasdata['goto'] = $row['goto'];
+      $aliasdata['address'] = $row['address'];
+      (!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0;
+      $aliasdata['active'] = $row['active'];
+      $aliasdata['created'] = $row['created'];
+      $aliasdata['modified'] = $row['modified'];
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  if (isset($aliasdata['domain']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdata['domain'])) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => sprintf($lang['danger']['access_denied'])
+    );
+    return false;
+  }
+  return $aliasdata;
+}
+function mailbox_get_alias_domain_details($aliasdomain) {
+	global $lang;
+	global $pdo;
+  $aliasdomaindata = array();
+  try {
+    $stmt = $pdo->prepare("SELECT
+      `alias_domain`,
+      `target_domain`,
+      CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
+      `created`,
+      `modified`
+        FROM `alias_domain`
+            WHERE `alias_domain` = :aliasdomain");
+    $stmt->execute(array(
+      ':aliasdomain' => $aliasdomain,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $aliasdomaindata['alias_domain'] = $row['alias_domain'];
+      $aliasdomaindata['target_domain'] = $row['target_domain'];
+      $aliasdomaindata['active'] = $row['active'];
+      $aliasdomaindata['created'] = $row['created'];
+      $aliasdomaindata['modified'] = $row['modified'];
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  if (isset($aliasdomaindata['target_domain']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $aliasdomaindata['target_domain'])) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => sprintf($lang['danger']['access_denied'])
+    );
+    return false;
+  }
+  return $aliasdomaindata;
+}
+function mailbox_get_domains() {
+	global $lang;
+	global $pdo;
+
+  try {
+    $domains = array();
+    $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
+      WHERE (`domain` IN (
+        SELECT `domain` from `domain_admins`
+          WHERE (`active`='1' AND `username` = :username))
+        )
+        OR ('admin'= :role)
+        AND `domain` != 'ALL'");
+    $stmt->execute(array(
+      ':username' => $_SESSION['mailcow_cc_username'],
+      ':role' => $_SESSION['mailcow_cc_role'],
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $domains[] = $row['domain'];
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  return $domains;
+}
+function mailbox_get_domain_details($domain) {
+	global $lang;
+	global $pdo;
+
+	$domain = idn_to_ascii(strtolower(trim($domain)));
+
+	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
+		$_SESSION['return'] = array(
+			'type' => 'danger',
+			'msg' => sprintf($lang['danger']['access_denied'])
+		);
+		return false;
 	}
 
-	if (!empty($password) && !empty($password2)) {
-		if ($password != $password2) {
-			$_SESSION['return'] = array(
-				'type' => 'danger',
-				'msg' => sprintf($lang['danger']['password_mismatch'])
-			);
-			return false;
-		}
-		$password_hashed = hash_password($password);
-		try {
-			$stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
-			$stmt->execute(array(
-				':password_hashed' => $password_hashed,
-				':username' => $username,
-				':modified' => date('Y-m-d H:i:s'),
-				':active' => $active
-			));
-		}
-		catch (PDOException $e) {
-			$_SESSION['return'] = array(
-				'type' => 'danger',
-				'msg' => 'MySQL: '.$e
-			);
-			return false;
-		}
-	}
-	else {
-		try {
-			$stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `active` = :active WHERE `username` = :username");
-			$stmt->execute(array(
-				':username' => $username,
-				':modified' => date('Y-m-d H:i:s'),
-				':active' => $active
-			));
-		}
-		catch (PDOException $e) {
-			$_SESSION['return'] = array(
-				'type' => 'danger',
-				'msg' => 'MySQL: '.$e
-			);
-			return false;
-		}
-	}
+  try {
+    $stmt = $pdo->prepare("SELECT 
+        `domain`,
+        `aliases`,
+        `mailboxes`, 
+        `maxquota`,
+        `quota`,
+        CASE `backupmx` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `backupmx`,
+        CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
+          FROM `domain` WHERE `domain`= :domain");
+    $stmt->execute(array(
+      ':domain' => $domain,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $domaindata['domain_name'] = $row['domain'];
+      $domaindata['max_num_aliases_for_domain'] = $row['aliases'];
+      $domaindata['max_num_mboxes_for_domain'] = $row['mailboxes'];
+      $domaindata['max_quota_for_mbox'] = formatBytes(intval($row['maxquota'] * 1048576), 2);
+      $domaindata['max_quota_for_domain'] = formatBytes(intval($row['quota'] * 1048576), 2);
+      $domaindata['backupmx'] = $row['backupmx'];
+      $domaindata['active'] = $row['active'];
+    }
 
-	$_SESSION['return'] = array(
-		'type' => 'success',
-		'msg' => sprintf($lang['success']['domain_admin_modified'], htmlspecialchars($username))
-	);
+    $stmt = $pdo->prepare("SELECT COUNT(*) AS `alias_count` FROM `alias`
+      WHERE `domain`= :domain
+        AND `address` NOT IN (
+          SELECT `username` FROM `mailbox`
+        )");
+    $stmt->execute(array(
+      ':domain' => $domain,
+    ));
+    $row = $stmt->fetchAll();
+    $domaindata['aliases_in_domain'] = $row[0]['alias_count'];
+
+    $stmt = $pdo->prepare("SELECT COUNT(`username`) AS `mailbox_count`, SUM(`quota`) AS `quota` FROM `mailbox`
+        WHERE `domain` = :domain");
+    $stmt->execute(array(
+      ':domain' => $domain,
+    ));
+    $row = $stmt->fetchAll();
+    $domaindata['mboxes_in_domain'] = $row[0]['mailbox_count'];
+    $domaindata['quota_used_in_domain'] = formatBytes(intval($row[0]['quota']), 2);
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+
+  return $domaindata;
+}
+function mailbox_get_mailbox_details($mailbox) {
+	global $lang;
+	global $pdo;
+  try {
+    $stmt = $pdo->prepare("SELECT
+        `domain`.`backupmx`,
+        `mailbox`.`username`,
+        `mailbox`.`name`,
+        CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
+        `mailbox`.`domain`,
+        `mailbox`.`quota`,
+        `quota2`.`bytes`,
+        `quota2`.`messages`
+          FROM `mailbox`, `quota2`, `domain`
+            WHERE `mailbox`.`username` = `quota2`.`username` AND `domain`.`domain` = `mailbox`.`domain` AND `mailbox`.`username` = :mailbox");
+    $stmt->execute(array(
+      ':mailbox' => $mailbox,
+    ));
+    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while($row = array_shift($rows)) {
+      $mailboxdata['username'] = $row['username'];
+      $mailboxdata['is_relayed'] = $row['backupmx'];
+      $mailboxdata['name'] = $row['name'];
+      $mailboxdata['active'] = $row['active'];
+      $mailboxdata['domain'] = $row['domain'];
+      $mailboxdata['quota'] = formatBytes(intval($row['quota']), 2);
+      $mailboxdata['quota_used'] = formatBytes(intval($row['bytes']), 2);
+      $mailboxdata['percent_in_use'] = round((intval($row['bytes']) / intval($row['quota'])) * 100);
+      $mailboxdata['messages'] = $row['messages'];
+      if ($mailboxdata['percent_in_use'] >= 90) {
+        $mailboxdata['percent_class'] = "danger";
+      }
+      elseif ($mailboxdata['percent_in_use'] >= 75) {
+        $mailboxdata['percent_class'] = "warning";
+      }
+      else {
+        $mailboxdata['percent_class'] = "success";
+      }
+    }
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+  if (isset($mailboxdata['domain']) && !hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $mailboxdata['domain'])) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => sprintf($lang['danger']['access_denied'])
+    );
+    return false;
+  }
+  return $mailboxdata;
 }
 function mailbox_edit_mailbox($postarray) {
 	global $lang;
@@ -1808,6 +2060,122 @@ function mailbox_delete_mailbox($postarray) {
 		'msg' => sprintf($lang['success']['mailbox_removed'], htmlspecialchars($username))
 	);
 }
+function edit_domain_admin($postarray) {
+	global $lang;
+	global $pdo;
+	$username     = $postarray['username'];
+	$password     = $postarray['password'];
+	$password2    = $postarray['password2'];
+	isset($postarray['active']) ? $active = '1' : $active = '0';
+
+	if ($_SESSION['mailcow_cc_role'] != "admin") {
+		$_SESSION['return'] = array(
+			'type' => 'danger',
+			'msg' => sprintf($lang['danger']['access_denied'])
+		);
+		return false;
+	}
+	
+	foreach ($postarray['domain'] as $domain) {
+		if (!is_valid_domain_name($domain)) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => sprintf($lang['danger']['domain_invalid'])
+			);
+			return false;
+		}
+	}
+
+	if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
+		$_SESSION['return'] = array(
+			'type' => 'danger',
+			'msg' => sprintf($lang['danger']['username_invalid'])
+		);
+		return false;
+	}
+
+	try {
+		$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
+		$stmt->execute(array(
+			':username' => $username,
+		));
+	}
+	catch (PDOException $e) {
+		$_SESSION['return'] = array(
+			'type' => 'danger',
+			'msg' => 'MySQL: '.$e
+		);
+		return false;
+	}
+
+	foreach ($postarray['domain'] as $domain) {
+		try {
+			$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
+				VALUES (:username, :domain, :created, :active)");
+			$stmt->execute(array(
+				':username' => $username,
+				':domain' => $domain,
+				':created' => date('Y-m-d H:i:s'),
+				':active' => $active
+			));
+		}
+		catch (PDOException $e) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => 'MySQL: '.$e
+			);
+			return false;
+		}
+	}
+
+	if (!empty($password) && !empty($password2)) {
+		if ($password != $password2) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => sprintf($lang['danger']['password_mismatch'])
+			);
+			return false;
+		}
+		$password_hashed = hash_password($password);
+		try {
+			$stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
+			$stmt->execute(array(
+				':password_hashed' => $password_hashed,
+				':username' => $username,
+				':modified' => date('Y-m-d H:i:s'),
+				':active' => $active
+			));
+		}
+		catch (PDOException $e) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => 'MySQL: '.$e
+			);
+			return false;
+		}
+	}
+	else {
+		try {
+			$stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `active` = :active WHERE `username` = :username");
+			$stmt->execute(array(
+				':username' => $username,
+				':modified' => date('Y-m-d H:i:s'),
+				':active' => $active
+			));
+		}
+		catch (PDOException $e) {
+			$_SESSION['return'] = array(
+				'type' => 'danger',
+				'msg' => 'MySQL: '.$e
+			);
+			return false;
+		}
+	}
+	$_SESSION['return'] = array(
+		'type' => 'success',
+		'msg' => sprintf($lang['success']['domain_admin_modified'], htmlspecialchars($username))
+	);
+}
 function set_admin_account($postarray) {
 	global $lang;
 	global $pdo;
@@ -1912,11 +2280,19 @@ function set_time_limited_aliases($postarray) {
 	global $lang;
 	global $pdo;
 	$username	= $_SESSION['mailcow_cc_username'];
-	$domain		= substr($username, strpos($username, '@'));
-	if (($_SESSION['mailcow_cc_role'] != "user" &&
-		$_SESSION['mailcow_cc_role'] != "domainadmin") || 
-			empty($username) ||
-			empty($domain)) {
+	try {
+    $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :username");
+    $stmt->execute(array(':username' => $username));
+    $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain'];
+  }
+  catch (PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
+  }
+	if ($_SESSION['mailcow_cc_role'] != "user" || empty($username) || empty($domain)) {
 				$_SESSION['return'] = array(
 					'type' => 'danger',
 					'msg' => sprintf($lang['danger']['access_denied'])
@@ -1939,7 +2315,7 @@ function set_time_limited_aliases($postarray) {
 				$stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES
 					(:address, :goto, :validity)");
 				$stmt->execute(array(
-					':address' => $random_name.$domain,
+					':address' => $random_name . '@' . $domain,
 					':goto' => $username,
 					':validity' => $validity
 				));
@@ -1956,7 +2332,7 @@ function set_time_limited_aliases($postarray) {
 				'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
 			);
 		break;
-		case "delete":
+		case "deleteall":
 			try {
 				$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
 				$stmt->execute(array(
@@ -1975,6 +2351,34 @@ function set_time_limited_aliases($postarray) {
 				'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
 			);
 		break;
+		case "delete":
+			if (empty($postarray['item']) || !filter_var($postarray['item'], FILTER_VALIDATE_EMAIL)) {
+				$_SESSION['return'] = array(
+					'type' => 'danger',
+					'msg' => sprintf($lang['danger']['access_denied'])
+				);
+				return false;
+			}
+      $item	= $postarray['item'];
+			try {
+				$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username AND `address` = :item");
+				$stmt->execute(array(
+					':username' => $username,
+					':item' => $item
+				));
+			}
+			catch (PDOException $e) {
+				$_SESSION['return'] = array(
+					'type' => 'danger',
+					'msg' => 'MySQL: '.$e
+				);
+				return false;
+			}	
+			$_SESSION['return'] = array(
+				'type' => 'success',
+				'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
+			);
+		break;
 		case "extend":
 			try {
 				$stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = (`validity` + 3600)
@@ -2538,6 +2942,7 @@ function set_syncjob($postarray, $action) {
     );
     return true;
   }
+  // ADD
   elseif ($action == "add") {
     isset($postarray['active']) ? $active = '1' : $active = '0';
     isset($postarray['delete2duplicates']) ? $delete2duplicates = '1' : $delete2duplicates = '0';
@@ -2545,10 +2950,26 @@ function set_syncjob($postarray, $action) {
     $host1            = $postarray['host1'];
     $password1        = $postarray['password1'];
     $exclude          = $postarray['exclude'];
+    $maxage           = $postarray['maxage'];
+    $subfolder2       = $postarray['subfolder2'];
     $user1            = $postarray['user1'];
     $mins_interval    = $postarray['mins_interval'];
     $enc1             = $postarray['enc1'];
 
+    if (empty($subfolder2)) {
+      $subfolder2 = "";
+    }
+    if (empty($maxage)) {
+      $maxage = 0;
+    }
+
+    if (!filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 0, 'max_range' => 32767)))) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
     if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
       $_SESSION['return'] = array(
         'type' => 'danger',
@@ -2605,11 +3026,13 @@ function set_syncjob($postarray, $action) {
       return false;
     }
     try {
-      $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
-        VALUES (:user2, :exclude, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
+      $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
+        VALUES (:user2, :exclude, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
       $stmt->execute(array(
         ':user2' => $username,
         ':exclude' => $exclude,
+        ':maxage' => $maxage,
+        ':subfolder2' => $subfolder2,
         ':host1' => $host1,
         ':authmech1' => 'PLAIN',
         ':user1' => $user1,
@@ -2634,6 +3057,7 @@ function set_syncjob($postarray, $action) {
     );
     return true;
   }
+  // EDIT
   elseif ($action == "edit") {
     isset($postarray['active']) ? $active = '1' : $active = '0';
     isset($postarray['delete2duplicates']) ? $delete2duplicates = '1' : $delete2duplicates = '0';
@@ -2642,9 +3066,26 @@ function set_syncjob($postarray, $action) {
     $host1            = $postarray['host1'];
     $password1        = $postarray['password1'];
     $exclude          = $postarray['exclude'];
+    $maxage           = $postarray['maxage'];
+    $subfolder2       = $postarray['subfolder2'];
     $user1            = $postarray['user1'];
     $mins_interval    = $postarray['mins_interval'];
     $enc1             = $postarray['enc1'];
+
+    if (empty($subfolder2)) {
+      $subfolder2 = "";
+    }
+    if (empty($maxage)) {
+      $maxage = 0;
+    }
+
+    if (!filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 0, 'max_range' => 32767)))) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
     if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
       $_SESSION['return'] = array(
         'type' => 'danger',
@@ -2701,12 +3142,14 @@ function set_syncjob($postarray, $action) {
       return false;
     }
     try {
-      $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
+      $stmt = $pdo->prepare("UPDATE `imapsync` set `maxage` = :maxage, `subfolder2` = :subfolder2, `exclude` = :exclude, `host1` = :host1, `user1` = :user1, `password1` = :password1, `mins_interval` = :mins_interval, `port1` = :port1, `enc1` = :enc1, `delete2duplicates` = :delete2duplicates, `active` = :active
         WHERE `user2` = :user2 AND `id` = :id");
       $stmt->execute(array(
         ':user2' => $username,
         ':id' => $id,
         ':exclude' => $exclude,
+        ':maxage' => $maxage,
+        ':subfolder2' => $subfolder2,
         ':host1' => $host1,
         ':user1' => $user1,
         ':password1' => $password1,
@@ -2966,50 +3409,58 @@ function tagging_options($action, $data = null) {
   }
   return false;
 }
-function user_object_info($action, $data = null) {
+function user_get_alias_details($username) {
 	global $lang;
 	global $pdo;
-  $username	= $_SESSION['mailcow_cc_username'];
-  if ($action == "get") {
-    if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
-      return false;
-    }
-    try {
-      $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");
-      $stmt->execute(array(':username_goto' => $username, ':username_address' => $username));
-      $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while ($row = array_shift($run)) {
-        $data['aliases'] = $row['aliases'];
-      }
-      $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 '@%';");
-      $stmt->execute(array(':username' => $username));
-      $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while ($row = array_shift($run)) {
-        $data['aliases_also_send_as'] = $row['send_as'];
-      }
-      $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 '@%';");
-      $stmt->execute(array(':username' => $username));
-      $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while ($row = array_shift($run)) {
-        $data['aliases_send_as_all'] = $row['send_as'];
-      }
-      $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '&#10008;') as `address` FROM `alias` WHERE `goto` = :username AND `address` LIKE '@%';");
-      $stmt->execute(array(':username' => $username));
-      $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while ($row = array_shift($run)) {
-        $data['is_catch_all'] = $row['address'];
-      }
-      return $data;
-    }
-    catch(PDOException $e) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => 'MySQL: '.$e
-      );
-      return false;
-    }
+  if ($_SESSION['mailcow_cc_role'] == "user") {
+    $username	= $_SESSION['mailcow_cc_username'];
+  }
+  if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
+    return false;
+  }
+  try {
+    $data['address'] = $username;
+    $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");
+    $stmt->execute(array(':username_goto' => $username, ':username_address' => $username));
+    $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while ($row = array_shift($run)) {
+      $data['aliases'] = $row['aliases'];
+    }
+    $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ', '), '&#10008;') AS `ad_alias` FROM `mailbox`
+      LEFT OUTER JOIN `alias_domain` on `target_domain` = `domain`
+        WHERE `username` = :username ;");
+    $stmt->execute(array(':username' => $username));
+    $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while ($row = array_shift($run)) {
+      $data['ad_alias'] = $row['ad_alias'];
+    }
+    $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 '@%';");
+    $stmt->execute(array(':username' => $username));
+    $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while ($row = array_shift($run)) {
+      $data['aliases_also_send_as'] = $row['send_as'];
+    }
+    $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 '@%';");
+    $stmt->execute(array(':username' => $username));
+    $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while ($row = array_shift($run)) {
+      $data['aliases_send_as_all'] = $row['send_as'];
+    }
+    $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '&#10008;') as `address` FROM `alias` WHERE `goto` = :username AND `address` LIKE '@%';");
+    $stmt->execute(array(':username' => $username));
+    $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
+    while ($row = array_shift($run)) {
+      $data['is_catch_all'] = $row['address'];
+    }
+    return $data;
+  }
+  catch(PDOException $e) {
+    $_SESSION['return'] = array(
+      'type' => 'danger',
+      'msg' => 'MySQL: '.$e
+    );
+    return false;
   }
-  return false;
 }
 function is_valid_domain_name($domain_name) { 
 	if (empty($domain_name)) {
diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php
index d72ec73f..43e1119c 100644
--- a/data/web/inc/header.inc.php
+++ b/data/web/inc/header.inc.php
@@ -232,10 +232,14 @@ endif;
 				?>
 					<?php
 				}
-				if (isset($_SESSION['mailcow_cc_username'])):
+				if (!isset($_SESSION["dual-login"]) && isset($_SESSION['mailcow_cc_username'])):
 				?>
 					<li><a style="border-left:1px solid #E7E7E7" href="#" onclick="logout.submit()"><?=sprintf($lang['header']['logged_in_as_logout'], $_SESSION['mailcow_cc_username']);?></a></li>
 				<?php
+				elseif (isset($_SESSION["dual-login"])):
+				?>
+					<li><a style="border-left:1px solid #E7E7E7" href="#" onclick="logout.submit()"><?=sprintf($lang['header']['logged_in_as_logout_dual'], $_SESSION['mailcow_cc_username'], $_SESSION["dual-login"]["username"]);?></a></li>
+				<?php
 				endif;
 				?>
 			</ul>
diff --git a/data/web/inc/init.sql b/data/web/inc/init.sql
index a85d6bfb..64d7da5a 100644
--- a/data/web/inc/init.sql
+++ b/data/web/inc/init.sql
@@ -1,120 +1,125 @@
 CREATE TABLE IF NOT EXISTS `admin` (
-	`username` varchar(255) NOT NULL,
-	`password` varchar(255) NOT NULL,
-	`superadmin` tinyint(1) NOT NULL DEFAULT '0',
-	`created` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`modified` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`active` tinyint(1) NOT NULL DEFAULT '1',
+	`username` VARCHAR(255) NOT NULL,
+	`password` VARCHAR(255) NOT NULL,
+	`superadmin` TINYINT(1) NOT NULL DEFAULT '0',
+	`created` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`modified` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`active` TINYINT(1) NOT NULL DEFAULT '1',
 	PRIMARY KEY (`username`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `alias` (
-	`address` varchar(255) NOT NULL,
-	`goto` text NOT NULL,
-	`domain` varchar(255) NOT NULL,
-	`created` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`modified` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`active` tinyint(1) NOT NULL DEFAULT '1',
+	`address` VARCHAR(255) NOT NULL,
+	`goto` TEXT NOT NULL,
+	`domain` VARCHAR(255) NOT NULL,
+	`created` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`modified` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`active` TINYINT(1) NOT NULL DEFAULT '1',
 	PRIMARY KEY (`address`),
 	KEY `domain` (`domain`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `sender_acl` (
-	`logged_in_as` varchar(255) NOT NULL,
-	`send_as` varchar(255) NOT NULL
+	`logged_in_as` VARCHAR(255) NOT NULL,
+	`send_as` VARCHAR(255) NOT NULL
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `spamalias` (
-	`address` varchar(255) NOT NULL,
-	`goto` text NOT NULL,
-	`validity` int(11) NOT NULL,
+	`address` VARCHAR(255) NOT NULL,
+	`goto` TEXT NOT NULL,
+	`validity` INT(11) NOT NULL,
 	PRIMARY KEY (`address`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `alias_domain` (
-	`alias_domain` varchar(255) NOT NULL,
-	`target_domain` varchar(255) NOT NULL,
-	`created` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`modified` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`active` tinyint(1) NOT NULL DEFAULT '1',
+	`alias_domain` VARCHAR(255) NOT NULL,
+	`target_domain` VARCHAR(255) NOT NULL,
+	`created` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`modified` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`active` TINYINT(1) NOT NULL DEFAULT '1',
 	PRIMARY KEY (`alias_domain`),
 	KEY `active` (`active`),
 	KEY `target_domain` (`target_domain`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `domain` (
-	`domain` varchar(255) NOT NULL,
-	`description` varchar(255),
-	`aliases` int(10) NOT NULL DEFAULT '0',
-	`mailboxes` int(10) NOT NULL DEFAULT '0',
-	`maxquota` bigint(20) NOT NULL DEFAULT '0',
-	`quota` bigint(20) NOT NULL DEFAULT '0',
-	`transport` varchar(255) NOT NULL,
-	`backupmx` tinyint(1) NOT NULL DEFAULT '0',
-	`relay_all_recipients` tinyint(1) NOT NULL DEFAULT '0',
-	`created` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`modified` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`active` tinyint(1) NOT NULL DEFAULT '1',
+	`domain` VARCHAR(255) NOT NULL,
+	`description` VARCHAR(255),
+	`aliases` INT(10) NOT NULL DEFAULT '0',
+	`mailboxes` INT(10) NOT NULL DEFAULT '0',
+	`maxquota` BIGINT(20) NOT NULL DEFAULT '0',
+	`quota` BIGINT(20) NOT NULL DEFAULT '0',
+	`transport` VARCHAR(255) NOT NULL,
+	`backupmx` TINYINT(1) NOT NULL DEFAULT '0',
+	`relay_all_recipients` TINYINT(1) NOT NULL DEFAULT '0',
+	`created` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`modified` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`active` TINYINT(1) NOT NULL DEFAULT '1',
 	PRIMARY KEY (`domain`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `domain_admins` (
-	`username` varchar(255) NOT NULL,
-	`domain` varchar(255) NOT NULL,
-	`created` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`active` tinyint(1) NOT NULL DEFAULT '1',
+	`username` VARCHAR(255) NOT NULL,
+	`domain` VARCHAR(255) NOT NULL,
+	`created` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`active` TINYINT(1) NOT NULL DEFAULT '1',
 	KEY `username` (`username`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `mailbox` (
-	`username` varchar(255) NOT NULL,
-	`password` varchar(255) NOT NULL,
-	`name` varchar(255),
-	`maildir` varchar(255) NOT NULL,
-	`quota` bigint(20) NOT NULL DEFAULT '0',
-	`local_part` varchar(255) NOT NULL,
-	`domain` varchar(255) NOT NULL,
-	`created` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`modified` datetime NOT NULL DEFAULT '2016-01-01 00:00:00',
-	`tls_enforce_in` tinyint(1) NOT NULL DEFAULT '0',
-	`tls_enforce_out` tinyint(1) NOT NULL DEFAULT '0',
-	`kind` varchar(100) NOT NULL DEFAULT '',
-	`multiple_bookings` tinyint(1) NOT NULL DEFAULT '0',
-	`wants_tagged_subject` tinyint(1) NOT NULL DEFAULT '0',
-	`active` tinyint(1) NOT NULL DEFAULT '1',
+	`username` VARCHAR(255) NOT NULL,
+	`password` VARCHAR(255) NOT NULL,
+	`name` VARCHAR(255),
+	`maildir` VARCHAR(255) NOT NULL,
+	`quota` BIGINT(20) NOT NULL DEFAULT '0',
+	`local_part` VARCHAR(255) NOT NULL,
+	`domain` VARCHAR(255) NOT NULL,
+	`created` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`modified` DATETIME NOT NULL DEFAULT '2016-01-01 00:00:00',
+	`tls_enforce_in` TINYINT(1) NOT NULL DEFAULT '0',
+	`tls_enforce_out` TINYINT(1) NOT NULL DEFAULT '0',
+	`kind` VARCHAR(100) NOT NULL DEFAULT '',
+	`multiple_bookings` TINYINT(1) NOT NULL DEFAULT '0',
+	`wants_tagged_subject` TINYINT(1) NOT NULL DEFAULT '0',
+	`active` TINYINT(1) NOT NULL DEFAULT '1',
 	PRIMARY KEY (`username`),
 	KEY `domain` (`domain`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `quota2` (
-	`username` varchar(100) NOT NULL,
-	`bytes` bigint(20) NOT NULL DEFAULT '0',
-	`messages` int(11) NOT NULL DEFAULT '0',
+	`username` VARCHAR(100) NOT NULL,
+	`bytes` BIGINT(20) NOT NULL DEFAULT '0',
+	`messages` INT(11) NOT NULL DEFAULT '0',
 	PRIMARY KEY (`username`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `filterconf` (
-	`object` varchar(100) NOT NULL DEFAULT '',
-	`option` varchar(50) NOT NULL DEFAULT '',
-	`value` varchar(100) NOT NULL DEFAULT '',
-	`prefid` int(11) NOT NULL AUTO_INCREMENT,
+	`object` VARCHAR(100) NOT NULL DEFAULT '',
+	`option` VARCHAR(50) NOT NULL DEFAULT '',
+	`value` VARCHAR(100) NOT NULL DEFAULT '',
+	`prefid` INT(11) NOT NULL AUTO_INCREMENT,
 	PRIMARY KEY (`prefid`),
 	KEY `object` (`object`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS `imapsync` (
-  `id` int NOT NULL AUTO_INCREMENT,
-  `user2` varchar(255) NOT NULL,
-  `host1` varchar(255) NOT NULL,
+  `id` INT NOT NULL AUTO_INCREMENT,
+  `user2` VARCHAR(255) NOT NULL,
+  `host1` VARCHAR(255) NOT NULL,
   `authmech1` ENUM('PLAIN','LOGIN','CRAM-MD5') DEFAULT 'PLAIN',
-  `user1` varchar(255) NOT NULL,
-  `password1` varchar(255) NOT NULL,
+  `regextrans2` VARCHAR(255) DEFAULT '',
+  `authmd51` TINYINT(1) NOT NULL DEFAULT 0,
+  `domain2` VARCHAR(255) NOT NULL DEFAULT '',
+  `subfolder2` VARCHAR(255) NOT NULL DEFAULT '',
+  `user1` VARCHAR(255) NOT NULL,
+  `password1` VARCHAR(255) NOT NULL,
   `exclude` VARCHAR(500) NOT NULL DEFAULT '',
-  `mins_interval` VARCHAR(50) NOT NULL,
+  `maxage` SMALLINT NOT NULL DEFAULT '0',
+  `mins_INTerval` VARCHAR(50) NOT NULL,
   `port1` SMALLINT NOT NULL,
   `enc1` ENUM('TLS','SSL','PLAIN') DEFAULT 'TLS',
   `delete2duplicates` TINYINT(1) NOT NULL DEFAULT '1',
-  `returned_text` TEXT,
+  `returned_TEXT` TEXT,
   `last_run` TIMESTAMP NULL DEFAULT NULL,
   `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
   `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -143,80 +148,80 @@ SELECT username, IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ' '
 LEFT OUTER JOIN alias_domain on target_domain=domain GROUP BY username;
 
 CREATE TABLE IF NOT EXISTS sogo_acl (
-	c_folder_id integer NOT NULL,
+	c_folder_id INTeger NOT NULL,
 	c_object character varying(255) NOT NULL,
 	c_uid character varying(255) NOT NULL,
 	c_role character varying(80) NOT NULL
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_alarms_folder (
-	c_path          varchar(255) NOT NULL,
-	c_name          varchar(255) NOT NULL,
-	c_uid           varchar(255) NOT NULL,
-	c_recurrence_id int(11)      DEFAULT NULL,
-	c_alarm_number  int(11)      NOT NULL,
-	c_alarm_date    int(11)      NOT NULL
+	c_path          VARCHAR(255) NOT NULL,
+	c_name          VARCHAR(255) NOT NULL,
+	c_uid           VARCHAR(255) NOT NULL,
+	c_recurrence_id INT(11)      DEFAULT NULL,
+	c_alarm_number  INT(11)      NOT NULL,
+	c_alarm_date    INT(11)      NOT NULL
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_cache_folder (
-	c_uid          varchar(255) NOT NULL,
-	c_path         varchar(255) NOT NULL,
-	c_parent_path  varchar(255) DEFAULT NULL,
-	c_type         tinyint(3)   unsigned NOT NULL,
-	c_creationdate int(11)      NOT NULL,
-	c_lastmodified int(11)      NOT NULL,
-	c_version      int(11)      NOT NULL DEFAULT '0',
-	c_deleted      tinyint(4)   NOT NULL DEFAULT '0',
-	c_content      longtext,
+	c_uid          VARCHAR(255) NOT NULL,
+	c_path         VARCHAR(255) NOT NULL,
+	c_parent_path  VARCHAR(255) DEFAULT NULL,
+	c_type         TINYINT(3)   unsigned NOT NULL,
+	c_creationdate INT(11)      NOT NULL,
+	c_lastmodified INT(11)      NOT NULL,
+	c_version      INT(11)      NOT NULL DEFAULT '0',
+	c_deleted      TINYINT(4)   NOT NULL DEFAULT '0',
+	c_content      longTEXT,
 	PRIMARY KEY (c_uid,c_path)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_folder_info (
-	c_folder_id      bigint(20)    unsigned NOT NULL AUTO_INCREMENT,
-	c_path           varchar(255)  NOT NULL,
-	c_path1          varchar(255)  NOT NULL,
-	c_path2          varchar(255)  DEFAULT NULL,
-	c_path3          varchar(255)  DEFAULT NULL,
-	c_path4          varchar(255)  DEFAULT NULL,
-	c_foldername     varchar(255)  NOT NULL,
-	c_location       integer NULL,
-	c_quick_location varchar(2048) DEFAULT NULL,
-	c_acl_location   varchar(2048) DEFAULT NULL,
-	c_folder_type    varchar(255)  NOT NULL,
+	c_folder_id      BIGINT(20)    unsigned NOT NULL AUTO_INCREMENT,
+	c_path           VARCHAR(255)  NOT NULL,
+	c_path1          VARCHAR(255)  NOT NULL,
+	c_path2          VARCHAR(255)  DEFAULT NULL,
+	c_path3          VARCHAR(255)  DEFAULT NULL,
+	c_path4          VARCHAR(255)  DEFAULT NULL,
+	c_foldername     VARCHAR(255)  NOT NULL,
+	c_location       INTeger NULL,
+	c_quick_location VARCHAR(2048) DEFAULT NULL,
+	c_acl_location   VARCHAR(2048) DEFAULT NULL,
+	c_folder_type    VARCHAR(255)  NOT NULL,
 	PRIMARY KEY (c_path),
 	UNIQUE KEY c_folder_id (c_folder_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
-CREATE TABLE IF NOT EXISTS sogo_quick_appointment (
-	c_folder_id integer NOT NULL,
+CREATE TABLE IF NOT EXISTS sogo_quick_appoINTment (
+	c_folder_id INTeger NOT NULL,
 	c_name character varying(255) NOT NULL,
 	c_uid character varying(255) NOT NULL,
-	c_startdate integer,
-	c_enddate integer,
-	c_cycleenddate integer,
+	c_startdate INTeger,
+	c_enddate INTeger,
+	c_cycleenddate INTeger,
 	c_title character varying(1000) NOT NULL,
-	c_participants text,
-	c_isallday integer,
-	c_iscycle integer,
-	c_cycleinfo text,
-	c_classification integer NOT NULL,
-	c_isopaque integer NOT NULL,
-	c_status integer NOT NULL,
-	c_priority integer,
+	c_participants TEXT,
+	c_isallday INTeger,
+	c_iscycle INTeger,
+	c_cycleinfo TEXT,
+	c_classification INTeger NOT NULL,
+	c_isopaque INTeger NOT NULL,
+	c_status INTeger NOT NULL,
+	c_priority INTeger,
 	c_location character varying(255),
 	c_orgmail character varying(255),
-	c_partmails text,
-	c_partstates text,
+	c_partmails TEXT,
+	c_partstates TEXT,
 	c_category character varying(255),
-	c_sequence integer,
+	c_sequence INTeger,
 	c_component character varying(10) NOT NULL,
-	c_nextalarm integer,
-	c_description text,
-	CONSTRAINT sogo_quick_appointment_pkey PRIMARY KEY (c_folder_id, c_name)
+	c_nextalarm INTeger,
+	c_description TEXT,
+	CONSTRAINT sogo_quick_appoINTment_pkey PRIMARY KEY (c_folder_id, c_name)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_quick_contact (
-	c_folder_id integer NOT NULL,
+	c_folder_id INTeger NOT NULL,
 	c_name character varying(255) NOT NULL,
 	c_givenname character varying(255),
 	c_cn character varying(255),
@@ -233,28 +238,28 @@ CREATE TABLE IF NOT EXISTS sogo_quick_contact (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_sessions_folder (
-	c_id           varchar(255) NOT NULL,
-	c_value        varchar(255) NOT NULL,
-	c_creationdate int(11)      NOT NULL,
-	c_lastseen     int(11)      NOT NULL,
+	c_id           VARCHAR(255) NOT NULL,
+	c_value        VARCHAR(255) NOT NULL,
+	c_creationdate INT(11)      NOT NULL,
+	c_lastseen     INT(11)      NOT NULL,
 	PRIMARY KEY (c_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_store (
-	c_folder_id integer NOT NULL,
+	c_folder_id INTeger NOT NULL,
 	c_name character varying(255) NOT NULL,
-	c_content mediumtext NOT NULL,
-	c_creationdate integer NOT NULL,
-	c_lastmodified integer NOT NULL,
-	c_version integer NOT NULL,
-	c_deleted integer,
+	c_content mediumTEXT NOT NULL,
+	c_creationdate INTeger NOT NULL,
+	c_lastmodified INTeger NOT NULL,
+	c_version INTeger NOT NULL,
+	c_deleted INTeger,
 	CONSTRAINT sogo_store_pkey PRIMARY KEY (c_folder_id, c_name)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
 CREATE TABLE IF NOT EXISTS sogo_user_profile (
-	c_uid      varchar(255) NOT NULL,
-	c_defaults text,
-	c_settings text,
+	c_uid      VARCHAR(255) NOT NULL,
+	c_defaults TEXT,
+	c_settings TEXT,
 	PRIMARY KEY (c_uid)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
 
diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php
index cec7454d..4ec73e52 100644
--- a/data/web/inc/prerequisites.inc.php
+++ b/data/web/inc/prerequisites.inc.php
@@ -3,10 +3,17 @@
 //ini_set("session.cookie_httponly", 1);
 session_start();
 if (isset($_POST["logout"])) {
-	session_unset();
-	session_destroy();
-	session_write_close();
-	setcookie(session_name(),'',0,'/');
+  if (isset($_SESSION["dual-login"])) {
+    $_SESSION["mailcow_cc_username"] = $_SESSION["dual-login"]["username"];
+    $_SESSION["mailcow_cc_role"] = $_SESSION["dual-login"]["role"];
+    unset($_SESSION["dual-login"]);
+  }
+  else {
+    session_unset();
+    session_destroy();
+    session_write_close();
+    setcookie(session_name(),'',0,'/');
+  }
 }
 
 require_once 'inc/vars.inc.php';
@@ -75,4 +82,4 @@ require_once 'lang/lang.en.php';
 include 'lang/lang.'.$_SESSION['mailcow_locale'].'.php';
 require_once 'inc/functions.inc.php';
 require_once 'inc/triggers.inc.php';
-init_db_schema();
+(!isset($_SESSION['mailcow_cc_username'])) ? init_db_schema() : null;
diff --git a/data/web/inc/triggers.inc.php b/data/web/inc/triggers.inc.php
index c2588148..00de3a9e 100644
--- a/data/web/inc/triggers.inc.php
+++ b/data/web/inc/triggers.inc.php
@@ -25,6 +25,20 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
 	}
 }
 if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
+	if (isset($_GET["duallogin"])) {
+    if (filter_var($_GET["duallogin"], FILTER_VALIDATE_EMAIL)) {
+      $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :duallogin");
+      $stmt->execute(array(':duallogin' => $_GET["duallogin"]));
+      $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+      if ($num_results != 0) {
+        $_SESSION["dual-login"]["username"] = $_SESSION['mailcow_cc_username'];
+        $_SESSION["dual-login"]["role"]     = $_SESSION['mailcow_cc_role'];
+        $_SESSION['mailcow_cc_username']    = $_GET["duallogin"];
+        $_SESSION['mailcow_cc_role']        = "user";
+        header("Location: /user.php");
+      }
+    }
+  }
 	if (isset($_POST["trigger_set_admin"])) {
 		set_admin_account($_POST);
 	}
diff --git a/data/web/js/user.js b/data/web/js/user.js
index 821ff99d..9dbca08c 100644
--- a/data/web/js/user.js
+++ b/data/web/js/user.js
@@ -15,6 +15,9 @@ $(document).ready(function() {
 		}
 	});
 
+  $(function () {
+    $('[data-toggle="tooltip"]').tooltip()
+  })
 	// Show generate button after time selection
 	$('#trigger_set_time_limited_aliases').hide(); 
 	$('#validity').change(function(){
@@ -29,6 +32,6 @@ $(document).ready(function() {
   // Log modal
   $('#logModal').on('show.bs.modal', function(e) {
   var logText = $(e.relatedTarget).data('log-text');
-  $(e.currentTarget).find('#logText').html('<pre>' + logText + '</pre>');
+  $(e.currentTarget).find('#logText').html('<pre style="background:none;font-size:11px;line-height:1.1;border:0px">' + logText + '</pre>');
   });
 });
\ No newline at end of file
diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php
index 328167cb..de983776 100644
--- a/data/web/lang/lang.de.php
+++ b/data/web/lang/lang.de.php
@@ -66,7 +66,7 @@ $lang['danger']['is_alias'] = '%s lautet bereits eine Alias-Adresse';
 $lang['danger']['is_alias_or_mailbox'] = "Eine Mailbox oder ein Alias mit der Adresse %s ist bereits vorhanden";
 $lang['danger']['is_spam_alias'] = '%s lautet bereits eine Spam-Alias-Adresse';
 $lang['danger']['quota_not_0_not_numeric'] = 'Speicherplatz muss numerisch und >= 0 sein';
-$lang['danger']['domain_not_found'] = 'Domain nicht gefunden.';
+$lang['danger']['domain_not_found'] = 'Domain "%s" nicht gefunden.';
 $lang['danger']['max_mailbox_exceeded'] = 'Anzahl an Mailboxen überschritten (%d von %d)';
 $lang['danger']['mailbox_quota_exceeded'] = 'Speicherplatz überschreitet das Limit (max. %d MiB)';
 $lang['danger']['mailbox_quota_left_exceeded'] = 'Nicht genügend Speicherplatz vorhanden (Speicherplatz anwendbar: %d MiB)';
@@ -102,6 +102,7 @@ $lang['user']['did_you_know'] = '<b>Wussten Sie schon?</b> Sie können Ihre E-Ma
 $lang['user']['spam_aliases'] = 'Temporäre E-Mail Aliasse';
 $lang['user']['alias'] = 'Alias';
 $lang['user']['aliases'] = 'Aliasse';
+$lang['user']['domain_aliases'] = 'Domain-Alias Adressen';
 $lang['user']['is_catch_all'] = 'Ist Catch-All Adresse für Domain(s)';
 $lang['user']['aliases_also_send_as'] = 'Darf außerdem versenden als';
 $lang['user']['aliases_send_as_all'] = 'Absender für folgende Domains nicht prüfen';
@@ -163,6 +164,7 @@ $lang['user']['active'] = 'Aktiv';
 $lang['user']['action'] = 'Aktion';
 $lang['user']['edit'] = 'Bearbeiten';
 $lang['user']['remove'] = 'Entfernen';
+$lang['user']['delete_now'] = 'Sofort löschen';
 $lang['user']['create_syncjob'] = 'Neuen Sync-Job erstellen';
 
 $lang['start']['dashboard'] = '%s - Dashboard';
@@ -194,6 +196,7 @@ $lang['header']['mailboxes'] = 'Mailboxen';
 $lang['header']['user_settings'] = 'Benutzereinstellungen';
 $lang['header']['login'] = 'Anmeldung';
 $lang['header']['logged_in_as_logout'] = 'Eingeloggt als <b>%s</b> (abmelden)';
+$lang['header']['logged_in_as_logout_dual'] = 'Eingeloggt als <b>%s <span class="text-info">[%s]</span></b>';
 $lang['header']['locale'] = 'Sprache';
 $lang['mailbox']['domain'] = 'Domain';
 $lang['mailbox']['alias'] = 'Alias';
@@ -220,7 +223,7 @@ $lang['mailbox']['msg_num'] = 'Anzahl Nachrichten';
 $lang['mailbox']['remove'] = 'Entfernen';
 $lang['mailbox']['edit'] = 'Bearbeiten';
 $lang['mailbox']['archive'] = 'Archiv-Zugriff';
-$lang['mailbox']['no_record'] = 'Kein Eintrag';
+$lang['mailbox']['no_record'] = 'Kein Eintrag für Objekt %s';
 $lang['mailbox']['add_domain'] = 'Domain hinzufügen';
 $lang['mailbox']['add_domain_alias'] = 'Domain-Alias hinzufügen';
 $lang['mailbox']['add_mailbox'] = 'Mailbox hinzufügen';
@@ -247,6 +250,8 @@ $lang['edit']['save'] = 'Änderungen speichern';
 $lang['edit']['username'] = 'Benutzername';
 $lang['edit']['hostname'] = 'Servername';
 $lang['edit']['encryption'] = 'Verschlüsselungsmethode';
+$lang['edit']['maxage'] = 'Maximales Alter in Tagen einer Nachricht, die kopiert werden soll</br ><small>(0 = alle Nachrichten kopieren)</small>';
+$lang['edit']['subfolder2'] = 'Ziel-Ordner<br /><small>(leer = kein Unterordner)</small>';
 $lang['edit']['mins_interval'] = 'Intervall (min)';
 $lang['edit']['exclude'] = 'Elemente ausschließen (Regex)';
 $lang['edit']['archive'] = 'Archiv-Zugriff';
@@ -292,6 +297,8 @@ $lang['add']['syncjob_hint'] = 'Passwörter werden unverschlüsselt abgelegt!';
 $lang['add']['hostname'] = 'Servername';
 $lang['add']['username'] = 'Benutzername';
 $lang['add']['enc_method'] = 'Verschlüsselungsmethode';
+$lang['add']['maxage'] = 'Maximum age of messages that will be polled from remote (0 = ignore age)';
+$lang['add']['subfolder2'] = 'Sync into subfolder on destination';
 $lang['add']['mins_interval'] = 'Abrufintervall (Minuten)';
 $lang['add']['exclude'] = 'Elemente ausschließen (Regex)';
 $lang['add']['delete2duplicates'] = 'Lösche Duplikate im Ziel';
diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php
index 3600d154..e764985c 100644
--- a/data/web/lang/lang.en.php
+++ b/data/web/lang/lang.en.php
@@ -104,6 +104,7 @@ $lang['user']['did_you_know'] = '<b>Did you know?</b> You can use tags in your e
 $lang['user']['spam_aliases'] = 'Temporary email aliases';
 $lang['user']['alias'] = 'Alias';
 $lang['user']['aliases'] = 'Aliases';
+$lang['user']['domain_aliases'] = 'Domain alias addresses';
 $lang['user']['is_catch_all'] = 'Catch-all for domain/s';
 $lang['user']['aliases_also_send_as'] = 'Also allowed to send as';
 $lang['user']['aliases_send_as_all'] = 'Do not check sender access for following domain/s';
@@ -165,6 +166,7 @@ $lang['user']['active'] = 'Active';
 $lang['user']['action'] = 'Action';
 $lang['user']['edit'] = 'Edit';
 $lang['user']['remove'] = 'Remove';
+$lang['user']['delete_now'] = 'Remove now';
 $lang['user']['create_syncjob'] = 'Create new sync job';
 
 $lang['start']['dashboard'] = '%s - dashboard';
@@ -196,6 +198,7 @@ $lang['header']['mailboxes'] = 'Mailboxes';
 $lang['header']['user_settings'] = 'User settings';
 $lang['header']['login'] = 'Login';
 $lang['header']['logged_in_as_logout'] = 'Logged in as <b>%s</b> (logout)';
+$lang['header']['logged_in_as_logout_dual'] = 'Logged in as <b>%s <span class="text-info">[%s]</span></b>';
 $lang['header']['locale'] = 'Language';
 $lang['mailbox']['domain'] = 'Domain';
 $lang['mailbox']['alias'] = 'Alias';
@@ -222,7 +225,7 @@ $lang['mailbox']['msg_num'] = 'Message #';
 $lang['mailbox']['remove'] = 'Remove';
 $lang['mailbox']['edit'] = 'Edit';
 $lang['mailbox']['archive'] = 'Archive';
-$lang['mailbox']['no_record'] = 'No Record';
+$lang['mailbox']['no_record'] = 'No Record for object %s';
 $lang['mailbox']['add_domain'] = 'Add domain';
 $lang['mailbox']['add_domain_alias'] = 'Add domain alias';
 $lang['mailbox']['add_mailbox'] = 'Add mailbox';
@@ -249,6 +252,8 @@ $lang['edit']['save'] = 'Save changes';
 $lang['edit']['username'] = 'Save changes';
 $lang['edit']['hostname'] = 'Hostname';
 $lang['edit']['encryption'] = 'Encryption';
+$lang['edit']['maxage'] = 'Maximum age of messages in days that will be polled from remote<br /><small>(0 = ignore age)</small>';
+$lang['edit']['subfolder2'] = 'Sync into subfolder on destination<br /><small>(empty = do not use subfolder)</small>';
 $lang['edit']['mins_interval'] = 'Interval (min)';
 $lang['edit']['exclude'] = 'Exclude objects (regex)';
 $lang['edit']['save'] = 'Save changes';
@@ -296,6 +301,8 @@ $lang['add']['hostname'] = 'Hostname';
 $lang['add']['username'] = 'Username';
 $lang['add']['enc_method'] = 'Encryption method';
 $lang['add']['mins_interval'] = 'Polling interval (minutes)';
+$lang['add']['maxage'] = 'Maximum age of messages that will be polled from remote (0 = ignore age)';
+$lang['add']['subfolder2'] = 'Sync into subfolder on destination';
 $lang['add']['exclude'] = 'Exclude objects (regex)';
 $lang['add']['delete2duplicates'] = 'Delete duplicates on destination';
 
diff --git a/data/web/mailbox.php b/data/web/mailbox.php
index b04523f4..26c799b6 100644
--- a/data/web/mailbox.php
+++ b/data/web/mailbox.php
@@ -49,80 +49,32 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
 					</thead>
 					<tbody>
 					<?php
-					try {
-						$stmt = $pdo->prepare("SELECT 
-								`domain`,
-								`aliases`,
-								`mailboxes`, 
-								`maxquota` * 1048576 AS `maxquota`,
-								`quota` * 1048576 AS `quota`,
-								CASE `backupmx` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `backupmx`,
-								CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
-									FROM `domain` WHERE
-										`domain` IN (
-											SELECT `domain` FROM `domain_admins` WHERE `username`= :username AND `active`='1'
-										)
-										OR 'admin'= :admin");
-						$stmt->execute(array(
-							':username' => $_SESSION['mailcow_cc_username'],
-							':admin' => $_SESSION['mailcow_cc_role'],
-						));
-						$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-					}
-					catch (PDOException $e) {
-						$_SESSION['return'] = array(
-							'type' => 'danger',
-							'msg' => 'MySQL: '.$e
-						);
-						return false;
-					}
-	        if(!empty($rows)):
-					while($row = array_shift($rows)):
-						try {
-							$stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias`
-								WHERE `domain`= :domain
-								AND `address` NOT IN (
-									SELECT `username` FROM `mailbox`)");
-							$stmt->execute(array(':domain' => $row['domain']));
-							$AliasData = $stmt->fetch(PDO::FETCH_ASSOC);
-			
-							$stmt = $pdo->prepare("SELECT 
-								COUNT(*) AS `count`,
-								COALESCE(SUM(`quota`), '0') AS `quota`
-									FROM `mailbox`
-										WHERE `domain` = :domain");
-							$stmt->execute(array(':domain' => $row['domain']));
-							$MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
-						}
-						catch (PDOException $e) {
-							$_SESSION['return'] = array(
-								'type' => 'danger',
-								'msg' => 'MySQL: '.$e
-							);
-							return false;
-						}
+          $domains = mailbox_get_domains();
+	        if (!empty($domains)):
+					foreach ($domains as $domain):
+            $domaindata = mailbox_get_domain_details($domain);
 					?>
 						<tr id="data">
-							<td><?=htmlspecialchars($row['domain']);?></td>
-							<td><?=intval($AliasData['count']);?> / <?=intval($row['aliases']);?></td>
-							<td><?=$MailboxData['count'];?> / <?=$row['mailboxes'];?></td>
-							<td><?=formatBytes(intval($row['maxquota']), 2);?></td>
-							<td><?=formatBytes(intval($MailboxData['quota']), 2);?> / <?=formatBytes(intval($row['quota']));?></td>
+							<td><?=htmlspecialchars($domaindata['domain_name']);?></td>
+							<td><?=$domaindata['aliases_in_domain'];?> / <?=$domaindata['max_num_aliases_for_domain'];?></td>
+							<td><?=$domaindata['mboxes_in_domain'];?> / <?=$domaindata['max_num_mboxes_for_domain'];?></td>
+							<td><?=$domaindata['max_quota_for_mbox'];?></td>
+							<td><?=$domaindata['quota_used_in_domain'];?> / <?=$domaindata['max_quota_for_domain'];?></td>
 							<?php
 							if ($_SESSION['mailcow_cc_role'] == "admin"):
 							?>
-								<td><?=$row['backupmx'];?></td>
+								<td><?=$domaindata['backupmx'];?></td>
 							<?php
 							endif;
 							?>
-							<td><?=$row['active'];?></td>
+							<td><?=$domaindata['active'];?></td>
 							<?php
 							if ($_SESSION['mailcow_cc_role'] == "admin"):
 							?>
 								<td style="text-align: right;">
 									<div class="btn-group">
-										<a href="/edit.php?domain=<?=urlencode($row['domain']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
-										<a href="/delete.php?domain=<?=urlencode($row['domain']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
+										<a href="/edit.php?domain=<?=urlencode($domaindata['domain_name']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
+										<a href="/delete.php?domain=<?=urlencode($domaindata['domain_name']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
 									</div>
 								</td>
 							<?php
@@ -130,19 +82,19 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
 							?>
 								<td style="text-align: right;">
 									<div class="btn-group">
-										<a href="/edit.php?domain=<?=urlencode($row['domain']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
+										<a href="/edit.php?domain=<?=urlencode($domaindata['domain_name']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
 									</div>
 								</td>
 						</tr>
-							<?php
-							endif;
-							endwhile;
-	            else:
-							?>
-							  <tr id="no-data"><td colspan="8" style="text-align: center; font-style: italic;"><?=$lang['mailbox']['no_record'];?></td></tr>
-							<?php
-							endif;
+              <?php
+              endif;
+            endforeach;
+            else:
 							?>
+              <tr id="no-data"><td colspan="8" style="text-align: center; font-style: italic;"><?=$lang['mailbox']['no_record'];?></td></tr>
+            <?php
+            endif;
+            ?>
 					</tbody>
 						<?php
 						if ($_SESSION['mailcow_cc_role'] == "admin"):
@@ -189,51 +141,33 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
 					</thead>
 					<tbody>
 					<?php
-					try {
-						$stmt = $pdo->prepare("SELECT 
-								`alias_domain`,
-								`target_domain`,
-								CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
-									FROM `alias_domain`
-										WHERE `target_domain` IN (
-											SELECT `domain` FROM `domain_admins`
-												WHERE `username`= :username 
-												AND `active`='1'
-										)
-										OR 'admin' = :admin");
-						$stmt->execute(array(
-							':username' => $_SESSION['mailcow_cc_username'],
-							':admin' => $_SESSION['mailcow_cc_role'],
-						));
-						$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-					} catch(PDOException $e) {
-						$_SESSION['return'] = array(
-							'type' => 'danger',
-							'msg' => 'MySQL: '.$e
-						);
-					}
-	        if(!empty($rows)):
-					while($row = array_shift($rows)):
-					?>
-						<tr id="data">
-							<td><?=htmlspecialchars($row['alias_domain']);?></td>
-							<td><?=htmlspecialchars($row['target_domain']);?></td>
-							<td><?=$row['active'];?></td>
-							<td style="text-align: right;">
-								<div class="btn-group">
-									<a href="/edit.php?aliasdomain=<?=urlencode($row['alias_domain']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
-									<a href="/delete.php?aliasdomain=<?=urlencode($row['alias_domain']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
-								</div>
-							</td>
-						</tr>
-					<?php
-					endwhile;
-	        else:
+          foreach (mailbox_get_domains() as $domain) {
+            $alias_domains = mailbox_get_alias_domains($domain);
+            if (!empty($alias_domains)) {
+              foreach ($alias_domains as $alias_domain) {
+                $aliasdomaindata = mailbox_get_alias_domain_details($alias_domain);
+                ?>
+                <tr id="data">
+                  <td><?=htmlspecialchars($aliasdomaindata['alias_domain']);?></td>
+                  <td><?=htmlspecialchars($aliasdomaindata['target_domain']);?></td>
+                  <td><?=$aliasdomaindata['active'];?></td>
+                  <td style="text-align: right;">
+                    <div class="btn-group">
+                      <a href="/edit.php?aliasdomain=<?=urlencode($aliasdomaindata['alias_domain']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
+                      <a href="/delete.php?aliasdomain=<?=urlencode($aliasdomaindata['alias_domain']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
+                    </div>
+                  </td>
+                </tr>
+                <?php
+              }
+            }
+            else {
 	        ?>
-						<tr id="no-data"><td colspan="4" style="text-align: center; font-style: italic;"><?=$lang['mailbox']['no_record'];?></td></tr>
+                  <tr id="no-data"><td colspan="8" style="text-align: center; font-style: italic;"><?=sprintf($lang['mailbox']['no_record'], $domain);?></td></tr>
 	        <?php
-	        endif;
-					?>
+            }
+          }
+          ?>
 					</tbody>
 					<tfoot>
 						<tr id="no-data">
@@ -278,91 +212,45 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
 					</thead>
 					<tbody>
 						<?php
-						try {
-							$stmt = $pdo->prepare("SELECT
-									`domain`.`backupmx`,
-									`mailbox`.`username`,
-									`mailbox`.`name`,
-									CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
-									`mailbox`.`domain`,
-									`mailbox`.`quota`,
-									`quota2`.`bytes`,
-									`quota2`.`messages`
-										FROM `mailbox`, `quota2`, `domain`
-											WHERE (`mailbox`.`username` = `quota2`.`username`)
-											AND (`domain`.`domain` = `mailbox`.`domain`)
-											AND (`mailbox`.`domain` IN (
-												SELECT `domain` FROM `domain_admins`
-													WHERE `username`= :username
-														AND `active`='1'
-													)
-													OR 'admin' = :admin)");
-							$stmt->execute(array(
-								':username' => $_SESSION['mailcow_cc_username'],
-								':admin' => $_SESSION['mailcow_cc_role'],
-							));
-							$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-						}
-						catch (PDOException $e) {
-							$_SESSION['return'] = array(
-								'type' => 'danger',
-								'msg' => 'MySQL: '.$e
-							);
-							return false;
-						}
-	          if(!empty($rows)):
-						while($row = array_shift($rows)):
+            foreach (mailbox_get_domains() as $domain) {
+              $mailboxes = mailbox_get_mailboxes($domain);
+              if (!empty($mailboxes)) {
+                foreach ($mailboxes as $mailbox) {
+                  $mailboxdata = mailbox_get_mailbox_details($mailbox);
 						?>
 						<tr id="data">
-							<?php
-							if ($row['backupmx'] == "0"):
-							?>
-								<td><?=htmlspecialchars($row['username']);?></td>
-							<?php
-							else:
-							?>
-								<td><span data-toggle="tooltip" title="Relayed"><i class="glyphicon glyphicon-forward"></i> <?=htmlspecialchars($row['username']);?></span></td>
-							<?php
-							endif;
-							?>
-							<td><?=htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8');?></td>
-							<td><?=htmlspecialchars($row['domain']);?></td>
-							<td><?=formatBytes(intval($row['bytes']), 2);?> / <?=formatBytes(intval($row['quota']), 2);?></td>
+							<td><?=($mailboxdata['is_relayed'] == "0") ? htmlspecialchars($mailboxdata['username']) : '<span data-toggle="tooltip" title="Relayed"><i class="glyphicon glyphicon-forward"></i>' . htmlspecialchars($mailboxdata['username']) . '</span>';?></td>
+							<td><?=htmlspecialchars($mailboxdata['name'], ENT_QUOTES, 'UTF-8');?></td>
+							<td><?=htmlspecialchars($mailboxdata['domain']);?></td>
+							<td><?=$mailboxdata['quota_used'];?> / <?=$mailboxdata['quota'];?></td>
 							<td style="min-width:120px;">
-								<?php
-								$percentInUse = round((intval($row['bytes']) / intval($row['quota'])) * 100);
-								if ($percentInUse >= 90) {
-									$pbar = "progress-bar-danger";
-								}
-								elseif ($percentInUse >= 75) {
-									$pbar = "progress-bar-warning";
-								}
-								else {
-									$pbar = "progress-bar-success";
-								}
-								?>
 								<div class="progress">
-									<div class="progress-bar <?=$pbar;?>" role="progressbar" aria-valuenow="<?=$percentInUse;?>" aria-valuemin="0" aria-valuemax="100" style="min-width:2em;width: <?=$percentInUse;?>%;">
-										<?=$percentInUse;?>%
+									<div class="progress-bar progress-bar-<?=$mailboxdata['percent_class'];?>" role="progressbar" aria-valuenow="<?=$mailboxdata['percent_in_use'];?>" aria-valuemin="0" aria-valuemax="100" style="min-width:2em;width: <?=$mailboxdata['percent_in_use'];?>%;">
+										<?=$mailboxdata['percent_in_use'];?>%
 									</div>
 								</div>
 							</td>
-							<td><?=$row['messages'];?></td>
-							<td><?=$row['active'];?></td>
+							<td><?=$mailboxdata['messages'];?></td>
+							<td><?=$mailboxdata['active'];?></td>
 							<td style="text-align: right;">
 								<div class="btn-group">
-									<a href="/edit.php?mailbox=<?=urlencode($row['username']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
-									<a href="/delete.php?mailbox=<?=urlencode($row['username']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
+									<a href="/edit.php?mailbox=<?=urlencode($mailboxdata['username']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
+									<a href="/delete.php?mailbox=<?=urlencode($mailboxdata['username']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
+									<?php if ($_SESSION['mailcow_cc_role'] == "admin"): ?>
+                  <a href="/index.php?duallogin=<?=urlencode($mailboxdata['username']);?>" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>
+                  <?php endif; ?>
 								</div>
 							</td>
 						</tr>
 						<?php
-						endwhile;
-	          else:
-						?>
-						  <tr id="no-data"><td colspan="8" style="text-align: center; font-style: italic;"><?=$lang['mailbox']['no_record'];?></td></tr>
-						<?php
-						endif;
+                }
+              }
+              else {
+                  ?>
+                  <tr id="no-data"><td colspan="8" style="text-align: center; font-style: italic;"><?=sprintf($lang['mailbox']['no_record'], $domain);?></td></tr>
+                  <?php
+              }
+            }
 						?>
 					</tbody>
 					<tfoot>
@@ -405,76 +293,42 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
 					</thead>
 					<tbody>
 					<?php
-					try {
-						$stmt = $pdo->prepare("SELECT
-								`address`,
-								`goto`,
-								`domain`,
-								CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
-									FROM alias
-										WHERE (
-											`address` NOT IN (
-												SELECT `username` FROM `mailbox`
-											)
-											AND `address` != `goto`
-										) AND (`domain` IN (
-											SELECT `domain` FROM `domain_admins`
-												WHERE `username` = :username 
-												AND active='1'
-											)
-											OR 'admin' = :admin)");
-						$stmt->execute(array(
-							':username' => $_SESSION['mailcow_cc_username'],
-							':admin' => $_SESSION['mailcow_cc_role'],
-						));
-						$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-					}
-					catch (PDOException $e) {
-						$_SESSION['return'] = array(
-							'type' => 'danger',
-							'msg' => 'MySQL: '.$e
-						);
-						return false;
-					}
-	        if(!empty($rows)):
-					while($row = array_shift($rows)):
+          foreach (mailbox_get_domains() as $domain) {
+            $aliases = mailbox_get_aliases($domain);
+            if (!empty($aliases)) {
+              foreach ($aliases as $alias) {
+                $aliasdata = mailbox_get_alias_details($alias);
 					?>
 						<tr id="data">
 							<td>
-							<?php
-							if(!filter_var($row['address'], FILTER_VALIDATE_EMAIL)):
-							?>
-								<span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span> Catch-all @<?=htmlspecialchars($row['domain']);?>
-							<?php
-							else:
-								echo htmlspecialchars($row['address']);
-							endif;
-							?>
+							<?= ($aliasdata['is_catch_all'] == "1") ? '<span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span> Catch-all ' . htmlspecialchars($aliasdata['address']) : htmlspecialchars($aliasdata['address']); ?>
 							</td>
 							<td>
 							<?php
-							foreach(explode(",", $row['goto']) as $goto) {
+							foreach(explode(",", $aliasdata['goto']) as $goto) {
 								echo nl2br(htmlspecialchars($goto.PHP_EOL));
 							}
 							?>
 							</td>
-							<td><?=htmlspecialchars($row['domain']);?></td>
-							<td><?=$row['active'];?></td>
+							<td><?=htmlspecialchars($aliasdata['domain']);?></td>
+							<td><?=$aliasdata['active'];?></td>
 							<td style="text-align: right;">
 								<div class="btn-group">
-									<a href="/edit.php?alias=<?=urlencode($row['address']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
-									<a href="/delete.php?alias=<?=urlencode($row['address']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
+									<a href="/edit.php?alias=<?=urlencode($aliasdata['address']);?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> <?=$lang['mailbox']['edit'];?></a>
+									<a href="/delete.php?alias=<?=urlencode($aliasdata['address']);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['mailbox']['remove'];?></a>
 								</div>
 							</td>
 						</tr>
-					<?php
-					endwhile;
-	        else:
-					?>
-					  <tr id="no-data"><td colspan="5" style="text-align: center; font-style: italic;"><?=$lang['mailbox']['no_record'];?></td></tr>
-					<?php
-					endif;	
-					?>
+						<?php
+                }
+              }
+              else {
+                  ?>
+                  <tr id="no-data"><td colspan="8" style="text-align: center; font-style: italic;"><?=sprintf($lang['mailbox']['no_record'], $domain);?></td></tr>
+                  <?php
+              }
+            }
+						?>
 					</tbody>
 					<tfoot>
 						<tr id="no-data">
diff --git a/data/web/user.php b/data/web/user.php
index 7d55d0c1..33e26e81 100644
--- a/data/web/user.php
+++ b/data/web/user.php
@@ -51,29 +51,35 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
   </form>
   <hr>
   <?php // Get user information about aliases
-  $get_user_object_info = user_object_info('get');?>
+  $user_get_alias_details = user_get_alias_details($username);?>
   <div class="row">
     <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['aliases'];?>:</div>
     <div class="col-md-9 col-xs-7">
-    <p><?=$get_user_object_info['aliases'];?></p>
+    <p><?=$user_get_alias_details['aliases'];?></p>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['domain_aliases'];?>:</div>
+    <div class="col-md-9 col-xs-7">
+    <p><?=$user_get_alias_details['ad_alias'];?></p>
     </div>
   </div>
   <div class="row">
     <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['aliases_also_send_as'];?>:</div>
     <div class="col-md-9 col-xs-7">
-    <p><?=$get_user_object_info['aliases_also_send_as'];?></p>
+    <p><?=$user_get_alias_details['aliases_also_send_as'];?></p>
     </div>
   </div>
   <div class="row">
     <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['aliases_send_as_all'];?>:</div>
     <div class="col-md-9 col-xs-7">
-    <p><?=$get_user_object_info['aliases_send_as_all'];?></p>
+    <p><?=$user_get_alias_details['aliases_send_as_all'];?></p>
     </div>
   </div>
   <div class="row">
     <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['is_catch_all'];?>:</div>
     <div class="col-md-9 col-xs-7">
-    <p><?=$get_user_object_info['is_catch_all'];?></p>
+    <p><?=$user_get_alias_details['is_catch_all'];?></p>
     </div>
   </div>
   <hr>
@@ -107,16 +113,16 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
 
 <div class="tab-content">
 	<div role="tabpanel" class="tab-pane active" id="SpamAliases">
-		<form class="form-horizontal" role="form" method="post">
-		<div class="table-responsive">
-		<table class="table table-striped sortable-theme-bootstrap" data-sortable id="timelimitedaliases">
-			<thead>
-			<tr>
-				<th class="sort-table" style="min-width: 96px;"><?=$lang['user']['alias'];?></th>
-				<th class="sort-table" style="min-width: 135px;"><?=$lang['user']['alias_valid_until'];?></th>
-			</tr>
-			</thead>
-			<tbody>
+		<div class="row">
+			<div class="col-xs-5">
+				<p><b><?=$lang['user']['alias'];?></b></p>
+			</div>
+			<div class="col-xs-4">
+				<p><b><?=$lang['user']['alias_valid_until'];?></b></p>
+			</div>
+			<div class="col-xs-3">
+        <p><b><?=$lang['user']['action'];?></b></p>
+			</div>
 			<?php
 			try {
 				$stmt = $pdo->prepare("SELECT `address`,
@@ -137,21 +143,31 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
 			if(!empty($rows)):
 			while ($row = array_shift($rows)):
 			?>
-				<tr id="data">
-				<td><?=htmlspecialchars($row['address']);?></td>
-				<td><?=htmlspecialchars(date($lang['user']['alias_full_date'], $row['validity']));?></td>
-				</tr>
+			<div class="col-xs-5">
+				<p><?=htmlspecialchars($row['address']);?></p>
+			</div>
+			<div class="col-xs-4">
+				<p><?=htmlspecialchars(date($lang['user']['alias_full_date'], $row['validity']));?></p>
+			</div>
+			<div class="col-xs-3">
+				<form class="form-inline" role="form" method="post">
+          <a href="#" onclick="$(this).closest('form').submit()" data-toggle="tooltip" data-placement="left" title="<?=$lang['user']['delete_now'];?>"><span class="glyphicon glyphicon-remove"></span></a>
+          <input type="hidden" name="trigger_set_time_limited_aliases" value="delete">
+          <input type="hidden" name="item" value="<?=htmlspecialchars($row['address']);?>">
+				</form>
+			</div>
 			<?php
 			endwhile;
 			else:
 			?>
-				<tr id="no-data"><td colspan="2" style="text-align: center; font-style: italic;"><?=$lang['user']['no_record'];?></td></tr>
+      <div class="col-xs-12">
+        <center><i><?=$lang['user']['no_record'];?></i></center>
+      </div>
 			<?php
 			endif;	
 			?>
-			</tbody>
-		</table>
 		</div>
+    <form class="form-horizontal" role="form" method="post">
 		<div class="form-group">
 			<div class="col-sm-9">
 				<select id="validity" name="validity" title="<?=$lang['user']['alias_select_validity'];?>">
@@ -166,7 +182,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
 		</div>
 		<div class="form-group">
 			<div class="col-sm-12">
-				<button style="border-color:#f5f5f5;background:none;color:red" type="submit" name="trigger_set_time_limited_aliases" value="delete" class="btn btn-sm">
+				<button style="border-color:#f5f5f5;background:none;color:red" type="submit" name="trigger_set_time_limited_aliases" value="deleteall" class="btn btn-sm">
 					<span class="glyphicon glyphicon-remove" aria-hidden="true"></span> <?=$lang['user']['alias_remove_all'];?>
 				</button>
 				<button style="border-color:#f5f5f5;background:none;color:grey" type="submit" name="trigger_set_time_limited_aliases" value="extend" class="btn btn-sm">
@@ -365,13 +381,14 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
 		</form>
 	</div>
 	<div role="tabpanel" class="tab-pane" id="Syncjobs">
+		<div class="table-responsive">
 		<table class="table table-striped sortable-theme-bootstrap" data-sortable id="timelimitedaliases">
 			<thead>
 			<tr>
 				<th class="sort-table" style="min-width: 96px;">Server:Port</th>
 				<th class="sort-table" style="min-width: 96px;"><?=$lang['user']['encryption'];?></th>
 				<th class="sort-table" style="min-width: 96px;"><?=$lang['user']['username'];?></th>
-				<th class="sort-table" style="min-width: 35px;"><?=$lang['user']['excludes'];?></th>
+				<th class="sort-table" style="min-width: 96px;"><?=$lang['user']['excludes'];?></th>
 				<th class="sort-table" style="min-width: 35px;"><?=$lang['user']['interval'];?></th>
 				<th class="sort-table" style="min-width: 35px;"><?=$lang['user']['last_run'];?></th>
 				<th class="sort-table" style="min-width: 35px;">Log</th>
@@ -401,9 +418,9 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
 				<td><?=htmlspecialchars($row['host1'] . ':' . $row['port1']);?></td>
 				<td><?=htmlspecialchars($row['enc1']);?></td>
 				<td><?=htmlspecialchars($row['user1']);?></td>
-				<td><?=($row['exclude'] == '') ? '&#10008;' : $row['exclude'];?></td>
+				<td><?=($row['exclude'] == '') ? '&#10008;' : '<code>' . $row['exclude'] . '</code>';?></td>
 				<td><?=htmlspecialchars($row['mins_interval']);?> min</td>
-				<td><?=(empty($row['last_run'])) ? '&#10008;' : htmlspecialchars(date($lang['user']['syncjob_full_date'], strtotime($row['last_run'])));?></td>
+				<td><?=(empty($row['last_run'])) ? '&#10008;' : htmlspecialchars(date($lang['user']['syncjob_full_date'], strtotime($row['last_run'] . ' UTC')));?></td>
 				<td>
         <?php
         if (empty($row['returned_text'])) {
@@ -442,11 +459,12 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user
       </tfoot>
 		</table>
 		</div>
+		</div>
 	</div>
 </div>
 <br />
 <div class="modal fade" id="logModal" tabindex="-1" role="dialog" aria-labelledby="logTextLabel">
-  <div class="modal-dialog modal-lg" role="document">
+  <div class="modal-dialog" style="width:90%" role="document">
     <div class="modal-content">
       <div class="modal-body">
         <span id="logText"></span>