NobGit
public nobgit read

NobMail

Based on mailcow: dockerized

Languages

Repository composition by tracked source files.

PHP
PHP 49% JavaScript 35% HTML 9% CSS 4% Shell 2% Python 1% Lua 0% Perl 0% Ruby 0% SCSS 0%
Create file Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git

Commit

A lot of changes... still not finished, use with caution. Edit actions can be done with the internal API, trying to get rid of edit and add files

14a9a1c6
andryyy <[email protected]> 9 years ago
data/web/add.php               |   35 +-
 data/web/admin.php             |   64 +-
 data/web/css/mailbox.css       |   15 +-
 data/web/css/mailcow.css       |   10 +-
 data/web/css/noty.css          |  650 --------------
 data/web/edit.php              |   45 +-
 data/web/inc/footer.inc.php    |    5 +-
 data/web/inc/functions.inc.php | 1811 +++++++++++++++++++++-------------------
 data/web/inc/vars.inc.php      |    5 +-
 data/web/js/admin.js           |  365 ++++----
 data/web/js/mailbox.js         |  690 +++++++--------
 data/web/js/notify.min.js      |    1 -
 data/web/js/noty.min.js        |    9 -
 data/web/json_api.php          |  495 +++++++++--
 data/web/lang/lang.de.php      |    4 +-
 data/web/lang/lang.en.php      |    2 +-
 data/web/mailbox.php           |   75 +-
 data/web/user.php              |    6 +-
 18 files changed, 2060 insertions(+), 2227 deletions(-)
 delete mode 100644 data/web/css/noty.css
 delete mode 100644 data/web/js/notify.min.js
 delete mode 100644 data/web/js/noty.min.js

Diff

diff --git a/data/web/add.php b/data/web/add.php
index 5f1aa0d6..88e60b06 100644
--- a/data/web/add.php
+++ b/data/web/add.php
@@ -21,6 +21,9 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 ?>
 				<h4><?=$lang['add']['domain'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
+          <input type="hidden" value="0" name="backupmx">
+          <input type="hidden" value="0" name="relay_all_recipients">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
 						<div class="col-sm-10">
@@ -61,9 +64,9 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 						<label class="control-label col-sm-2"><?=$lang['add']['backup_mx_options'];?></label>
 						<div class="col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="backupmx"> <?=$lang['add']['relay_domain'];?></label>
+							<label><input type="checkbox" value="1" name="backupmx"> <?=$lang['add']['relay_domain'];?></label>
 							<br />
-							<label><input type="checkbox" name="relay_all_recipients"> <?=$lang['add']['relay_all'];?></label>
+							<label><input type="checkbox" value="1" name="relay_all_recipients"> <?=$lang['add']['relay_all'];?></label>
 							<p><?=$lang['add']['relay_all_info'];?></p>
 							</div>
 						</div>
@@ -71,7 +74,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" checked> <?=$lang['add']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
 							</div>
 						</div>
 					</div>
@@ -89,6 +92,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 				<h4><?=$lang['add']['alias'];?></h4>
 				<p><?=$lang['add']['alias_spf_fail'];?></p>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="address"><?=$lang['add']['alias_address'];?></label>
 						<div class="col-sm-10">
@@ -106,7 +110,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" checked> <?=$lang['add']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
 							</div>
 						</div>
 					</div>
@@ -122,6 +126,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 	?>
 				<h4><?=$lang['add']['alias_domain'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="alias_domain"><?=$lang['add']['alias_domain'];?></label>
 						<div class="col-sm-10">
@@ -144,7 +149,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" checked> <?=$lang['add']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
 							</div>
 						</div>
 					</div>
@@ -160,6 +165,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 	?>
 				<h4><?=$lang['add']['mailbox'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="local_part"><?=$lang['add']['mailbox_username'];?></label>
 						<div class="col-sm-10">
@@ -207,7 +213,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" checked> <?=$lang['add']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
 							</div>
 						</div>
 					</div>
@@ -223,6 +229,8 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 	?>
 				<h4><?=$lang['add']['resource'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
+          <input type="hidden" value="0" name="multiple_bookings">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
 						<div class="col-sm-10">
@@ -254,14 +262,14 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" checked> <?=$lang['add']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="multiple_bookings" checked> <?=$lang['add']['multiple_bookings'];?></label>
+							<label><input type="checkbox" value="1" name="multiple_bookings" checked> <?=$lang['add']['multiple_bookings'];?></label>
 							</div>
 						</div>
 					</div>
@@ -285,6 +293,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] ==
 				<h4><?=$lang['add']['syncjob'];?></h4>
 				<p><?=$lang['add']['syncjob_hint'];?></p>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
+          <input type="hidden" value="0" name="delete1">
+          <input type="hidden" value="0" name="delete2duplicates">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label>
 						<div class="col-sm-10">
@@ -346,27 +357,27 @@ elseif (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] ==
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="delete2duplicates" checked> <?=$lang['add']['delete2duplicates'];?></label>
+							<label><input type="checkbox" value="1" name="delete2duplicates" checked> <?=$lang['add']['delete2duplicates'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="delete1"> <?=$lang['add']['delete1'];?></label>
+							<label><input type="checkbox" value="1" name="delete1"> <?=$lang['add']['delete1'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" checked> <?=$lang['add']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
-							<button type="submit" name="add_syncjob" value="1" class="btn btn-success "><?=$lang['add']['save'];?></button>
+							<button type="submit" name="add_syncjob" class="btn btn-success "><?=$lang['add']['save'];?></button>
 						</div>
 					</div>
 				</form>
diff --git a/data/web/admin.php b/data/web/admin.php
index 9a7f2ba2..2d800622 100644
--- a/data/web/admin.php
+++ b/data/web/admin.php
@@ -100,6 +100,7 @@ $tfa_data = get_tfa();
           <small>
           <legend><?=$lang['admin']['add_domain_admin'];?></legend>
           <form class="form-horizontal" role="form" method="post">
+            <input type="hidden" value="0" name="active">
             <div class="form-group">
               <label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label>
               <div class="col-sm-10">
@@ -134,7 +135,7 @@ $tfa_data = get_tfa();
             <div class="form-group">
               <div class="col-sm-offset-2 col-sm-10">
                 <div class="checkbox">
-                <label><input type="checkbox" name="active" checked> <?=$lang['admin']['active'];?></label>
+                <label><input type="checkbox" value="1" name="active" checked> <?=$lang['admin']['active'];?></label>
                 </div>
               </div>
             </div>
@@ -155,36 +156,39 @@ $tfa_data = get_tfa();
     <div class="panel panel-default">
       <div class="panel-heading"><?=$lang['admin']['dkim_keys'];?></div>
       <div class="panel-body">
-      <form class="form-inline" method="post" data-id="dkimkeys">
+        <div class="mass-actions-admin">
+          <div class="btn-group btn-group-sm">
+            <button type="button" id="toggle_multi_select_all" data-id="dkim" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
+            <button type="button" id="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-danger"><?=$lang['admin']['remove'];?></button>
+          </div>
+        </div>
         <?php
         foreach(mailbox_get_domains() as $domain) {
             if (!empty($dkim = dkim_get_key_details($domain))) {
           ?>
             <div class="row">
-              <div class="col-xs-3">
+              <div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" /></div>
+              <div class="col-xs-2">
                 <p>Domain: <strong><?=htmlspecialchars($domain);?></strong><br />
                   <span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span>
                   <span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span>
                   <span class="label label-info"><?=$dkim['length'];?> bit</span>
                 </p>
               </div>
-              <div class="col-xs-8">
+              <div class="col-xs-9">
                   <pre><?=$dkim['dkim_txt'];?></pre>
               </div>
-              <div class="col-xs-1">
-                <span style="cursor:pointer" data-dkim-domain="<?=$domain;?>" data-dkim-selector="<?=$dkim['dkim_selector'];?>" id="delete_dkim_key" class="text-danger glyphicon glyphicon-remove"></span></a>
-              </div>
             </div>
           <?php
           }
           else {
           ?>
           <div class="row">
-            <div class="col-xs-3">
+              <div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
+            <div class="col-xs-2">
               <p>Domain: <strong><?=htmlspecialchars($domain);?></strong><br /><span class="label label-danger"><?=$lang['admin']['dkim_key_missing'];?></span></p>
             </div>
-            <div class="col-xs-8"><pre>-</pre></div>
-            <div class="col-xs-1">&nbsp;</div>
+            <div class="col-xs-9"><pre>-</pre></div>
           </div>
           <?php
           }
@@ -192,30 +196,28 @@ $tfa_data = get_tfa();
             if (!empty($dkim = dkim_get_key_details($alias_domain))) {
             ?>
               <div class="row">
-                <div class="col-xs-offset-1 col-xs-2">
+              <div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$alias_domain;?>" /></div>
+                <div class="col-xs-1 col-xs-offset-1">
                   <p><small>↳ Alias-Domain: <strong><?=htmlspecialchars($alias_domain);?></strong><br /></small>
                     <span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span>
                     <span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span>
                     <span class="label label-info"><?=$dkim['length'];?> bit</span>
                 </p>
                 </div>
-                <div class="col-xs-8">
+                <div class="col-xs-9">
                   <pre><?=$dkim['dkim_txt'];?></pre>
                 </div>
-                <div class="col-xs-1">
-                  <span style="cursor:pointer" data-dkim-domain="<?=$domain;?>" data-dkim-selector="<?=$dkim['dkim_selector'];?>" id="delete_dkim_key" class="text-danger glyphicon glyphicon-remove"></span></a>
-                </div>
               </div>
             <?php
             }
             else {
             ?>
             <div class="row">
-              <div class="col-xs-2 col-xs-offset-1">
+              <div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
+              <div class="col-xs-1 col-xs-offset-1">
                 <p><small>↳ Alias-Domain: <strong><?=htmlspecialchars($alias_domain);?></strong><br /></small><span class="label label-danger"><?=$lang['admin']['dkim_key_missing'];?></span></p>
               </div>
-            <div class="col-xs-8"><pre>-</pre></div>
-            <div class="col-xs-1">&nbsp;</div>
+            <div class="col-xs-9"><pre>-</pre></div>
             </div>
             <?php
             }
@@ -225,25 +227,22 @@ $tfa_data = get_tfa();
           if (!empty($dkim = dkim_get_key_details($blind))) {
           ?>
             <div class="row">
-              <div class="col-xs-3">
+              <div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$blind;?>" /></div>
+              <div class="col-xs-2">
                 <p>Domain: <strong><?=htmlspecialchars($blind);?></strong><br />
                   <span class="label label-warning"><?=$lang['admin']['dkim_key_unused'];?></span>
                   <span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span>
                   <span class="label label-info"><?=$dkim['length'];?> bit</span>
                 </p>
                 </div>
-                <div class="col-xs-8">
+                <div class="col-xs-9">
                   <pre><?=$dkim['dkim_txt'];?></pre>
                 </div>
-                <div class="col-xs-1">
-                  <span style="cursor:pointer" data-dkim-domain="<?=$blind;?>" data-dkim-selector="<?=$dkim['dkim_selector'];?>" id="delete_dkim_key" class="text-danger glyphicon glyphicon-remove"></span></a>
-                </div>
             </div>
           <?php
           }
         }
         ?>
-        </form>
 
         <legend style="margin-top:40px"><?=$lang['admin']['dkim_add_key'];?></legend>
         <form class="form-inline" role="form" method="post">
@@ -270,21 +269,20 @@ $tfa_data = get_tfa();
       <div class="panel-heading"><?=$lang['admin']['forwarding_hosts'];?></div>
       <div class="panel-body">
         <p style="margin-bottom:40px"><?=$lang['admin']['forwarding_hosts_hint'];?></p>
-        <form method="post" data-id="fwdhosts">
-        <div class="btn-group btn-group-sm">
-          <button type="button" id="toggle_multi_select_all" data-form-id="fwdhosts" class="btn btn-default">Toggle all</button>
-          <button type="button" id="delete_fwdhosts" name="delete_fwdhosts" class="btn btn-danger"><?=$lang['admin']['remove'];?></button>
+        <div class="mass-actions-admin">
+          <div class="btn-group btn-group-sm">
+            <button type="button" id="toggle_multi_select_all" data-id="fwdhosts" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
+            <button type="button" id="delete_selected" name="delete_selected" data-id="fwdhosts" data-api-url="delete/fwdhost" class="btn btn-danger"><?=$lang['admin']['remove'];?></button>
+          </div>
         </div>
-        <hr >
         <div class="table-responsive">
-            <table class="table table-striped" id="forwardinghoststable"></table>
-          </div>
-        </form>
+          <table class="table table-striped" id="forwardinghoststable"></table>
+        </div>
         <legend><?=$lang['admin']['add_forwarding_host'];?></legend>
         <p class="help-block"><?=$lang['admin']['forwarding_hosts_add_hint'];?></p>
         <form class="form-inline" role="form" method="post">
           <div class="form-group">
-            <label for="hostname"><?=$lang['edit']['host'];?></label>
+            <label for="hostname"><?=$lang['admin']['host'];?></label>
             <input class="form-control" id="hostname" name="hostname" placeholder="example.org" required>
           </div>
           <div class="form-group">
diff --git a/data/web/css/mailbox.css b/data/web/css/mailbox.css
index 2e6c1afe..8db97c31 100644
--- a/data/web/css/mailbox.css
+++ b/data/web/css/mailbox.css
@@ -13,21 +13,12 @@ table.footable>tbody>tr.footable-empty>td {
 }
 .footer-add-item {
   display:block;
+  text-align: center;
+  font-style: italic;
   padding: 10px;
   background: #F5F5F5;
 }
-.mass-each-action {
-  padding: 0 3px 0 3px;
-  user-select: none;
-}
-.mass-actions {
-  user-select: none;
-  padding:10px;
-}
-.mass-select-all {
-  cursor:pointer;
-  color:#555;
-}
+
 #alias_table {
   cursor:pointer;
 }
diff --git a/data/web/css/mailcow.css b/data/web/css/mailcow.css
index 90dccf93..3978fcd9 100644
--- a/data/web/css/mailcow.css
+++ b/data/web/css/mailcow.css
@@ -62,4 +62,12 @@ body.modal-open {
   min-width: 350px;
   max-width: 550px;
   z-index: 2000;
-}
\ No newline at end of file
+}
+.mass-actions-mailbox {
+  user-select: none;
+  padding:10px 0 10px 10px;
+}
+.mass-actions-admin {
+  user-select: none;
+  padding:10px 0 10px 0;
+}
diff --git a/data/web/css/noty.css b/data/web/css/noty.css
deleted file mode 100644
index 2df92f1f..00000000
--- a/data/web/css/noty.css
+++ /dev/null
@@ -1,650 +0,0 @@
-.noty_layout_mixin, #noty_layout__top, #noty_layout__topLeft, #noty_layout__topCenter, #noty_layout__topRight, #noty_layout__bottom, #noty_layout__bottomLeft, #noty_layout__bottomCenter, #noty_layout__bottomRight, #noty_layout__center, #noty_layout__centerLeft, #noty_layout__centerRight {
-  position: fixed;
-  margin: 0;
-  padding: 0;
-  z-index: 9999999;
-  -webkit-transform: translateZ(0) scale(1, 1);
-          transform: translateZ(0) scale(1, 1);
-  -webkit-backface-visibility: hidden;
-          backface-visibility: hidden;
-  -webkit-font-smoothing: subpixel-antialiased;
-  filter: blur(0);
-  -webkit-filter: blur(0);
-  max-width: 90%; }
-
-#noty_layout__top {
-  top: 0;
-  left: 5%;
-  width: 90%; }
-
-#noty_layout__topLeft {
-  top: 20px;
-  left: 20px;
-  width: 325px; }
-
-#noty_layout__topCenter {
-  top: 5%;
-  left: 50%;
-  width: 325px;
-  -webkit-transform: translate(-webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
-          transform: translate(calc(-50% - .5px)) translateZ(0) scale(1, 1); }
-
-#noty_layout__topRight {
-  top: 20px;
-  right: 20px;
-  width: 325px; }
-
-#noty_layout__bottom {
-  bottom: 0;
-  left: 5%;
-  width: 90%; }
-
-#noty_layout__bottomLeft {
-  bottom: 20px;
-  left: 20px;
-  width: 325px; }
-
-#noty_layout__bottomCenter {
-  bottom: 5%;
-  left: 50%;
-  width: 325px;
-  -webkit-transform: translate(-webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
-          transform: translate(calc(-50% - .5px)) translateZ(0) scale(1, 1); }
-
-#noty_layout__bottomRight {
-  bottom: 20px;
-  right: 20px;
-  width: 325px; }
-
-#noty_layout__center {
-  top: 50%;
-  left: 50%;
-  width: 325px;
-  -webkit-transform: translate(-webkit-calc(-50% - .5px), -webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
-          transform: translate(calc(-50% - .5px), calc(-50% - .5px)) translateZ(0) scale(1, 1); }
-
-#noty_layout__centerLeft {
-  top: 50%;
-  left: 20px;
-  width: 325px;
-  -webkit-transform: translate(0, -webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
-          transform: translate(0, calc(-50% - .5px)) translateZ(0) scale(1, 1); }
-
-#noty_layout__centerRight {
-  top: 50%;
-  right: 20px;
-  width: 325px;
-  -webkit-transform: translate(0, -webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
-          transform: translate(0, calc(-50% - .5px)) translateZ(0) scale(1, 1); }
-
-.noty_progressbar {
-  display: none; }
-
-.noty_has_timeout .noty_progressbar {
-  display: block;
-  position: absolute;
-  left: 0;
-  bottom: 0;
-  height: 3px;
-  width: 100%;
-  background-color: #646464;
-  opacity: 0.2;
-  filter: alpha(opacity=10); }
-
-.noty_bar {
-  -webkit-backface-visibility: hidden;
-  -webkit-transform: translate(0, 0) translateZ(0) scale(1, 1);
-  -ms-transform: translate(0, 0) scale(1, 1);
-      transform: translate(0, 0) scale(1, 1);
-  -webkit-font-smoothing: subpixel-antialiased;
-  overflow: hidden; }
-
-.noty_effects_open {
-  opacity: 0;
-  -webkit-transform: translate(50%);
-      -ms-transform: translate(50%);
-          transform: translate(50%);
-  -webkit-animation: noty_anim_in 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-          animation: noty_anim_in 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-  -webkit-animation-fill-mode: forwards;
-          animation-fill-mode: forwards; }
-
-.noty_effects_close {
-  -webkit-animation: noty_anim_out 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-          animation: noty_anim_out 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-  -webkit-animation-fill-mode: forwards;
-          animation-fill-mode: forwards; }
-
-.noty_fix_effects_height {
-  -webkit-animation: noty_anim_height 75ms ease-out;
-          animation: noty_anim_height 75ms ease-out; }
-
-.noty_close_with_click {
-  cursor: pointer; }
-
-.noty_close_button {
-  position: absolute;
-  top: 2px;
-  right: 2px;
-  font-weight: bold;
-  width: 20px;
-  height: 20px;
-  text-align: center;
-  line-height: 20px;
-  background-color: rgba(0, 0, 0, 0.05);
-  border-radius: 2px;
-  cursor: pointer;
-  -webkit-transition: all .2s ease-out;
-  transition: all .2s ease-out; }
-
-.noty_close_button:hover {
-  background-color: rgba(0, 0, 0, 0.1); }
-
-.noty_modal {
-  position: fixed;
-  width: 100%;
-  height: 100%;
-  background-color: #000;
-  z-index: 10000;
-  opacity: .3;
-  left: 0;
-  top: 0; }
-
-.noty_modal.noty_modal_open {
-  opacity: 0;
-  -webkit-animation: noty_modal_in .3s ease-out;
-          animation: noty_modal_in .3s ease-out; }
-
-.noty_modal.noty_modal_close {
-  -webkit-animation: noty_modal_out .3s ease-out;
-          animation: noty_modal_out .3s ease-out;
-  -webkit-animation-fill-mode: forwards;
-          animation-fill-mode: forwards; }
-
-@-webkit-keyframes noty_modal_in {
-  100% {
-    opacity: .3; } }
-
-@keyframes noty_modal_in {
-  100% {
-    opacity: .3; } }
-
-@-webkit-keyframes noty_modal_out {
-  100% {
-    opacity: 0; } }
-
-@keyframes noty_modal_out {
-  100% {
-    opacity: 0; } }
-
-@keyframes noty_modal_out {
-  100% {
-    opacity: 0; } }
-
-@-webkit-keyframes noty_anim_in {
-  100% {
-    -webkit-transform: translate(0);
-            transform: translate(0);
-    opacity: 1; } }
-
-@keyframes noty_anim_in {
-  100% {
-    -webkit-transform: translate(0);
-            transform: translate(0);
-    opacity: 1; } }
-
-@-webkit-keyframes noty_anim_out {
-  100% {
-    -webkit-transform: translate(50%);
-            transform: translate(50%);
-    opacity: 0; } }
-
-@keyframes noty_anim_out {
-  100% {
-    -webkit-transform: translate(50%);
-            transform: translate(50%);
-    opacity: 0; } }
-
-@-webkit-keyframes noty_anim_height {
-  100% {
-    height: 0; } }
-
-@keyframes noty_anim_height {
-  100% {
-    height: 0; } }
-
-.noty_theme__relax.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  border-radius: 2px;
-  position: relative; }
-  .noty_theme__relax.noty_bar .noty_body {
-    padding: 10px; }
-  .noty_theme__relax.noty_bar .noty_buttons {
-    border-top: 1px solid #e7e7e7;
-    padding: 5px 10px; }
-
-.noty_theme__relax.noty_type__alert,
-.noty_theme__relax.noty_type__notification {
-  background-color: #fff;
-  border: 1px solid #dedede;
-  color: #444; }
-
-.noty_theme__relax.noty_type__warning {
-  background-color: #FFEAA8;
-  border: 1px solid #FFC237;
-  color: #826200; }
-  .noty_theme__relax.noty_type__warning .noty_buttons {
-    border-color: #dfaa30; }
-
-.noty_theme__relax.noty_type__error {
-  background-color: #FF8181;
-  border: 1px solid #e25353;
-  color: #FFF; }
-  .noty_theme__relax.noty_type__error .noty_buttons {
-    border-color: darkred; }
-
-.noty_theme__relax.noty_type__info,
-.noty_theme__relax.noty_type__information {
-  background-color: #78C5E7;
-  border: 1px solid #3badd6;
-  color: #FFF; }
-  .noty_theme__relax.noty_type__info .noty_buttons,
-  .noty_theme__relax.noty_type__information .noty_buttons {
-    border-color: #0B90C4; }
-
-.noty_theme__relax.noty_type__success {
-  background-color: #BCF5BC;
-  border: 1px solid #7cdd77;
-  color: darkgreen; }
-  .noty_theme__relax.noty_type__success .noty_buttons {
-    border-color: #50C24E; }
-
-.noty_theme__metroui.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  position: relative;
-  box-shadow: rgba(0, 0, 0, 0.298039) 0 0 5px 0; }
-  .noty_theme__metroui.noty_bar .noty_progressbar {
-    position: absolute;
-    left: 0;
-    bottom: 0;
-    height: 3px;
-    width: 100%;
-    background-color: #000;
-    opacity: 0.2;
-    filter: alpha(opacity=20); }
-  .noty_theme__metroui.noty_bar .noty_body {
-    padding: 1.25em;
-    font-size: 14px; }
-  .noty_theme__metroui.noty_bar .noty_buttons {
-    padding: 0 10px .5em 10px; }
-
-.noty_theme__metroui.noty_type__alert,
-.noty_theme__metroui.noty_type__notification {
-  background-color: #fff;
-  color: #1d1d1d; }
-
-.noty_theme__metroui.noty_type__warning {
-  background-color: #FA6800;
-  color: #fff; }
-
-.noty_theme__metroui.noty_type__error {
-  background-color: #CE352C;
-  color: #FFF; }
-
-.noty_theme__metroui.noty_type__info,
-.noty_theme__metroui.noty_type__information {
-  background-color: #1BA1E2;
-  color: #FFF; }
-
-.noty_theme__metroui.noty_type__success {
-  background-color: #60A917;
-  color: #fff; }
-
-.noty_theme__mint.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  border-radius: 2px;
-  position: relative; }
-  .noty_theme__mint.noty_bar .noty_body {
-    padding: 10px;
-    font-size: 14px; }
-  .noty_theme__mint.noty_bar .noty_buttons {
-    padding: 10px; }
-
-.noty_theme__mint.noty_type__alert,
-.noty_theme__mint.noty_type__notification {
-  background-color: #fff;
-  border-bottom: 1px solid #D1D1D1;
-  color: #2F2F2F; }
-
-.noty_theme__mint.noty_type__warning {
-  background-color: #FFAE42;
-  border-bottom: 1px solid #E89F3C;
-  color: #fff; }
-
-.noty_theme__mint.noty_type__error {
-  background-color: #DE636F;
-  border-bottom: 1px solid #CA5A65;
-  color: #fff; }
-
-.noty_theme__mint.noty_type__info,
-.noty_theme__mint.noty_type__information {
-  background-color: #7F7EFF;
-  border-bottom: 1px solid #7473E8;
-  color: #fff; }
-
-.noty_theme__mint.noty_type__success {
-  background-color: #AFC765;
-  border-bottom: 1px solid #A0B55C;
-  color: #fff; }
-
-.noty_theme__sunset.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  border-radius: 2px;
-  position: relative; }
-  .noty_theme__sunset.noty_bar .noty_body {
-    padding: 10px;
-    font-size: 14px;
-    text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); }
-  .noty_theme__sunset.noty_bar .noty_buttons {
-    padding: 10px; }
-
-.noty_theme__sunset.noty_type__alert,
-.noty_theme__sunset.noty_type__notification {
-  background-color: #073B4C;
-  color: #fff; }
-  .noty_theme__sunset.noty_type__alert .noty_progressbar,
-  .noty_theme__sunset.noty_type__notification .noty_progressbar {
-    background-color: #fff; }
-
-.noty_theme__sunset.noty_type__warning {
-  background-color: #FFD166;
-  color: #fff; }
-
-.noty_theme__sunset.noty_type__error {
-  background-color: #EF476F;
-  color: #fff; }
-  .noty_theme__sunset.noty_type__error .noty_progressbar {
-    opacity: .4; }
-
-.noty_theme__sunset.noty_type__info,
-.noty_theme__sunset.noty_type__information {
-  background-color: #118AB2;
-  color: #fff; }
-  .noty_theme__sunset.noty_type__info .noty_progressbar,
-  .noty_theme__sunset.noty_type__information .noty_progressbar {
-    opacity: .6; }
-
-.noty_theme__sunset.noty_type__success {
-  background-color: #06D6A0;
-  color: #fff; }
-
-.noty_theme__bootstrap-v3.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  position: relative;
-  border: 1px solid transparent;
-  border-radius: 4px; }
-  .noty_theme__bootstrap-v3.noty_bar .noty_body {
-    padding: 15px; }
-  .noty_theme__bootstrap-v3.noty_bar .noty_buttons {
-    padding: 10px; }
-  .noty_theme__bootstrap-v3.noty_bar .noty_close_button {
-    font-size: 21px;
-    font-weight: 700;
-    line-height: 1;
-    color: #000;
-    text-shadow: 0 1px 0 #fff;
-    filter: alpha(opacity=20);
-    opacity: .2;
-    background: transparent; }
-  .noty_theme__bootstrap-v3.noty_bar .noty_close_button:hover {
-    background: transparent;
-    text-decoration: none;
-    cursor: pointer;
-    filter: alpha(opacity=50);
-    opacity: .5; }
-
-.noty_theme__bootstrap-v3.noty_type__alert,
-.noty_theme__bootstrap-v3.noty_type__notification {
-  background-color: #fff;
-  color: inherit; }
-
-.noty_theme__bootstrap-v3.noty_type__warning {
-  background-color: #fcf8e3;
-  color: #8a6d3b;
-  border-color: #faebcc; }
-
-.noty_theme__bootstrap-v3.noty_type__error {
-  background-color: #f2dede;
-  color: #a94442;
-  border-color: #ebccd1; }
-
-.noty_theme__bootstrap-v3.noty_type__info,
-.noty_theme__bootstrap-v3.noty_type__information {
-  background-color: #d9edf7;
-  color: #31708f;
-  border-color: #bce8f1; }
-
-.noty_theme__bootstrap-v3.noty_type__success {
-  background-color: #dff0d8;
-  color: #3c763d;
-  border-color: #d6e9c6; }
-
-.noty_theme__bootstrap-v4.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  position: relative;
-  border: 1px solid transparent;
-  border-radius: .25rem; }
-  .noty_theme__bootstrap-v4.noty_bar .noty_body {
-    padding: .75rem 1.25rem; }
-  .noty_theme__bootstrap-v4.noty_bar .noty_buttons {
-    padding: 10px; }
-  .noty_theme__bootstrap-v4.noty_bar .noty_close_button {
-    font-size: 1.5rem;
-    font-weight: 700;
-    line-height: 1;
-    color: #000;
-    text-shadow: 0 1px 0 #fff;
-    filter: alpha(opacity=20);
-    opacity: .5;
-    background: transparent; }
-  .noty_theme__bootstrap-v4.noty_bar .noty_close_button:hover {
-    background: transparent;
-    text-decoration: none;
-    cursor: pointer;
-    filter: alpha(opacity=50);
-    opacity: .75; }
-
-.noty_theme__bootstrap-v4.noty_type__alert,
-.noty_theme__bootstrap-v4.noty_type__notification {
-  background-color: #fff;
-  color: inherit; }
-
-.noty_theme__bootstrap-v4.noty_type__warning {
-  background-color: #fcf8e3;
-  color: #8a6d3b;
-  border-color: #faebcc; }
-
-.noty_theme__bootstrap-v4.noty_type__error {
-  background-color: #f2dede;
-  color: #a94442;
-  border-color: #ebccd1; }
-
-.noty_theme__bootstrap-v4.noty_type__info,
-.noty_theme__bootstrap-v4.noty_type__information {
-  background-color: #d9edf7;
-  color: #31708f;
-  border-color: #bce8f1; }
-
-.noty_theme__bootstrap-v4.noty_type__success {
-  background-color: #dff0d8;
-  color: #3c763d;
-  border-color: #d6e9c6; }
-
-.noty_theme__semanticui.noty_bar {
-  margin: 4px 0;
-  overflow: hidden;
-  position: relative;
-  border: 1px solid transparent;
-  font-size: 1em;
-  border-radius: .28571429rem;
-  box-shadow: 0 0 0 1px rgba(34, 36, 38, 0.22) inset, 0 0 0 0 transparent; }
-  .noty_theme__semanticui.noty_bar .noty_body {
-    padding: 1em 1.5em;
-    line-height: 1.4285em; }
-  .noty_theme__semanticui.noty_bar .noty_buttons {
-    padding: 10px; }
-
-.noty_theme__semanticui.noty_type__alert,
-.noty_theme__semanticui.noty_type__notification {
-  background-color: #f8f8f9;
-  color: rgba(0, 0, 0, 0.87); }
-
-.noty_theme__semanticui.noty_type__warning {
-  background-color: #fffaf3;
-  color: #573a08;
-  box-shadow: 0 0 0 1px #c9ba9b inset, 0 0 0 0 transparent; }
-
-.noty_theme__semanticui.noty_type__error {
-  background-color: #fff6f6;
-  color: #9f3a38;
-  box-shadow: 0 0 0 1px #e0b4b4 inset, 0 0 0 0 transparent; }
-
-.noty_theme__semanticui.noty_type__info,
-.noty_theme__semanticui.noty_type__information {
-  background-color: #f8ffff;
-  color: #276f86;
-  box-shadow: 0 0 0 1px #a9d5de inset, 0 0 0 0 transparent; }
-
-.noty_theme__semanticui.noty_type__success {
-  background-color: #fcfff5;
-  color: #2c662d;
-  box-shadow: 0 0 0 1px #a3c293 inset, 0 0 0 0 transparent; }
-
-.noty_theme__nest.noty_bar {
-  margin: 0 0 15px 0;
-  overflow: hidden;
-  border-radius: 2px;
-  position: relative;
-  box-shadow: rgba(0, 0, 0, 0.098039) 5px 4px 10px 0; }
-  .noty_theme__nest.noty_bar .noty_body {
-    padding: 10px;
-    font-size: 14px;
-    text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); }
-  .noty_theme__nest.noty_bar .noty_buttons {
-    padding: 10px; }
-
-.noty_layout .noty_theme__nest.noty_bar {
-  z-index: 5; }
-
-.noty_layout .noty_theme__nest.noty_bar:nth-child(2) {
-  position: absolute;
-  top: 0;
-  margin-top: 4px;
-  margin-right: -4px;
-  margin-left: 4px;
-  z-index: 4;
-  width: 100%; }
-
-.noty_layout .noty_theme__nest.noty_bar:nth-child(3) {
-  position: absolute;
-  top: 0;
-  margin-top: 8px;
-  margin-right: -8px;
-  margin-left: 8px;
-  z-index: 3;
-  width: 100%; }
-
-.noty_layout .noty_theme__nest.noty_bar:nth-child(4) {
-  position: absolute;
-  top: 0;
-  margin-top: 12px;
-  margin-right: -12px;
-  margin-left: 12px;
-  z-index: 2;
-  width: 100%; }
-
-.noty_layout .noty_theme__nest.noty_bar:nth-child(5) {
-  position: absolute;
-  top: 0;
-  margin-top: 16px;
-  margin-right: -16px;
-  margin-left: 16px;
-  z-index: 1;
-  width: 100%; }
-
-.noty_layout .noty_theme__nest.noty_bar:nth-child(n+6) {
-  position: absolute;
-  top: 0;
-  margin-top: 20px;
-  margin-right: -20px;
-  margin-left: 20px;
-  z-index: -1;
-  width: 100%; }
-
-#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(2),
-#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(2) {
-  margin-top: 4px;
-  margin-left: -4px;
-  margin-right: 4px; }
-
-#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(3),
-#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(3) {
-  margin-top: 8px;
-  margin-left: -8px;
-  margin-right: 8px; }
-
-#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(4),
-#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(4) {
-  margin-top: 12px;
-  margin-left: -12px;
-  margin-right: 12px; }
-
-#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(5),
-#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(5) {
-  margin-top: 16px;
-  margin-left: -16px;
-  margin-right: 16px; }
-
-#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(n+6),
-#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(n+6) {
-  margin-top: 20px;
-  margin-left: -20px;
-  margin-right: 20px; }
-
-.noty_theme__nest.noty_type__alert,
-.noty_theme__nest.noty_type__notification {
-  background-color: #073B4C;
-  color: #fff; }
-  .noty_theme__nest.noty_type__alert .noty_progressbar,
-  .noty_theme__nest.noty_type__notification .noty_progressbar {
-    background-color: #fff; }
-
-.noty_theme__nest.noty_type__warning {
-  background-color: #FFD166;
-  color: #fff; }
-
-.noty_theme__nest.noty_type__error {
-  background-color: #EF476F;
-  color: #fff; }
-  .noty_theme__nest.noty_type__error .noty_progressbar {
-    opacity: .4; }
-
-.noty_theme__nest.noty_type__info,
-.noty_theme__nest.noty_type__information {
-  background-color: #118AB2;
-  color: #fff; }
-  .noty_theme__nest.noty_type__info .noty_progressbar,
-  .noty_theme__nest.noty_type__information .noty_progressbar {
-    opacity: .6; }
-
-.noty_theme__nest.noty_type__success {
-  background-color: #06D6A0;
-  color: #fff; }
-
-/*# sourceMappingURL=noty.css.map*/
\ No newline at end of file
diff --git a/data/web/edit.php b/data/web/edit.php
index 3f3311d0..1532d06b 100644
--- a/data/web/edit.php
+++ b/data/web/edit.php
@@ -26,6 +26,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<h4><?=$lang['edit']['alias'];?></h4>
 					<br />
 					<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
 					<input type="hidden" name="address" value="<?=htmlspecialchars($alias);?>">
 						<div class="form-group">
 							<label class="control-label col-sm-2" for="goto"><?=$lang['edit']['target_address'];?></label>
@@ -36,7 +37,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 						<div class="form-group">
 							<div class="col-sm-offset-2 col-sm-10">
 								<div class="checkbox">
-								<label><input type="checkbox" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
+								<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
 								</div>
 							</div>
 						</div>
@@ -66,6 +67,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 				<h4><?=$lang['edit']['domain_admin'];?></h4>
 				<br />
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+        <input type="hidden" value="0" name="active">
 				<input type="hidden" name="username_now" value="<?=htmlspecialchars($domain_admin);?>">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="username"><?=$lang['edit']['username'];?></label>
@@ -107,14 +109,14 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="disable_tfa"> <?=$lang['tfa']['disable_tfa'];?></label>
+							<label><input type="checkbox" value="1" name="disable_tfa"> <?=$lang['tfa']['disable_tfa'];?></label>
 							</div>
 						</div>
 					</div>
@@ -141,6 +143,9 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 			?>
 				<h4><?=$lang['edit']['domain'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+        <input type="hidden" value="0" name="active">
+        <input type="hidden" value="0" name="backupmx">
+        <input type="hidden" value="0" name="relay_all_recipients">
 				<input type="hidden" name="domain" value="<?=htmlspecialchars($domain);?>">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="description"><?=$lang['edit']['description'];?></label>
@@ -179,9 +184,9 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 						<label class="control-label col-sm-2"><?=$lang['edit']['backup_mx_options'];?></label>
 						<div class="col-sm-10">
 							<div class="checkbox">
-								<label><input type="checkbox" name="backupmx" <?=(isset($result['backupmx_int']) && $result['backupmx_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['relay_domain'];?></label>
+								<label><input type="checkbox" value="1" name="backupmx" <?=(isset($result['backupmx_int']) && $result['backupmx_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['relay_domain'];?></label>
 								<br />
-								<label><input type="checkbox" name="relay_all_recipients" <?=(isset($result['relay_all_recipients_int']) && $result['relay_all_recipients_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['relay_all'];?></label>
+								<label><input type="checkbox" value="1" name="relay_all_recipients" <?=(isset($result['relay_all_recipients_int']) && $result['relay_all_recipients_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['relay_all'];?></label>
 								<p><?=$lang['edit']['relay_all_info'];?></p>
 							</div>
 						</div>
@@ -192,7 +197,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-								<label><input type="checkbox" name="active" <?=(isset($result['active_int']) && $result['active_int']=="1") ? "checked" : null;?> <?=($_SESSION['mailcow_cc_role'] == "admin") ? null : "disabled";?>> <?=$lang['edit']['active'];?></label>
+								<label><input type="checkbox" value="1" name="active" <?=(isset($result['active_int']) && $result['active_int']=="1") ? "checked" : null;?> <?=($_SESSION['mailcow_cc_role'] == "admin") ? null : "disabled";?>> <?=$lang['edit']['active'];?></label>
 							</div>
 						</div>
 					</div>
@@ -350,17 +355,18 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 			?>
 				<h4><?=$lang['edit']['edit_alias_domain'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
-					<input type="hidden" name="alias_domain_now" value="<?=htmlspecialchars($alias_domain);?>">
+          <input type="hidden" value="0" name="active">
+          <input type="hidden" value="<?=$result['alias_domain'];?>" name="alias_domain">
 					<div class="form-group">
-						<label class="control-label col-sm-2" for="alias_domain"><?=$lang['edit']['alias_domain'];?></label>
+						<label class="control-label col-sm-2" for="target_domain"><?=$lang['edit']['target_domain'];?></label>
 						<div class="col-sm-10">
-							<input type="text" class="form-control" name="alias_domain" id="alias_domain" value="<?=htmlspecialchars($result['alias_domain']);?>">
+							<input type="text" class="form-control" name="target_domain" id="target_domain" value="<?=htmlspecialchars($result['target_domain']);?>">
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-								<label><input type="checkbox" name="active" <?=(isset($result['active_int']) && $result['active_int']=="1") ?  "checked" : null ?>> <?=$lang['edit']['active'];?></label>
+								<label><input type="checkbox" value="1" name="active" <?=(isset($result['active_int']) && $result['active_int']=="1") ?  "checked" : null ?>> <?=$lang['edit']['active'];?></label>
 							</div>
 						</div>
 					</div>
@@ -398,6 +404,8 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
       ?>
       <h4><?=$lang['edit']['mailbox'];?></h4>
       <form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+      <input type="hidden" value="0" name="sender_acl">
+      <input type="hidden" value="0" name="active">
       <input type="hidden" name="username" value="<?=htmlspecialchars($result['username']);?>">
         <div class="form-group">
           <label class="control-label col-sm-2" for="name"><?=$lang['edit']['full_name'];?>:</label>
@@ -481,7 +489,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
         <div class="form-group">
           <div class="col-sm-offset-2 col-sm-10">
             <div class="checkbox">
-            <label><input type="checkbox" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
+            <label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
             </div>
           </div>
         </div>
@@ -501,6 +509,8 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
         ?>
 				<h4><?=$lang['edit']['resource'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+          <input type="hidden" value="0" name="active">
+          <input type="hidden" value="0" name="multiple_bookings">
           <input type="hidden" name="name" value="<?=htmlspecialchars($result['name']);?>">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
@@ -521,14 +531,14 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" <?=($result['active_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['active'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="multiple_bookings" <?=($result['multiple_bookings_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['multiple_bookings'];?></label>
+							<label><input type="checkbox" value="1" name="multiple_bookings" <?=($result['multiple_bookings_int']=="1") ? "checked" : null;?>> <?=$lang['edit']['multiple_bookings'];?></label>
 							</div>
 						</div>
 					</div>
@@ -561,6 +571,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] ==
 			?>
 				<h4><?=$lang['edit']['syncjob'];?></h4>
 				<form class="form-horizontal" role="form" method="post" action="<?=($FORM_ACTION == "previous") ? $_SESSION['return_to'] : null;?>">
+        <input type="hidden" value="0" name="delete2duplicates">
+        <input type="hidden" value="0" name="delete1">
+        <input type="hidden" value="0" name="active">
 				<input type="hidden" name="id" value="<?=htmlspecialchars($result['id']);?>">
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="host1"><?=$lang['edit']['hostname'];?></label>
@@ -623,21 +636,21 @@ elseif (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] ==
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="delete2duplicates" <?=($result['delete2duplicates']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete2duplicates'];?></label>
+							<label><input type="checkbox" value="1" name="delete2duplicates" <?=($result['delete2duplicates']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete2duplicates'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="delete1" <?=($result['delete1']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete1'];?></label>
+							<label><input type="checkbox" value="1" name="delete1" <?=($result['delete1']=="1") ? "checked" : "";?>> <?=$lang['edit']['delete1'];?></label>
 							</div>
 						</div>
 					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">
-							<label><input type="checkbox" name="active" <?=($result['active']=="1") ? "checked" : "";?>> <?=$lang['edit']['active'];?></label>
+							<label><input type="checkbox" value="1" name="active" <?=($result['active']=="1") ? "checked" : "";?>> <?=$lang['edit']['active'];?></label>
 							</div>
 						</div>
 					</div>
diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php
index 08fd6d00..d809a160 100644
--- a/data/web/inc/footer.inc.php
+++ b/data/web/inc/footer.inc.php
@@ -226,12 +226,15 @@ $(document).ready(function() {
 			}
 		});
 	});
+
+  if ($('#mailcow-alert').hasClass('alert-success')) {
+    $('#mailcow-alert').delay(5000).animate({right: '-50%'}, 1000);
+  };
 });
 </script>
 
 <div class="container">
   <div id="mailcow-alert" class="alert" role="alert">
-    <a href="#" class="close" data-dismiss="alert"> &times;</a>
     <span id="mailcow-alert-text"></span>
   </div>
 </div>
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index ac99a014..7d1594ad 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -733,9 +733,9 @@ function add_policy_list_item($postarray) {
   // If 'delete_prefid' then delete item id
 	global $lang;
 	global $pdo;
-  (isset($postarray['username'])) ? $object = $postarray['username'] : null;
-  (isset($postarray['domain']))   ? $object = $postarray['domain'] : null;
-  (!isset($object))               ? $object = $_SESSION['mailcow_cc_username'] : null;
+  $object = (isset($postarray['username'])) ? $postarray['username'] : null;
+  $object = (isset($postarray['domain'])) ? $postarray['domain'] : null;
+  (!isset($object)) ? $object = $_SESSION['mailcow_cc_username'] : null;
 
   if (is_valid_domain_name($object)) {
 		if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
@@ -826,9 +826,9 @@ function delete_policy_list_item($postarray) {
   // 'delete_prefid' is item to be deleted
 	global $lang;
 	global $pdo;
-  (isset($postarray['username'])) ? $object = $postarray['username'] : null;
-  (isset($postarray['domain']))   ? $object = $postarray['domain'] : null;
-  (!isset($object))               ? $object = $_SESSION['mailcow_cc_username'] : null;
+  $object = (isset($postarray['username'])) ? $postarray['username'] : null;
+  $object = (isset($postarray['domain'])) ? $postarray['domain'] : null;
+  (!isset($object)) ? $object = $_SESSION['mailcow_cc_username'] : null;
 
   if (is_valid_domain_name($object)) {
 		if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
@@ -1010,9 +1010,10 @@ function add_syncjob($postarray) {
   else {
     $username = $_SESSION['mailcow_cc_username'];
   }
-  isset($postarray['active']) ? $active = '1' : $active = '0';
-  isset($postarray['delete2duplicates']) ? $delete2duplicates = '1' : $delete2duplicates = '0';
-  isset($postarray['delete1']) ? $delete1 = '1' : $delete1 = '0';
+
+	$active  = intval($postarray['active']);
+	$delete2duplicates = intval($postarray['delete2duplicates']);
+	$delete1  = intval($postarray['delete1']);
   $port1            = $postarray['port1'];
   $host1            = $postarray['host1'];
   $password1        = $postarray['password1'];
@@ -1137,9 +1138,10 @@ function edit_syncjob($postarray) {
   else {
     $username = $_SESSION['mailcow_cc_username'];
   }
-  isset($postarray['active']) ? $active = '1' : $active = '0';
-  isset($postarray['delete2duplicates']) ? $delete2duplicates = '1' : $delete2duplicates = '0';
-  isset($postarray['delete1']) ? $delete1 = '1' : $delete1 = '0';
+  
+	$active           = intval($postarray['active']);
+	$delete2duplicates = intval($postarray['delete2duplicates']);
+	$delete1          = intval($postarray['delete1']);
   $id               = $postarray['id'];
   $port1            = $postarray['port1'];
   $host1            = $postarray['host1'];
@@ -1263,8 +1265,8 @@ function edit_tls_policy($postarray) {
   else {
     $username = $_SESSION['mailcow_cc_username'];
   }
-	isset($postarray['tls_in']) ? $tls_in = '1' : $tls_in = '0';
-	isset($postarray['tls_out']) ? $tls_out = '1' : $tls_out = '0';
+  $tls_out = intval($postarray['tls_out']);
+  $tls_in = intval($postarray['tls_in']);
 	$username = $_SESSION['mailcow_cc_username'];
 	if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
 		$_SESSION['return'] = array(
@@ -1480,7 +1482,8 @@ function add_domain_admin($postarray) {
 	$username		= strtolower(trim($postarray['username']));
 	$password		= $postarray['password'];
 	$password2  = $postarray['password2'];
-	isset($postarray['active']) ? $active = '1' : $active = '0';
+  $active  = intval($postarray['active']);
+
 	if ($_SESSION['mailcow_cc_role'] != "admin") {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
@@ -1793,7 +1796,7 @@ function set_tfa($postarray) {
   
 	switch ($postarray["tfa_method"]) {
 		case "yubi_otp":
-      (!isset($postarray["key_id"])) ? $key_id = 'unidentified' : $key_id = $postarray["key_id"];
+      $key_id = (!isset($postarray["key_id"])) ? 'unidentified' : $postarray["key_id"];
       $yubico_id = $postarray['yubico_id'];
       $yubico_key = $postarray['yubico_key'];
       $yubi = new Auth_Yubico($yubico_id, $yubico_key);
@@ -1845,8 +1848,8 @@ function set_tfa($postarray) {
 		break;
 
 		case "u2f":
+      $key_id = (!isset($postarray["key_id"])) ? 'unidentified' : $postarray["key_id"];
       try {
-        (!isset($postarray["key_id"])) ? $key_id = 'unidentified' : $key_id = $postarray["key_id"];
         $reg = $u2f->doRegister(json_decode($_SESSION['regReq']), json_decode($postarray['token']));
         $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username AND `authmech` != 'u2f'");
 				$stmt->execute(array(':username' => $username));
@@ -1869,7 +1872,7 @@ function set_tfa($postarray) {
 		break;
 
 		case "totp":
-      (!isset($postarray["key_id"])) ? $key_id = 'unidentified' : $key_id = $postarray["key_id"];
+      $key_id = (!isset($postarray["key_id"])) ? 'unidentified' : $postarray["key_id"];
       if ($tfa->verifyCode($_POST['totp_secret'], $_POST['totp_confirm_token']) === true) {
         try {
         $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
@@ -2139,7 +2142,7 @@ function edit_domain_admin($postarray) {
     $username_now = $postarray['username_now'];
     $password     = $postarray['password'];
     $password2    = $postarray['password2'];
-    isset($postarray['active']) ? $active = '1' : $active = '0';
+    $active       = intval($postarray['active']);
 
     if(isset($postarray['domain'])) {
       foreach ($postarray['domain'] as $domain) {
@@ -2520,11 +2523,10 @@ function dkim_delete_key($postarray) {
       return false;
     }
     try {
-      foreach ($redis->hGetAll('DKIM_SELECTORS') as $domain_name => $selector) {
-        $redis->hDel('DKIM_PUB_KEYS', $domain_name);
-        $redis->hDel('DKIM_PRIV_KEYS', $selector . '.' . $domain_name);
-        $redis->hDel('DKIM_SELECTORS', $domain_name);
-      }
+      $selector = $redis->hGet('DKIM_SELECTORS', $domain);
+      $redis->hDel('DKIM_PUB_KEYS', $domain);
+      $redis->hDel('DKIM_PRIV_KEYS', $selector . '.' . $domain);
+      $redis->hDel('DKIM_SELECTORS', $selector);
     }
     catch (RedisException $e) {
       $_SESSION['return'] = array(
@@ -2536,7 +2538,7 @@ function dkim_delete_key($postarray) {
   }
   $_SESSION['return'] = array(
     'type' => 'success',
-    'msg' => sprintf($lang['success']['dkim_removed'])
+    'msg' => sprintf($lang['success']['dkim_removed'], htmlspecialchars(implode(', ', $domains)))
   );
   return true;
 }
@@ -2584,10 +2586,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;
+  $active = intval($postarray['active']);
+  $relay_all_recipients = intval($postarray['relay_all_recipients']);
+  $backupmx = intval($postarray['backupmx']);
+  ($relay_all_recipients == 1) ? $backupmx = '1' : null;
 
 	if (!is_valid_domain_name($domain)) {
 		$_SESSION['return'] = array(
@@ -2679,7 +2681,7 @@ function mailbox_add_alias($postarray) {
 	global $pdo;
 	$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';
+  $active = intval($postarray['active']);
 	if (empty($addresses[0])) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
@@ -2695,24 +2697,23 @@ function mailbox_add_alias($postarray) {
 		);
 		return false;
 	}
-
-  $stmt = $pdo->prepare("SELECT `address` FROM `alias`
-    WHERE `address`= :address");
-  $stmt->execute(array(':address' => $address));
-  $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
-  if ($num_results != 0) {
-    $_SESSION['return'] = array(
-      'type' => 'danger',
-      'msg' => sprintf($lang['danger']['is_alias_or_mailbox'], htmlspecialchars($address))
-    );
-    return false;
-  }
-
 	foreach ($addresses as $address) {
 		if (empty($address)) {
 			continue;
 		}
 
+    $stmt = $pdo->prepare("SELECT `address` FROM `alias`
+      WHERE `address`= :address");
+    $stmt->execute(array(':address' => $address));
+    $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+    if ($num_results != 0) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['is_alias_or_mailbox'], htmlspecialchars($address))
+      );
+      return false;
+    }
+
 		$domain       = idn_to_ascii(substr(strstr($address, '@'), 1));
 		$local_part   = strstr($address, '@', true);
 		$address      = $local_part.'@'.$domain;
@@ -2725,7 +2726,7 @@ function mailbox_add_alias($postarray) {
       );
       return false;
     }
-      
+
 		try {
 			$stmt = $pdo->prepare("SELECT `domain` FROM `domain`
 				WHERE `domain`= :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2)");
@@ -2734,7 +2735,7 @@ function mailbox_add_alias($postarray) {
       if ($num_results == 0) {
         $_SESSION['return'] = array(
           'type' => 'danger',
-          'msg' => sprintf($lang['danger']['domain_not_found'], $domain)
+          'msg' => sprintf($lang['danger']['domain_not_found'], htmlspecialchars($domain))
         );
         return false;
       }
@@ -2874,7 +2875,7 @@ function mailbox_add_alias_domain($postarray) {
   // target_domain  string
 	global $lang;
 	global $pdo;
-	isset($postarray['active']) ? $active = '1' : $active = '0';
+  $active = intval($postarray['active']);
 	$alias_domain     = idn_to_ascii(strtolower(trim($postarray['alias_domain'])));
 	$target_domain    = idn_to_ascii(strtolower(trim($postarray['target_domain'])));
 
@@ -3005,7 +3006,7 @@ function mailbox_add_mailbox($postarray) {
 		$name = $local_part;
 	}
 
-	isset($postarray['active']) ? $active = '1' : $active = '0';
+  $active = intval($postarray['active']);
 
 	$quota_b		= ($quota_m * 1048576);
 	$maildir		= $domain."/".$local_part."/";
@@ -3207,8 +3208,8 @@ function mailbox_add_resource($postarray) {
   $local_part         = preg_replace('/[^\da-z]/i', '', preg_quote($description, '/'));
   $name               = $local_part . '@' . $domain;
   $kind               = $postarray['kind'];
-	isset($postarray['active']) ? $active = '1' : $active = '0';
-	isset($postarray['multiple_bookings']) ? $multiple_bookings = '1' : $multiple_bookings = '0';
+  $active = intval($postarray['active']);
+  $multiple_bookings = intval($postarray['multiple_bookings']);
 
 	if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
 		$_SESSION['return'] = array(
@@ -3331,95 +3332,75 @@ function mailbox_add_resource($postarray) {
 	}
 }
 function mailbox_edit_alias_domain($postarray) {
-  // Array elements
-  // active             int
-  // alias_domain_now   string
-  // alias_domain       string
+  // active         int
+  // target_domain  string
+  // alias_domain   string/array of strings
 	global $lang;
 	global $pdo;
-	isset($postarray['active']) ? $active = '1' : $active = '0';
-	$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',
-			'msg' => sprintf($lang['danger']['alias_domain_invalid'])
-		);
-		return false;
-	}
-
-	if (!is_valid_domain_name($alias_domain_now)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['alias_domain_invalid'])
-		);
-		return false;
-	}
-
-	try {
-		$stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
-				WHERE `alias_domain`= :alias_domain_now");
-		$stmt->execute(array(':alias_domain_now' => $alias_domain_now));
-		$DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
-	}
-	catch(PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-
-	try {
-		$stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
-		WHERE `target_domain`= :alias_domain");
-		$stmt->execute(array(':alias_domain' => $alias_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']['aliasd_targetd_identical'])
-		);
-		return false;
-	}
-
-	try {
-		$stmt = $pdo->prepare("UPDATE `alias_domain` SET
-      `alias_domain` = :alias_domain,
-      `active` = :active
-        WHERE `alias_domain` = :alias_domain_now");
-		$stmt->execute(array(
-			':alias_domain' => $alias_domain,
-			':alias_domain_now' => $alias_domain_now,
-			':active' => $active
-		));
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-
+  if (!is_array($postarray['alias_domain'])) {
+    $alias_domains = array();
+    $alias_domains[] = $postarray['alias_domain'];
+  }
+  else {
+    $alias_domains = $postarray['alias_domain'];
+  }
+  foreach ($alias_domains as $alias_domain) {
+    $alias_domain = idn_to_ascii(strtolower(trim($alias_domain)));
+    $is_now = mailbox_get_alias_domain_details($alias_domain);
+    if (!empty($is_now)) {
+      $active         = (isset($postarray['active'])) ? $postarray['active'] : $is_now['active_int'];
+      $target_domain  = (!empty($postarray['target_domain'])) ? idn_to_ascii(strtolower(trim($postarray['target_domain']))) : $is_now['target_domain'];
+    }
+    else {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['alias_domain_invalid'])
+      );
+      return false;
+    }
+    if (!is_valid_domain_name($target_domain)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['target_domain_invalid'])
+      );
+      return false;
+    }
+    if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $target_domain)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+    if (empty(mailbox_get_domain_details($target_domain))) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['target_domain_invalid'])
+      );
+      return false;
+    }
+    try {
+      $stmt = $pdo->prepare("UPDATE `alias_domain` SET
+        `target_domain` = :target_domain,
+        `active` = :active
+          WHERE `alias_domain` = :alias_domain");
+      $stmt->execute(array(
+        ':alias_domain' => $alias_domain,
+        ':target_domain' => $target_domain,
+        ':active' => $active
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
+  }
 	$_SESSION['return'] = array(
 		'type' => 'success',
-		'msg' => sprintf($lang['success']['aliasd_modified'], htmlspecialchars($alias_domain))
+		'msg' => sprintf($lang['success']['aliasd_modified'], htmlspecialchars(implode(', ', $alias_domains)))
 	);
 }
 function mailbox_edit_alias($postarray) {
@@ -3430,13 +3411,26 @@ function mailbox_edit_alias($postarray) {
 	global $lang;
 	global $pdo;
   if (!is_array($postarray['address'])) {
-    $address_array = array();
-    $address_array[] = $postarray['address'];
+    $addresses = array();
+    $addresses[] = $postarray['address'];
   }
   else {
-    $address_array = $postarray['address'];
+    $addresses = $postarray['address'];
   }
-	if (isset($postarray['goto']) || !empty($postarray['goto'])) {
+  foreach ($addresses as $address) {
+    $is_now = mailbox_get_alias_details($address);
+    if (!empty($is_now)) {
+      $active = (isset($postarray['active'])) ? $postarray['active'] : $is_now['active_int'];
+      $goto   = (!empty($postarray['goto'])) ? $postarray['goto'] : $is_now['goto'];
+    }
+    else {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['alias_invalid'])
+      );
+      return false;
+    }
+    
     $gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $postarray['goto']));
     foreach ($gotos as &$goto) {
       if (empty($goto)) {
@@ -3459,11 +3453,10 @@ function mailbox_edit_alias($postarray) {
     }
     $gotos = array_filter($gotos);
     $goto = implode(",", $gotos);
-  }
-	isset($postarray['active']) ? $active = '1' : $active = '0';
-  foreach ($address_array as $address) {
-    $domain       = idn_to_ascii(substr(strstr($address, '@'), 1));
-    $local_part   = strstr($address, '@', true);
+    
+    $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',
@@ -3471,6 +3464,7 @@ function mailbox_edit_alias($postarray) {
       );
       return false;
     }
+
     if ((!filter_var($address, FILTER_VALIDATE_EMAIL) === true) && !empty($local_part)) {
       $_SESSION['return'] = array(
         'type' => 'danger',
@@ -3478,8 +3472,9 @@ function mailbox_edit_alias($postarray) {
       );
       return false;
     }
+
     try {
-      if (isset($goto) && !empty($goto)) {
+      if (!empty($goto)) {
         $stmt = $pdo->prepare("UPDATE `alias` SET
           `goto` = :goto,
           `active`= :active
@@ -3510,7 +3505,7 @@ function mailbox_edit_alias($postarray) {
 	}
   $_SESSION['return'] = array(
     'type' => 'success',
-    'msg' => sprintf($lang['success']['alias_modified'], htmlspecialchars(implode(', ', $address_array)))
+    'msg' => sprintf($lang['success']['alias_modified'], htmlspecialchars(implode(', ', $addresses)))
   );
 }
 function mailbox_edit_domain($postarray) {
@@ -3529,288 +3524,416 @@ function mailbox_edit_domain($postarray) {
 	global $lang;
 	global $pdo;
   
-  $domain       = idn_to_ascii($postarray['domain']);
-	if (!is_valid_domain_name($domain)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['domain_invalid'])
-		);
-		return false;
-	}
-
-	if ($_SESSION['mailcow_cc_role'] == "domainadmin" && 	hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
-    $description  = $postarray['description'];
-    isset($postarray['active']) ? $active = '1' : $active = '0';
-    try {
-      $stmt = $pdo->prepare("UPDATE `domain` SET 
-      `description` = :description
-        WHERE `domain` = :domain");
-      $stmt->execute(array(
-        ':description' => $description,
-        ':domain' => $domain
-      ));
-      $_SESSION['return'] = array(
-        'type' => 'success',
-        'msg' => sprintf($lang['success']['domain_modified'], htmlspecialchars($domain))
-      );
-    }
-    catch (PDOException $e) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => 'MySQL: '.$e
-      );
-      return false;
-    }
+  if (!is_array($postarray['domain'])) {
+    $domains = array();
+    $domains[] = $postarray['domain'];
   }
-  elseif ($_SESSION['mailcow_cc_role'] == "admin") {
-    $description  = $postarray['description'];
-    isset($postarray['active']) ? $active = '1' : $active = '0';
-    $aliases		= filter_var($postarray['aliases'], 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);
-    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;
-    try {
-      // GET MAILBOX DATA
-      $stmt = $pdo->prepare("SELECT 
-          COUNT(*) AS count,
-          MAX(COALESCE(ROUND(`quota`/1048576), 0)) AS `maxquota`,
-          COALESCE(ROUND(SUM(`quota`)/1048576), 0) AS `quota`
-            FROM `mailbox`
-              WHERE `kind` NOT REGEXP 'location|thing|group'
-                AND domain = :domain");
-      $stmt->execute(array(':domain' => $domain));
-      $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
-      // GET ALIAS DATA
-      $stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias`
-          WHERE domain = :domain
-          AND address NOT IN (
-            SELECT `username` FROM `mailbox`
-          )");
-      $stmt->execute(array(':domain' => $domain));
-      $AliasData = $stmt->fetch(PDO::FETCH_ASSOC);
-    }
-    catch(PDOException $e) {
+  else {
+    $domains = $postarray['domain'];
+  }
+  foreach ($domains as $domain) {
+    $domain = idn_to_ascii($domain);
+    if (!is_valid_domain_name($domain)) {
       $_SESSION['return'] = array(
         'type' => 'danger',
-        'msg' => 'MySQL: '.$e
+        'msg' => sprintf($lang['danger']['domain_invalid'])
       );
       return false;
     }
-
-    if ($maxquota > $quota) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['mailbox_quota_exceeds_domain_quota'])
-      );
-      return false;
+    if ($_SESSION['mailcow_cc_role'] == "domainadmin" &&
+    hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
+      $description  = $postarray['description'];
+      $active = intval($postarray['active']);
+      try {
+        $stmt = $pdo->prepare("UPDATE `domain` SET 
+        `description` = :description
+          WHERE `domain` = :domain");
+        $stmt->execute(array(
+          ':description' => $description,
+          ':domain' => $domain
+        ));
+        $_SESSION['return'] = array(
+          'type' => 'success',
+          'msg' => sprintf($lang['success']['domain_modified'], htmlspecialchars($domain))
+        );
+      }
+      catch (PDOException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'MySQL: '.$e
+        );
+        return false;
+      }
     }
+    elseif ($_SESSION['mailcow_cc_role'] == "admin") {
+      $is_now = mailbox_get_domain_details($domain);
+      if (!empty($is_now)) {
+        $active               = (isset($postarray['active'])) ? $postarray['active'] : $is_now['active_int'];
+        $backupmx             = (isset($postarray['backupmx'])) ? $postarray['backupmx'] : $is_now['backupmx_int'];
+        $relay_all_recipients = (isset($postarray['relay_all_recipients'])) ? $postarray['relay_all_recipients'] : $is_now['relay_all_recipients_int'];
+        $aliases              = (!empty($postarray['aliases'])) ? $postarray['aliases'] : $is_now['max_num_aliases_for_domain'];
+        $mailboxes            = (!empty($postarray['mailboxes'])) ? $postarray['mailboxes'] : $is_now['max_num_mboxes_for_domain'];
+        $maxquota             = (!empty($postarray['maxquota'])) ? $postarray['maxquota'] : ($is_now['max_new_mailbox_quota'] / 1048576);
+        $quota                = (!empty($postarray['quota'])) ? $postarray['quota'] : ($is_now['max_quota_for_domain'] / 1048576);
+        $description          = (!empty($postarray['description'])) ? $postarray['description'] : $is_now['description'];
+        ($relay_all_recipients == '1') ? $backupmx = '1' : null;
+      }
+      else {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['domain_invalid'])
+        );
+        return false;
+      }
+      try {
+        // todo: should be using api here
+        $stmt = $pdo->prepare("SELECT 
+            COUNT(*) AS count,
+            MAX(COALESCE(ROUND(`quota`/1048576), 0)) AS `biggest_mailbox`,
+            COALESCE(ROUND(SUM(`quota`)/1048576), 0) AS `quota_all`
+              FROM `mailbox`
+                WHERE `kind` NOT REGEXP 'location|thing|group'
+                  AND domain = :domain");
+        $stmt->execute(array(':domain' => $domain));
+        $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
+        // todo: should be using api here
+        $stmt = $pdo->prepare("SELECT COUNT(*) AS `count` FROM `alias`
+            WHERE domain = :domain
+            AND address NOT IN (
+              SELECT `username` FROM `mailbox`
+            )");
+        $stmt->execute(array(':domain' => $domain));
+        $AliasData = $stmt->fetch(PDO::FETCH_ASSOC);
+      }
+      catch(PDOException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'MySQL: '.$e
+        );
+        return false;
+      }
 
-    if ($maxquota == "0" || empty($maxquota)) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['maxquota_empty'])
-      );
-      return false;
-    }
+      if ($maxquota > $quota) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['mailbox_quota_exceeds_domain_quota'])
+        );
+        return false;
+      }
 
-    if ($MailboxData['maxquota'] > $maxquota) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['max_quota_in_use'], $MailboxData['maxquota'])
-      );
-      return false;
-    }
+      if ($maxquota == "0" || empty($maxquota)) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['maxquota_empty'])
+        );
+        return false;
+      }
 
-    if ($MailboxData['quota'] > $quota) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['domain_quota_m_in_use'], $MailboxData['quota'])
-      );
-      return false;
-    }
+      if ($MailboxData['biggest_mailbox'] > $maxquota) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['max_quota_in_use'], $MailboxData['biggest_mailbox'])
+        );
+        return false;
+      }
 
-    if ($MailboxData['count'] > $mailboxes) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['mailboxes_in_use'], $MailboxData['count'])
-      );
-      return false;
-    }
+      if ($MailboxData['quota_all'] > $quota) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['domain_quota_m_in_use'], $MailboxData['quota_all'])
+        );
+        return false;
+      }
 
-    if ($AliasData['count'] > $aliases) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['aliases_in_use'], $AliasData['count'])
-      );
-      return false;
+      if ($MailboxData['count'] > $mailboxes) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['mailboxes_in_use'], $MailboxData['count'])
+        );
+        return false;
+      }
+
+      if ($AliasData['count'] > $aliases) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['aliases_in_use'], $AliasData['count'])
+        );
+        return false;
+      }
+      try {
+        $stmt = $pdo->prepare("UPDATE `domain` SET 
+        `relay_all_recipients` = :relay_all_recipients,
+        `backupmx` = :backupmx,
+        `active` = :active,
+        `quota` = :quota,
+        `maxquota` = :maxquota,
+        `mailboxes` = :mailboxes,
+        `aliases` = :aliases,
+        `description` = :description
+          WHERE `domain` = :domain");
+        $stmt->execute(array(
+          ':relay_all_recipients' => $relay_all_recipients,
+          ':backupmx' => $backupmx,
+          ':active' => $active,
+          ':quota' => $quota,
+          ':maxquota' => $maxquota,
+          ':mailboxes' => $mailboxes,
+          ':aliases' => $aliases,
+          ':description' => $description,
+          ':domain' => $domain
+        ));
+        $_SESSION['return'] = array(
+          'type' => 'success',
+          'msg' => sprintf($lang['success']['domain_modified'], htmlspecialchars($domain))
+        );
+      }
+      catch (PDOException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'MySQL: '.$e
+        );
+        return false;
+      }
     }
-    try {
-      $stmt = $pdo->prepare("UPDATE `domain` SET 
-      `relay_all_recipients` = :relay_all_recipients,
-      `backupmx` = :backupmx,
-      `active` = :active,
-      `quota` = :quota,
-      `maxquota` = :maxquota,
-      `mailboxes` = :mailboxes,
-      `aliases` = :aliases,
-      `description` = :description
-        WHERE `domain` = :domain");
-      $stmt->execute(array(
-        ':relay_all_recipients' => $relay_all_recipients,
-        ':backupmx' => $backupmx,
-        ':active' => $active,
-        ':quota' => $quota,
-        ':maxquota' => $maxquota,
-        ':mailboxes' => $mailboxes,
-        ':aliases' => $aliases,
-        ':description' => $description,
-        ':domain' => $domain
-      ));
+  }
+}
+function mailbox_edit_mailbox($postarray) {
+	global $lang;
+	global $pdo;
+  if (!is_array($postarray['username'])) {
+    $usernames = array();
+    $usernames[] = $postarray['username'];
+  }
+  else {
+    $usernames = $postarray['username'];
+  }
+  foreach ($usernames as $username) {
+    if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
       $_SESSION['return'] = array(
-        'type' => 'success',
-        'msg' => sprintf($lang['success']['domain_modified'], htmlspecialchars($domain))
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['username_invalid'])
       );
+      return false;
     }
-    catch (PDOException $e) {
+    $is_now = mailbox_get_mailbox_details($username);
+    if (!empty($is_now)) {
+      $active     = (isset($postarray['active'])) ? $postarray['active'] : $is_now['active_int'];
+      $name       = (!empty($postarray['name'])) ? $postarray['name'] : $is_now['name'];
+      $domain     = $is_now['domain'];
+      $quota_m    = (!empty($postarray['quota'])) ? $postarray['quota'] : ($is_now['quota'] / 1048576);
+      $quota_b    = $quota_m * 1048576;
+      $password   = (!empty($postarray['password'])) ? $postarray['password'] : null;
+      $password2  = (!empty($postarray['password2'])) ? $postarray['password2'] : null; 
+    }
+    else {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+    try {
+      $stmt = $pdo->prepare("SELECT `quota`, `maxquota`
+        FROM `domain`
+          WHERE `domain` = :domain");
+      $stmt->execute(array(':domain' => $domain));
+      $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
+    }
+    catch(PDOException $e) {
       $_SESSION['return'] = array(
         'type' => 'danger',
         'msg' => 'MySQL: '.$e
       );
       return false;
     }
-  }
-}
-function mailbox_edit_mailbox($postarray) {
-	global $lang;
-	global $pdo;
-	isset($postarray['active']) ? $active = '1' : $active = '0';
-	if (!filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['username_invalid'])
-		);
-		return false;
-	}
-	$quota_m      = intval($postarray['quota']);
-	$quota_b      = $quota_m*1048576;
-	$username     = $postarray['username'];
-	$name         = $postarray['name'];
-	$password     = $postarray['password'];
-	$password2    = $postarray['password2'];
 
-	try {
-		$stmt = $pdo->prepare("SELECT `domain`
-			FROM `mailbox`
-				WHERE username = :username");
-		$stmt->execute(array(':username' => $username));
-		$MailboxData1 = $stmt->fetch(PDO::FETCH_ASSOC);
-
-		$stmt = $pdo->prepare("SELECT 
-			COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota_m_now`
-				FROM `mailbox`
-					WHERE `username` = :username");
-		$stmt->execute(array(':username' => $username));
-		$MailboxData2 = $stmt->fetch(PDO::FETCH_ASSOC);
+    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 (!is_numeric($quota_m) || $quota_m == "0") {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['quota_not_0_not_numeric'], htmlspecialchars($quota_m))
+      );
+      return false;
+    }
+    if ($quota_m > $DomainData['maxquota']) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['mailbox_quota_exceeded'], $DomainData['maxquota'])
+      );
+      return false;
+    }
+    if (((($is_now['quota_used'] / 1048576) - $quota_m) + $quota_m) > $DomainData['quota']) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['mailbox_quota_left_exceeded'], ($is_now['max_new_quota'] / 1048576))
+      );
+      return false;
+    }
 
-		$stmt = $pdo->prepare("SELECT 
-			COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota_m_in_use`
-				FROM `mailbox`
-					WHERE `domain` = :domain");
-		$stmt->execute(array(':domain' => $MailboxData1['domain']));
-		$MailboxData3 = $stmt->fetch(PDO::FETCH_ASSOC);
-
-		$stmt = $pdo->prepare("SELECT `quota`, `maxquota`
-			FROM `domain`
-				WHERE `domain` = :domain");
-		$stmt->execute(array(':domain' => $MailboxData1['domain']));
-		$DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
-	}
-	catch(PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
+    if (isset($postarray['sender_acl'])) {
+      // Get sender_acl items set by admin
+      $sender_acl_admin = array_merge(
+        mailbox_get_sender_acl_handles($username)['sender_acl_domains']['ro'],
+        mailbox_get_sender_acl_handles($username)['sender_acl_addresses']['ro']
+      );
 
-	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $MailboxData1['domain'])) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-	if (!is_numeric($quota_m) || $quota_m == "0") {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['quota_not_0_not_numeric'], htmlspecialchars($quota_m))
-		);
-		return false;
-	}
-	if ($quota_m > $DomainData['maxquota']) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['mailbox_quota_exceeded'], $DomainData['maxquota'])
-		);
-		return false;
-	}
-	if (($MailboxData3['quota_m_in_use'] - $MailboxData2['quota_m_now'] + $quota_m) > $DomainData['quota']) {
-		$quota_left_m = ($DomainData['quota'] - $MailboxData3['quota_m_in_use'] + $MailboxData2['quota_m_now']);
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['mailbox_quota_left_exceeded'], $quota_left_m)
-		);
-		return false;
-	}
+      // Get sender_acl items from POST array
+      $sender_acl_domain_admin = ($postarray['sender_acl'] == "0") ? array() : $postarray['sender_acl'];
+
+      if (!empty($sender_acl_domain_admin) || !empty($sender_acl_admin)) {
+        // Check items in POST array
+        foreach ($sender_acl_domain_admin as $sender_acl) {
+          if (!filter_var($sender_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name(ltrim($sender_acl, '@'))) {
+              $_SESSION['return'] = array(
+                'type' => 'danger',
+                'msg' => sprintf($lang['danger']['sender_acl_invalid'])
+              );
+              return false;
+          }
+          if (is_valid_domain_name(ltrim($sender_acl, '@'))) {
+            if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], ltrim($sender_acl, '@'))) {
+              $_SESSION['return'] = array(
+                'type' => 'danger',
+                'msg' => sprintf($lang['danger']['sender_acl_invalid'])
+              );
+              return false;
+            }
+          }
+          if (filter_var($sender_acl, FILTER_VALIDATE_EMAIL)) {
+            if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $sender_acl)) {
+              $_SESSION['return'] = array(
+                'type' => 'danger',
+                'msg' => sprintf($lang['danger']['sender_acl_invalid'])
+              );
+              return false;
+            }
+          }
+        }
 
-  // Get sender_acl items set by admin
-  $sender_acl_admin = array_merge(
-    mailbox_get_sender_acl_handles($username)['sender_acl_domains']['ro'],
-    mailbox_get_sender_acl_handles($username)['sender_acl_addresses']['ro']
-  );
+        // Merge both arrays
+        $sender_acl_merged = array_merge($sender_acl_domain_admin, $sender_acl_admin);
 
-  // Get sender_acl items from POST array
-  (isset($postarray['sender_acl'])) ? $sender_acl_domain_admin = $postarray['sender_acl'] : $sender_acl_domain_admin = array();
+        try {
+          $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
+          $stmt->execute(array(
+            ':username' => $username
+          ));
+        }
+        catch (PDOException $e) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => 'MySQL: '.$e
+          );
+          return false;
+        }
 
-	if (!empty($sender_acl_domain_admin) || !empty($sender_acl_admin)) {
-    // Check items in POST array
-		foreach ($sender_acl_domain_admin as $sender_acl) {
-			if (!filter_var($sender_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name(ltrim($sender_acl, '@'))) {
-					$_SESSION['return'] = array(
-						'type' => 'danger',
-						'msg' => sprintf($lang['danger']['sender_acl_invalid'])
-					);
-					return false;
-			}
-      if (is_valid_domain_name(ltrim($sender_acl, '@'))) {
-        if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], ltrim($sender_acl, '@'))) {
-					$_SESSION['return'] = array(
-						'type' => 'danger',
-						'msg' => sprintf($lang['danger']['sender_acl_invalid'])
-					);
-					return false;
+        foreach ($sender_acl_merged as $sender_acl) {
+          $domain = ltrim($sender_acl, '@');
+          if (is_valid_domain_name($domain)) {
+            $sender_acl = '@' . $domain;
+          }
+          try {
+            $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`)
+              VALUES (:sender_acl, :username)");
+            $stmt->execute(array(
+              ':sender_acl' => $sender_acl,
+              ':username' => $username
+            ));
+          }
+          catch (PDOException $e) {
+            $_SESSION['return'] = array(
+              'type' => 'danger',
+              'msg' => 'MySQL: '.$e
+            );
+            return false;
+          }
         }
       }
-			if (filter_var($sender_acl, FILTER_VALIDATE_EMAIL)) {
-        if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $sender_acl)) {
-					$_SESSION['return'] = array(
-						'type' => 'danger',
-						'msg' => sprintf($lang['danger']['sender_acl_invalid'])
-					);
-					return false;
+      else {
+        try {
+          $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
+          $stmt->execute(array(
+            ':username' => $username
+          ));
+        }
+        catch (PDOException $e) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => 'MySQL: '.$e
+          );
+          return false;
         }
       }
     }
-
-    // Merge both arrays
-    $sender_acl_merged = array_merge($sender_acl_domain_admin, $sender_acl_admin);
-
+    if (!empty($password) && !empty($password2)) {
+      if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['password_complexity'])
+        );
+        return false;
+      }
+      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 `alias` SET
+            `active` = :active
+              WHERE `address` = :address");
+        $stmt->execute(array(
+          ':address' => $username,
+          ':active' => $active
+        ));
+        $stmt = $pdo->prepare("UPDATE `mailbox` SET
+            `active` = :active,
+            `password` = :password_hashed,
+            `name`= :name,
+            `quota` = :quota_b
+              WHERE `username` = :username");
+        $stmt->execute(array(
+          ':password_hashed' => $password_hashed,
+          ':active' => $active,
+          ':name' => $name,
+          ':quota_b' => $quota_b,
+          ':username' => $username
+        ));
+      }
+      catch (PDOException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'MySQL: '.$e
+        );
+        return false;
+      }
+    }
     try {
-      $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
+      $stmt = $pdo->prepare("UPDATE `alias` SET
+          `active` = :active
+            WHERE `address` = :address");
+      $stmt->execute(array(
+        ':address' => $username,
+        ':active' => $active
+      ));
+      $stmt = $pdo->prepare("UPDATE `mailbox` SET
+          `active` = :active,
+          `name`= :name,
+          `quota` = :quota_b
+            WHERE `username` = :username");
       $stmt->execute(array(
+        ':active' => $active,
+        ':name' => $name,
+        ':quota_b' => $quota_b,
         ':username' => $username
       ));
     }
@@ -3821,197 +3944,100 @@ function mailbox_edit_mailbox($postarray) {
       );
       return false;
     }
+  }
+  $_SESSION['return'] = array(
+    'type' => 'success',
+    'msg' => sprintf($lang['success']['mailbox_modified'], implode(', ', $usernames))
+  );
+  return true;
+}
+function mailbox_edit_resource($postarray) {
+	global $lang;
+	global $pdo;
 
-		foreach ($sender_acl_merged as $sender_acl) {
-      $domain = ltrim($sender_acl, '@');
-      if (is_valid_domain_name($domain)) {
-        $sender_acl = '@' . $domain;
-      }
-			try {
-				$stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`)
-					VALUES (:sender_acl, :username)");
-				$stmt->execute(array(
-					':sender_acl' => $sender_acl,
-					':username' => $username
-				));
-			}
-			catch (PDOException $e) {
-				$_SESSION['return'] = array(
-					'type' => 'danger',
-					'msg' => 'MySQL: '.$e
-				);
-				return false;
-			}
-		}
-	}
+  if (!is_array($postarray['name'])) {
+    $names = array();
+    $names[] = $postarray['name'];
+  }
   else {
-    try {
-      $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
-      $stmt->execute(array(
-        ':username' => $username
-      ));
+    $names = $postarray['name'];
+  }
+  foreach ($names as $name) {
+    $is_now = mailbox_get_resource_details($name);
+    if (!empty($is_now)) {
+      $active             = (isset($postarray['active'])) ? $postarray['active'] : $is_now['active_int'];
+      $multiple_bookings  = (isset($postarray['multiple_bookings'])) ? $postarray['multiple_bookings'] : $is_now['multiple_bookings_int'];
+      $description        = (!empty($postarray['description'])) ? $postarray['description'] : $is_now['description'];
+      $kind               = (!empty($postarray['kind'])) ? $postarray['kind'] : $is_now['kind'];
     }
-    catch (PDOException $e) {
+    else {
       $_SESSION['return'] = array(
         'type' => 'danger',
-        'msg' => 'MySQL: '.$e
+        'msg' => sprintf($lang['danger']['resource_invalid'])
       );
       return false;
     }
-  }
-	if (!empty($password) && !empty($password2)) {
-    if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
+
+    if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
       $_SESSION['return'] = array(
         'type' => 'danger',
-        'msg' => sprintf($lang['danger']['password_complexity'])
+        'msg' => sprintf($lang['danger']['resource_invalid'])
       );
       return false;
     }
-		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 `alias` SET
-					`active` = :active
-						WHERE `address` = :address");
-			$stmt->execute(array(
-				':address' => $username,
-				':active' => $active
-			));
-			$stmt = $pdo->prepare("UPDATE `mailbox` SET
-					`active` = :active,
-					`password` = :password_hashed,
-					`name`= :name,
-					`quota` = :quota_b
-						WHERE `username` = :username");
-			$stmt->execute(array(
-				':password_hashed' => $password_hashed,
-				':active' => $active,
-				':name' => $name,
-				':quota_b' => $quota_b,
-				':username' => $username
-			));
-			$_SESSION['return'] = array(
-				'type' => 'success',
-				'msg' => sprintf($lang['success']['mailbox_modified'], $username)
-			);
-			return true;
-		}
-		catch (PDOException $e) {
-			$_SESSION['return'] = array(
-				'type' => 'danger',
-				'msg' => 'MySQL: '.$e
-			);
-			return false;
-		}
-	}
-	try {
-		$stmt = $pdo->prepare("UPDATE `alias` SET
-				`active` = :active
-					WHERE `address` = :address");
-		$stmt->execute(array(
-			':address' => $username,
-			':active' => $active
-		));
-		$stmt = $pdo->prepare("UPDATE `mailbox` SET
-				`active` = :active,
-				`name`= :name,
-				`quota` = :quota_b
-					WHERE `username` = :username");
-		$stmt->execute(array(
-			':active' => $active,
-			':name' => $name,
-			':quota_b' => $quota_b,
-			':username' => $username
-		));
-		$_SESSION['return'] = array(
-			'type' => 'success',
-			'msg' => sprintf($lang['success']['mailbox_modified'], $username)
-		);
-		return true;
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-}
-function mailbox_edit_resource($postarray) {
-	global $lang;
-	global $pdo;
-
-	isset($postarray['active']) ? $active = '1' : $active = '0';
-	isset($postarray['multiple_bookings']) ? $multiple_bookings = '1' : $multiple_bookings = '0';
-	$name               = $postarray['name'];
-	$kind               = $postarray['kind'];
-	$description        = $postarray['description'];
-
-	if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['resource_invalid'])
-		);
-		return false;
-	}
 
-	if (empty($description)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['description_invalid'])
-		);
-		return false;
-  }
+    if (empty($description)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['description_invalid'])
+      );
+      return false;
+    }
 
-	if ($kind != 'location' && $kind != 'group' && $kind != 'thing') {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['resource_invalid'])
-		);
-		return false;
-	}
+    if ($kind != 'location' && $kind != 'group' && $kind != 'thing') {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['resource_invalid'])
+      );
+      return false;
+    }
 
-  if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) {
-    $_SESSION['return'] = array(
-      'type' => 'danger',
-      'msg' => sprintf($lang['danger']['access_denied'])
-    );
-    return false;
-  }
+    if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
 
-	try {
-		$stmt = $pdo->prepare("UPDATE `mailbox` SET
-				`active` = :active,
-				`name`= :description,
-				`kind`= :kind,
-				`multiple_bookings`= :multiple_bookings
-          WHERE `username` = :name");
-		$stmt->execute(array(
-			':active' => $active,
-			':description' => $description,
-			':multiple_bookings' => $multiple_bookings,
-			':kind' => $kind,
-			':name' => $name
-		));
-		$_SESSION['return'] = array(
-			'type' => 'success',
-			'msg' => sprintf($lang['success']['resource_modified'], $name)
-		);
-		return true;
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
+    try {
+      $stmt = $pdo->prepare("UPDATE `mailbox` SET
+          `active` = :active,
+          `name`= :description,
+          `kind`= :kind,
+          `multiple_bookings`= :multiple_bookings
+            WHERE `username` = :name");
+      $stmt->execute(array(
+        ':active' => $active,
+        ':description' => $description,
+        ':multiple_bookings' => $multiple_bookings,
+        ':kind' => $kind,
+        ':name' => $name
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
 	}
+  $_SESSION['return'] = array(
+    'type' => 'success',
+    'msg' => sprintf($lang['success']['resource_modified'], implode(', ', $names))
+  );
+  return true;
 }
 function mailbox_get_mailboxes($domain = null) {
 	global $lang;
@@ -4564,8 +4590,15 @@ function mailbox_get_resource_details($resource) {
 }
 function mailbox_delete_domain($postarray) {
 	global $lang;
+	global $redis;
 	global $pdo;
-	$domain = $postarray['domain'];
+  if (!is_array($postarray['domain'])) {
+    $domains = array();
+    $domains[] = $postarray['domain'];
+  }
+  else {
+    $domains = $postarray['domain'];
+  }
 	if ($_SESSION['mailcow_cc_role'] != "admin") {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
@@ -4573,90 +4606,92 @@ function mailbox_delete_domain($postarray) {
 		);
 		return false;
 	}
-	if (!is_valid_domain_name($domain)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['domain_invalid'])
-		);
-		return false;
-	}
-	$domain	= idn_to_ascii(strtolower(trim($domain)));
+  foreach ($domains as $domain) {
+    if (!is_valid_domain_name($domain)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['domain_invalid'])
+      );
+      return false;
+    }
+    $domain	= idn_to_ascii(strtolower(trim($domain)));
 
-	try {
-		$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
-			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 || !empty($num_results)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['domain_not_empty'])
-		);
-		return false;
-	}
+    try {
+      $stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
+        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 || !empty($num_results)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['domain_not_empty'])
+      );
+      return false;
+    }
 
-	try {
-		$stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain");
-		$stmt->execute(array(
-			':domain' => $domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `domain` = :domain");
-		$stmt->execute(array(
-			':domain' => $domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :domain");
-		$stmt->execute(array(
-			':domain' => $domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `target_domain` = :domain");
-		$stmt->execute(array(
-			':domain' => $domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `domain` = :domain");
-		$stmt->execute(array(
-			':domain' => $domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` LIKE :domain");
-		$stmt->execute(array(
-			':domain' => '%@'.$domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain");
-		$stmt->execute(array(
-			':domain' => '%@'.$domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain");
-		$stmt->execute(array(
-			':domain' => '%@'.$domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain");
-		$stmt->execute(array(
-			':domain' => '%@'.$domain,
-		));
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-  try {
-    $redis->hDel('DOMAIN_MAP', $domain);
-  }
-  catch (RedisException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'Redis: '.$e
-		);
-		return false;
+    try {
+      $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain");
+      $stmt->execute(array(
+        ':domain' => $domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `domain` = :domain");
+      $stmt->execute(array(
+        ':domain' => $domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :domain");
+      $stmt->execute(array(
+        ':domain' => $domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `target_domain` = :domain");
+      $stmt->execute(array(
+        ':domain' => $domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `domain` = :domain");
+      $stmt->execute(array(
+        ':domain' => $domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` LIKE :domain");
+      $stmt->execute(array(
+        ':domain' => '%@'.$domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain");
+      $stmt->execute(array(
+        ':domain' => '%@'.$domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain");
+      $stmt->execute(array(
+        ':domain' => '%@'.$domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain");
+      $stmt->execute(array(
+        ':domain' => '%@'.$domain,
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
+    try {
+      $redis->hDel('DOMAIN_MAP', $domain);
+    }
+    catch (RedisException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'Redis: '.$e
+      );
+      return false;
+    }
   }
 	$_SESSION['return'] = array(
 		'type' => 'success',
@@ -4669,13 +4704,13 @@ function mailbox_delete_alias($postarray) {
 	global $lang;
 	global $pdo;
   if (!is_array($postarray['address'])) {
-    $address_array = array();
-    $address_array[] = $postarray['address'];
+    $addresses = array();
+    $addresses[] = $postarray['address'];
   }
   else {
-    $address_array = $postarray['address'];
+    $addresses = $postarray['address'];
   }
-  foreach ($address_array as $address) {
+  foreach ($addresses as $address) {
     $local_part		= strstr($address, '@', true);
     $domain = mailbox_get_alias_details($address)['domain'];
     try {
@@ -4700,10 +4735,188 @@ function mailbox_delete_alias($postarray) {
       return false;
     }
     try {
-      $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `address` = :address AND `address` NOT IN (SELECT `username` FROM `mailbox`)");
+      $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `address` = :address AND `address` NOT IN (SELECT `username` FROM `mailbox`)");
+      $stmt->execute(array(
+        ':address' => $address
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
+  }
+	$_SESSION['return'] = array(
+		'type' => 'success',
+		'msg' => sprintf($lang['success']['alias_removed'], htmlspecialchars(implode(', ', $addresses)))
+	);
+
+}
+function mailbox_delete_alias_domain($postarray) {
+	global $lang;
+	global $pdo;
+  if (!is_array($postarray['alias_domain'])) {
+    $alias_domains = array();
+    $alias_domains[] = $postarray['alias_domain'];
+  }
+  else {
+    $alias_domains = $postarray['alias_domain'];
+  }
+  foreach ($alias_domains as $alias_domain) {
+    if (!is_valid_domain_name($alias_domain)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['domain_invalid'])
+      );
+      return false;
+    }
+    try {
+      $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
+        WHERE `alias_domain`= :alias_domain");
+      $stmt->execute(array(':alias_domain' => $alias_domain));
+      $DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
+    }
+    catch(PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
+    if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+    try {
+      $stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `alias_domain` = :alias_domain");
+      $stmt->execute(array(
+        ':alias_domain' => $alias_domain,
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :alias_domain");
+      $stmt->execute(array(
+        ':alias_domain' => $alias_domain,
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
+	}
+	$_SESSION['return'] = array(
+		'type' => 'success',
+		'msg' => sprintf($lang['success']['alias_domain_removed'], htmlspecialchars(implode(', ', $alias_domains)))
+	);
+}
+function mailbox_delete_mailbox($postarray) {
+	global $lang;
+	global $pdo;
+  if (!is_array($postarray['username'])) {
+    $usernames = array();
+    $usernames[] = $postarray['username'];
+  }
+  else {
+    $usernames = $postarray['username'];
+  }
+  foreach ($usernames as $username) {
+    if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+
+    if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+
+    try {
+      $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
       $stmt->execute(array(
-        ':address' => $address
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `user2` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $username . "/%' OR `c_uid` = :username");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
+      $stmt->execute(array(
+        ':username' => $username
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
+      $stmt->execute(array(
+        ':username' => $username
       ));
+      $stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
+          WHERE `goto` REGEXP :username");
+      $stmt->execute(array(':username' => '(^|,)'.$username.'($|,)'));
+      $GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC);
+      foreach ($GotoData as $gotos) {
+        $goto_exploded = explode(',', $gotos['goto']);
+        if (($key = array_search($username, $goto_exploded)) !== false) {
+          unset($goto_exploded[$key]);
+        }
+        $gotos_rebuild = implode(',', $goto_exploded);
+        $stmt = $pdo->prepare("UPDATE `alias` SET
+          `goto` = :goto
+            WHERE `address` = :address");
+        $stmt->execute(array(
+          ':goto' => $gotos_rebuild,
+          ':address' => $gotos['address']
+        ));
+      }
     }
     catch (PDOException $e) {
       $_SESSION['return'] = array(
@@ -4712,175 +4925,10 @@ function mailbox_delete_alias($postarray) {
       );
       return false;
     }
-  }
-	$_SESSION['return'] = array(
-		'type' => 'success',
-		'msg' => sprintf($lang['success']['alias_removed'], htmlspecialchars(implode(', ', $address_array)))
-	);
-
-}
-function mailbox_delete_alias_domain($postarray) {
-	global $lang;
-	global $pdo;
-  $alias_domain = $postarray['alias_domain'];
-	if (!is_valid_domain_name($postarray['alias_domain'])) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['domain_invalid'])
-		);
-		return false;
-	}
-	try {
-		$stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain`
-			WHERE `alias_domain`= :alias_domain");
-		$stmt->execute(array(':alias_domain' => $alias_domain));
-		$DomainData = $stmt->fetch(PDO::FETCH_ASSOC);
-	}
-	catch(PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-
-	if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $DomainData['target_domain'])) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-
-	try {
-		$stmt = $pdo->prepare("DELETE FROM `alias_domain` WHERE `alias_domain` = :alias_domain");
-		$stmt->execute(array(
-			':alias_domain' => $alias_domain,
-		));
-		$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `domain` = :alias_domain");
-		$stmt->execute(array(
-			':alias_domain' => $alias_domain,
-		));
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
-	}
-	$_SESSION['return'] = array(
-		'type' => 'success',
-		'msg' => sprintf($lang['success']['alias_domain_removed'], htmlspecialchars($alias_domain))
-	);
-}
-function mailbox_delete_mailbox($postarray) {
-	global $lang;
-	global $pdo;
-	$username	= $postarray['username'];
-
-	if (!filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-
-	if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-
-	try {
-		$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-		$stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-		$stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-		$stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-		$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-		$stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `user2` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-		$stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username");
-		$stmt->execute(array(
-			':username' => $username
-		));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $username . "/%' OR `c_uid` = :username");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
-    $stmt->execute(array(
-      ':username' => $username
-    ));
-		$stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
-				WHERE `goto` REGEXP :username");
-		$stmt->execute(array(':username' => '(^|,)'.$username.'($|,)'));
-		$GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC);
-		foreach ($GotoData as $gotos) {
-			$goto_exploded = explode(',', $gotos['goto']);
-			if (($key = array_search($username, $goto_exploded)) !== false) {
-				unset($goto_exploded[$key]);
-			}
-			$gotos_rebuild = implode(',', $goto_exploded);
-			$stmt = $pdo->prepare("UPDATE `alias` SET
-        `goto` = :goto
-          WHERE `address` = :address");
-			$stmt->execute(array(
-				':goto' => $gotos_rebuild,
-				':address' => $gotos['address']
-			));
-		}
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
 	}
 	$_SESSION['return'] = array(
 		'type' => 'success',
-		'msg' => sprintf($lang['success']['mailbox_removed'], htmlspecialchars($username))
+		'msg' => sprintf($lang['success']['mailbox_removed'], htmlspecialchars(implode(', ', $usernames)))
 	);
 }
 function mailbox_reset_eas($username) {
@@ -4926,67 +4974,73 @@ function mailbox_reset_eas($username) {
 function mailbox_delete_resource($postarray) {
 	global $lang;
 	global $pdo;
-	$name	= $postarray['name'];
-	if (!filter_var($postarray['name'], FILTER_VALIDATE_EMAIL)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-
-	if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => sprintf($lang['danger']['access_denied'])
-		);
-		return false;
-	}
-
-	try {
-		$stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
-		$stmt->execute(array(
-			':username' => $name
-		));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $name . "/%' OR `c_uid` = :username");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-    $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
-    $stmt->execute(array(
-      ':username' => $name
-    ));
-	}
-	catch (PDOException $e) {
-		$_SESSION['return'] = array(
-			'type' => 'danger',
-			'msg' => 'MySQL: '.$e
-		);
-		return false;
+  if (!is_array($postarray['name'])) {
+    $names = array();
+    $names[] = $postarray['name'];
+  }
+  else {
+    $names = $postarray['name'];
+  }
+  foreach ($names as $name) {
+    if (!filter_var($name, FILTER_VALIDATE_EMAIL)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+    if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $name)) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => sprintf($lang['danger']['access_denied'])
+      );
+      return false;
+    }
+    try {
+      $stmt = $pdo->prepare("DELETE FROM `mailbox` WHERE `username` = :username");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_user_profile` WHERE `c_uid` = :username");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_cache_folder` WHERE `c_uid` = :username");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_acl` WHERE `c_object` LIKE '%/" . $name . "/%' OR `c_uid` = :username");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_store` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_quick_contact` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_quick_appointment` WHERE `c_folder_id` IN (SELECT `c_folder_id` FROM `sogo_folder_info` WHERE `c_path2` = :username)");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+      $stmt = $pdo->prepare("DELETE FROM `sogo_folder_info` WHERE `c_path2` = :username");
+      $stmt->execute(array(
+        ':username' => $name
+      ));
+    }
+    catch (PDOException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'MySQL: '.$e
+      );
+      return false;
+    }
 	}
 	$_SESSION['return'] = array(
 		'type' => 'success',
-		'msg' => sprintf($lang['success']['resource_removed'], htmlspecialchars($name))
+		'msg' => sprintf($lang['success']['resource_removed'], htmlspecialchars(implode(', ', $names)))
 	);
 }
 function mailbox_get_sender_acl_handles($mailbox) {
@@ -5178,7 +5232,6 @@ function add_forwarding_host($postarray) {
 	else {
 		$hosts = get_outgoing_hosts_best_guess($host);
 	}
-  print_r($hosts);
 	if (empty($hosts)) {
 		$_SESSION['return'] = array(
 			'type' => 'danger',
diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php
index 67c6c34e..4c8a10cd 100644
--- a/data/web/inc/vars.inc.php
+++ b/data/web/inc/vars.inc.php
@@ -1,6 +1,7 @@
 <?php
-error_reporting(E_ERROR);
-//error_reporting(E_ALL);
+//error_reporting(E_ERROR);
+error_reporting(E_ALL);
+header('X-Powered-By: mailcow');
 
 /*
 PLEASE USE THE FILE "vars.local.inc.php" TO OVERWRITE SETTINGS AND MAKE THEM PERSISTENT!
diff --git a/data/web/js/admin.js b/data/web/js/admin.js
index 4ad8246b..e76feef7 100644
--- a/data/web/js/admin.js
+++ b/data/web/js/admin.js
@@ -1,17 +1,16 @@
 $(document).ready(function() {
-  
-  // Collect values of input fields with name multi_select with same data-form-id to js array multi_data[data-form-id-of-checkbox]
+  // Collect values of input fields with name multi_select with same data-id to js array multi_data[data-id]
   var multi_data = [];
   $(document).on('change', 'input[name=multi_select]:checkbox', function() {
-    if ($(this).is(':checked') && $(this).attr('data-form-id')) {
-      var id = $(this).data('form-id');
+    if ($(this).is(':checked') && $(this).data('id')) {
+      var id = $(this).data('id');
       if (typeof multi_data[id] == "undefined") {
         multi_data[id] = [];
       }
       multi_data[id].push($(this).val());
     }
     else {
-      var id = $(this).data('form-id');
+      var id = $(this).data('id');
       multi_data[id].splice($.inArray($(this).val(), multi_data[id]),1);
     }
   });
@@ -24,104 +23,21 @@ $(document).ready(function() {
       checkbox.trigger('click');
     }
   });
-  // Select or deselect all checkboxes with same data-form-id
+  // Select or deselect all checkboxes with same data-id
   $(document).on('click', '#toggle_multi_select_all', function(e) {
     e.preventDefault();
-    var all_checkboxes = $("input[data-form-id=" + $(this).attr("data-form-id") + "]");
+    id = $(this).data("id");
+    multi_data[id] = [];
+    var all_checkboxes = $("input[data-id=" + id + "]:enabled");
     all_checkboxes.prop("checked", !all_checkboxes.prop("checked")).change();
   });
-
-  // Draw domain admin table
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/domain-admin/all',
-    jsonp: false,
-    error: function () {
-      console.log('Cannot draw domain admin table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-					'</div>';
-      });
-      $('#domainadminstable').footable({
-        "columns": [
-          {"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
-          {"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
-          {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"}},
-          {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
-        ],
-        "rows": data,
-        "empty": lang.empty,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
-        },
-        "filtering": {
-          "enabled": true,
-          "position": "left",
-          "placeholder": lang.filter_table
-        },
-        "sorting": {
-          "enabled": true
-        }
-      });
-    }
-  });
-  
-  // Draw fwd hosts table
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/fwdhost/all',
-    jsonp: false,
-    error: function () {
-      console.log('Cannot draw forwarding hosts table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.action = '<div class="btn-group">' +
-          '<a href="/delete.php?forwardinghost=' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-					'</div>';
-        if (item.keep_spam == "yes") {
-          item.keep_spam = lang.no;
-        }
-        else {
-          item.keep_spam = lang.yes;
-        }
-        item.chkbox = '<input type="checkbox" data-form-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
-      });
-      $('#forwardinghoststable').footable({
-        "columns": [
-          {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
-          {"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},
-          {"name":"source","title":lang.source,"breakpoints":"xs sm"},
-          {"name":"keep_spam","title":lang.spamfilter, "type": "text","style":{"maxWidth":"80px","width":"80px"}},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
-        ],
-        "rows": data,
-        "empty": lang.empty,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
-        },
-        "sorting": {
-          "enabled": true
-        }
-      });
-    }
-  });
-  
-  $(document).on('click', '#delete_fwdhosts', function(e) {
+  // General API edit function
+  $(document).on('click', '#delete_selected', function(e) {
     e.preventDefault();
-    var id = $(this).closest("form").attr('data-id');
-    if (typeof multi_data[id] == "undefined") return;
+    var id = $(this).data('id');
+    if (typeof multi_data[id] == "undefined" || multi_data[id] == "") return;
     data_array = multi_data[id];
-    if (Object.keys(data_array).length !== 0) {
+    api_url = $(this).data('api-url');
       $(document).on('show.bs.modal','#ConfirmDeleteModal', function () {
         $("#ItemsToDelete").empty();
         for (var i in data_array) {
@@ -136,64 +52,46 @@ $(document).ready(function() {
         $.ajax({
           type: "POST",
           dataType: "json",
-          data: { "forwardinghost": JSON.stringify(data_array) },
-          url: '/api/v1/delete/fwdhost',
+          data: { "items": JSON.stringify(data_array) },
+          url: '/api/v1/' + api_url,
           jsonp: false,
           complete: function (data) {
-            window.location.href = window.location.href;
+            location.assign(window.location);
           }
         });
       })
       .one('click', '#isCanceled', function(e) {
         $('#ConfirmDeleteModal').modal('hide');
       });;
-    }
   });
 
-  $(document).on('click', '#delete_dkim_key', function(e) {
+});
+jQuery(function($){
+  function unix_time_format(tm) {
+    var date = new Date(tm ? tm * 1000 : 0);
+    return date.toLocaleString();
+  }
+  $("#refresh_postfix_log").on('click', function(e) {
     e.preventDefault();
-    var dkim_domain = $(this).data('dkim-domain');
-    var dkim_selector = $(this).data('dkim-selector');
-      $(document).on('show.bs.modal','#ConfirmDeleteModal', function () {
-        $("#ItemsToDelete").empty();
-        $("#ItemsToDelete").append("<li>" + dkim_domain + ", " + dkim_selector + "</li>");
-      })
-      $('#ConfirmDeleteModal').modal({
-        backdrop: 'static',
-        keyboard: false
-      })
-      .one('click', '#IsConfirmed', function(e) {
-        $.ajax({
-          type: "POST",
-          dataType: "json",
-          data: { "domains": JSON.stringify(dkim_domain) },
-          url: '/api/v1/delete/dkim',
-          jsonp: false,
-          complete: function (data) {
-            mailcow_alert_box("warn", "asd");
-          }
-        });
-      })
-      .one('click', '#isCanceled', function(e) {
-        $('#ConfirmDeleteModal').modal('hide');
-      });;
+    draw_postfix_logs();
   });
-
   $("#refresh_dovecot_log").on('click', function(e) {
-      function unix_time_format(tm) {
-        var date = new Date(tm ? tm * 1000 : 0);
-        return date.toLocaleString();
-      }
-      e.preventDefault();
-      if (typeof ft_dovecot_logs != 'undefined') {
-        ft_dovecot_logs.destroy();
-      }
-      $.ajax({
+    e.preventDefault();
+    draw_dovecot_logs();
+  });
+  function draw_postfix_logs() {
+    ft_postfix_logs = FooTable.init('#postfix_log', {
+      "columns": [
+        {"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
+        {"name":"priority","title":lang.priority,"style":{"width":"80px"}},
+        {"name":"message","title":lang.message},
+      ],
+      "rows": $.ajax({
         dataType: 'json',
-        url: '/api/v1/get/logs/dovecot/1000',
+        url: '/api/v1/get/logs/postfix/1000',
         jsonp: false,
         error: function () {
-          console.log('Cannot draw dovecot log table');
+          console.log('Cannot draw postfix log table');
         },
         success: function (data) {
           $.each(data, function (i, item) {
@@ -210,46 +108,37 @@ $(document).ready(function() {
               item.priority = '<span class="label label-info">' + item.priority + '</span>';
             }
           });
-          ft_dovecot_logs = FooTable.init("#dovecot_log", {
-            "columns": [
-              {"name":"time","formatter":function unix_time_format(tm) {var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
-              {"name":"priority","title":lang.priority,"style":{"width":"80px"}},
-              {"name":"message","title":lang.message},
-            ],
-            "rows": data,
-            "empty": lang.empty,
-            "paging": {
-              "enabled": true,
-              "limit": 5,
-              "size": pagination_size
-            },
-            "filtering": {
-              "enabled": true,
-              "position": "left",
-              "placeholder": lang.filter_table
-            },
-            "sorting": {
-              "enabled": true
-            }
-          });
         }
-      });
-  });
-  $("#refresh_postfix_log").on('click', function(e) {
-      function unix_time_format(tm) {
-        var date = new Date(tm ? tm * 1000 : 0);
-        return date.toLocaleString();
+      }),
+      "empty": lang.empty,
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
       }
-      e.preventDefault();
-      if (typeof ft_postfix_logs != 'undefined') {
-        ft_postfix_logs.destroy();
-      }
-      $.ajax({
+    });
+  }
+  function draw_dovecot_logs() {
+    ft_postfix_logs = FooTable.init('#dovecot_log', {
+      "columns": [
+        {"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
+        {"name":"priority","title":lang.priority,"style":{"width":"80px"}},
+        {"name":"message","title":lang.message},
+      ],
+      "rows": $.ajax({
         dataType: 'json',
-        url: '/api/v1/get/logs/postfix/1000',
+        url: '/api/v1/get/logs/dovecot/1000',
         jsonp: false,
         error: function () {
-          console.log('Cannot draw postfix log table');
+          console.log('Cannot draw dovecot log table');
         },
         success: function (data) {
           $.each(data, function (i, item) {
@@ -266,31 +155,111 @@ $(document).ready(function() {
               item.priority = '<span class="label label-info">' + item.priority + '</span>';
             }
           });
-          ft_postfix_logs = FooTable.init("#postfix_log", {
-            "columns": [
-              {"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
-              {"name":"priority","title":lang.priority,"style":{"width":"80px"}},
-              {"name":"message","title":lang.message},
-            ],
-            "rows": data,
-            "empty": lang.empty,
-            "paging": {
-              "enabled": true,
-              "limit": 5,
-              "size": pagination_size
-            },
-            "filtering": {
-              "enabled": true,
-              "position": "left",
-              "placeholder": lang.filter_table
-            },
-            "sorting": {
-              "enabled": true
+        }
+      }),
+      "empty": lang.empty,
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
+  function draw_domain_admins() {
+    ft_domainadmins = FooTable.init('#domainadminstable', {
+      "columns": [
+        {"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
+        {"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
+        {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"}},
+        {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
+        {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
+      ],
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/domain-admin/all',
+        jsonp: false,
+        error: function () {
+          console.log('Cannot draw domain admin table');
+        },
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.action = '<div class="btn-group">' +
+              '<a href="/edit.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+              '<a href="/delete.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+              '</div>';
+          });
+        }
+      }),
+      "empty": lang.empty,
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
+
+  function draw_fwd_hosts() {
+    ft_domainadmins = FooTable.init('#forwardinghoststable', {
+      "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
+        {"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},
+        {"name":"source","title":lang.source,"breakpoints":"xs sm"},
+        {"name":"keep_spam","title":lang.spamfilter, "type": "text","style":{"maxWidth":"80px","width":"80px"}},
+        {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
+      ],
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/fwdhost/all',
+        jsonp: false,
+        error: function () {
+          console.log('Cannot draw forwarding hosts table');
+        },
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.action = '<div class="btn-group">' +
+              '<a href="/delete.php?forwardinghost=' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+              '</div>';
+            if (item.keep_spam == "yes") {
+              item.keep_spam = lang.no;
             }
+            else {
+              item.keep_spam = lang.yes;
+            }
+            item.chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
           });
         }
-      });
-  });
-  $("#refresh_dovecot_log").trigger('click');
-  $("#refresh_postfix_log").trigger('click');
+      }),
+      "empty": lang.empty,
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
+
+  draw_postfix_logs();
+  draw_dovecot_logs();
+  draw_domain_admins();
+  draw_fwd_hosts();
 });
\ No newline at end of file
diff --git a/data/web/js/mailbox.js b/data/web/js/mailbox.js
index 39f2d976..70435ca1 100644
--- a/data/web/js/mailbox.js
+++ b/data/web/js/mailbox.js
@@ -1,5 +1,98 @@
 $(document).ready(function() {
-	$('[data-toggle="tooltip"]').tooltip();
+  // Collect values of input fields with name multi_select with same data-id to js array multi_data[data-id]
+  var multi_data = [];
+  $(document).on('change', 'input[name=multi_select]:checkbox', function() {
+    if ($(this).is(':checked') && $(this).data('id')) {
+      var id = $(this).data('id');
+      if (typeof multi_data[id] == "undefined") {
+        multi_data[id] = [];
+      }
+      multi_data[id].push($(this).val());
+    }
+    else {
+      var id = $(this).data('id');
+      multi_data[id].splice($.inArray($(this).val(), multi_data[id]),1);
+    }
+  });
+  // Select checkbox by click on parent tr
+  $(document).on('click', 'tr', function(e) {
+    if (e.target.type == "checkbox") {
+      e.stopPropagation();
+    } else {
+      var checkbox = $(this).find(':checkbox');
+      checkbox.trigger('click');
+    }
+  });
+  // Select or deselect all checkboxes with same data-id
+  $(document).on('click', '#toggle_multi_select_all', function(e) {
+    e.preventDefault();
+    id = $(this).data("id");
+    multi_data[id] = [];
+    var all_checkboxes = $("input[data-id=" + id + "]:enabled");
+    all_checkboxes.prop("checked", !all_checkboxes.prop("checked")).change();
+  });
+  // General API edit actions
+  $(document).on('click', '#edit_selected', function(e) {
+    e.preventDefault();
+    var id = $(this).data('id');
+    if (typeof multi_data[id] == "undefined") return;
+    data_array = multi_data[id];
+    api_url = $(this).data('api-url');
+    api_attr = $(this).data('api-attr');
+    if (Object.keys(data_array).length !== 0) {
+      $.ajax({
+        type: "POST",
+        dataType: "json",
+        data: { "items": JSON.stringify(data_array), "attr": JSON.stringify(api_attr) },
+        url: '/api/v1/' + api_url,
+        jsonp: false,
+        complete: function (data) {
+          // var reponse = (JSON.parse(data.responseText));
+          // alert(reponse.type);
+          // alert(reponse.msg);
+          location.assign(window.location);
+        }
+      });
+    }
+  });
+  // General API delete actions
+  $(document).on('click', '#delete_selected', function(e) {
+    e.preventDefault();
+    var id = $(this).data('id');
+    if (typeof multi_data[id] == "undefined" || multi_data[id] == "") return;
+    data_array = multi_data[id];
+    api_url = $(this).data('api-url');
+      $(document).on('show.bs.modal','#ConfirmDeleteModal', function () {
+        $("#ItemsToDelete").empty();
+        for (var i in data_array) {
+          $("#ItemsToDelete").append("<li>" + data_array[i] + "</li>");
+        }
+      })
+      $('#ConfirmDeleteModal').modal({
+        backdrop: 'static',
+        keyboard: false
+      })
+      .one('click', '#IsConfirmed', function(e) {
+        $.ajax({
+          type: "POST",
+          dataType: "json",
+          data: { "items": JSON.stringify(data_array) },
+          url: '/api/v1/' + api_url,
+          jsonp: false,
+          complete: function (data) {
+            location.assign(window.location);
+          }
+        });
+      })
+      .one('click', '#isCanceled', function(e) {
+        $('#ConfirmDeleteModal').modal('hide');
+      });;
+  });
+
+});
+
+jQuery(function($){
+  // Calculation human readable file sizes
   function humanFileSize(bytes) {
     if(Math.abs(bytes) < 1024) {
         return bytes + ' B';
@@ -12,358 +105,285 @@ $(document).ready(function() {
     } while(Math.abs(bytes) >= 1024 && u < units.length - 1);
     return bytes.toFixed(1)+' '+units[u];
   }
-
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/domain/all',
-    jsonp: false,
-    error: function () {
-      alert('Cannot draw domain table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.aliases = item.aliases_in_domain + " / " + item.max_num_aliases_for_domain;
-        item.mailboxes = item.mboxes_in_domain + " / " + item.max_num_mboxes_for_domain;
-        item.quota = item.quota_used_in_domain + "/" + item.max_quota_for_domain;
-        item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
-        if (role == "admin") {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?domain=' + encodeURI(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?domain=' + encodeURI(item.domain_name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-					'</div>';
-        }
-        else {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?domain=' + encodeURI(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-					'</div>';
-        }
-      });
-      $('#domain_table').footable({
-        "columns": [
-          {"sorted": true,"name":"domain_name","title":lang.domain,"style":{"width":"250px"}},
-          {"name":"aliases","title":lang.aliases,"breakpoints":"xs sm"},
-          {"name":"mailboxes","title":lang.mailboxes},
-          {"name":"quota","style":{"whiteSpace":"nowrap"},"title":lang.domain_quota,"formatter": function(value){
-            res = value.split("/");
-            return humanFileSize(res[0]) + " / " + humanFileSize(res[1]);
-          },
-          "sortValue": function(value){
-            res = value.split("/");
-            return res[0];
-          },
-          },
-          {"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm"},
-          {"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm"},
-          {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
-        ],
-        "rows": data,
-        "empty": lang.empty,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
+  function unix_time_format(tm) {
+    var date = new Date(tm ? tm * 1000 : 0);
+    return date.toLocaleString();
+  }
+  function draw_domain_table() {
+    ft_domain_table = FooTable.init('#domain_table', {
+      "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
+        {"sorted": true,"name":"domain_name","title":lang.domain,"style":{"width":"250px"}},
+        {"name":"aliases","title":lang.aliases,"breakpoints":"xs sm"},
+        {"name":"mailboxes","title":lang.mailboxes},
+        {"name":"quota","style":{"whiteSpace":"nowrap"},"title":lang.domain_quota,"formatter": function(value){
+          res = value.split("/");
+          return humanFileSize(res[0]) + " / " + humanFileSize(res[1]);
         },
-        "filtering": {
-          "enabled": true,
-          "position": "left",
-          "placeholder": lang.filter_table
+        "sortValue": function(value){
+          res = value.split("/");
+          return res[0];
         },
-        "sorting": {
-          "enabled": true
-        }
-      });
-    }
-  });
-
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/mailbox/all',
-    jsonp: false,
-    error: function () {
-      alert('Cannot draw mailbox table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.quota = item.quota_used + "/" + item.quota;
-        item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
-        if (role == "admin") {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-          '<a href="/index.php?duallogin=' + encodeURI(item.username) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
-					'</div>';
-        }
-        else {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-					'</div>';
-        }
-        item.in_use = '<div class="progress">' +
-				  '<div class="progress-bar progress-bar-' + item.percent_class + ' role="progressbar" aria-valuenow="' + item.percent_in_use + '" aria-valuemin="0" aria-valuemax="100" ' +
-          'style="min-width:2em;width:' + item.percent_in_use + '%">' + item.percent_in_use + '%' + '</div></div>';
-
-      });
-      $('#mailbox_table').footable({
-        "columns": [
-          {"sorted": true,"name":"username","style":{"word-break":"break-all","min-width":"120px"},"title":lang.username},
-          {"name":"name","title":lang.fname,"style":{"word-break":"break-all","min-width":"120px"},"breakpoints":"xs sm"},
-          {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
-          {"name":"quota","style":{"whiteSpace":"nowrap"},"title":lang.domain_quota,"formatter": function(value){
-            res = value.split("/");
-            return humanFileSize(res[0]) + " / " + humanFileSize(res[1]);
-          },
-          "sortValue": function(value){
-            res = value.split("/");
-            return res[0];
-          },
-          },
-          {"name":"spam_aliases","filterable": false,"title":lang.spam_aliases,"breakpoints":"xs sm md"},
-          {"name":"in_use","filterable": false,"type":"html","title":lang.in_use},
-          {"name":"messages","filterable": false,"title":lang.msg_num,"breakpoints":"xs sm md"},
-          {"name":"active","filterable": false,"title":lang.active},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
-        ],
-        "empty": lang.empty,
-        "rows": data,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
         },
-        "filtering": {
-          "enabled": true,
-          "position": "left",
-          "placeholder": lang.filter_table
+        {"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm"},
+        {"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm"},
+        {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
+      ],
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/domain/all',
+        jsonp: false,
+        error: function () {
+          alert('Cannot draw domain table');
         },
-        "sorting": {
-          "enabled": true
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.aliases = item.aliases_in_domain + " / " + item.max_num_aliases_for_domain;
+            item.mailboxes = item.mboxes_in_domain + " / " + item.max_num_mboxes_for_domain;
+            item.quota = item.quota_used_in_domain + "/" + item.max_quota_for_domain;
+            item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
+            item.chkbox = '<input type="checkbox" data-id="domain" name="multi_select" value="' + item.domain_name + '" />';
+            if (role == "admin") {
+              item.action = '<div class="btn-group">' +
+                '<a href="/edit.php?domain=' + encodeURI(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+                '<a href="/delete.php?domain=' + encodeURI(item.domain_name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+                '</div>';
+            }
+            else {
+              item.action = '<div class="btn-group">' +
+                '<a href="/edit.php?domain=' + encodeURI(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+                '</div>';
+            }
+          });
         }
-      });
-    }
-  });
-
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/resource/all',
-    jsonp: false,
-    error: function () {
-      alert('Cannot draw resource table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?resource=' + encodeURI(item.name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?resource=' + encodeURI(item.name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-					'</div>';
-      });
-      $('#resources_table').footable({
-        "columns": [
-          {"sorted": true,"name":"description","title":lang.description,"style":{"width":"250px"}},
-          {"name":"kind","title":lang.kind},
-          {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
-          {"name":"multiple_bookings","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.multiple_bookings,"breakpoints":"xs sm"},
-          {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
-        ],
-        "empty": lang.empty,
-        "rows": data,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
+      }),
+      "empty": lang.empty,
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
+  function draw_mailbox_table() {
+    ft_mailbox_table = FooTable.init('#mailbox_table', {
+      "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
+        {"sorted": true,"name":"username","style":{"word-break":"break-all","min-width":"120px"},"title":lang.username},
+        {"name":"name","title":lang.fname,"style":{"word-break":"break-all","min-width":"120px"},"breakpoints":"xs sm"},
+        {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
+        {"name":"quota","style":{"whiteSpace":"nowrap"},"title":lang.domain_quota,"formatter": function(value){
+          res = value.split("/");
+          return humanFileSize(res[0]) + " / " + humanFileSize(res[1]);
         },
-        "filtering": {
-          "enabled": true,
-          "position": "left",
-          "placeholder": lang.filter_table
+        "sortValue": function(value){
+          res = value.split("/");
+          return res[0];
         },
-        "sorting": {
-          "enabled": true
-        }
-      });
-    }
-  });
-
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/alias-domain/all',
-    jsonp: false,
-    error: function () {
-      alert('Cannot draw alias domain table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?aliasdomain=' + encodeURI(item.alias_domain) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?aliasdomain=' + encodeURI(item.alias_domain) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
-					'</div>';
-      });
-      $('#aliasdomain_table').footable({
-        "columns": [
-          {"sorted": true,"name":"alias_domain","title":lang.alias,"style":{"width":"250px"}},
-          {"name":"target_domain","title":lang.target_domain},
-          {"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
-        ],
-        "empty": lang.empty,
-        "rows": data,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
         },
-        "filtering": {
-          "enabled": true,
-          "position": "left",
-          "placeholder": lang.filter_table
+        {"name":"spam_aliases","filterable": false,"title":lang.spam_aliases,"breakpoints":"xs sm md"},
+        {"name":"in_use","filterable": false,"type":"html","title":lang.in_use},
+        {"name":"messages","filterable": false,"title":lang.msg_num,"breakpoints":"xs sm md"},
+        {"name":"active","filterable": false,"title":lang.active},
+        {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
+      ],
+      "empty": lang.empty,
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/mailbox/all',
+        jsonp: false,
+        error: function () {
+          alert('Cannot draw mailbox table');
         },
-        "sorting": {
-          "enabled": true
-        }
-      });
-    }
-  });
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.quota = item.quota_used + "/" + item.quota;
+            item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
+            item.chkbox = '<input type="checkbox" data-id="mailbox" name="multi_select" value="' + item.username + '" />';
+            if (role == "admin") {
+            item.action = '<div class="btn-group">' +
+              '<a href="/edit.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+              '<a href="/delete.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+              '<a href="/index.php?duallogin=' + encodeURI(item.username) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
+              '</div>';
+            }
+            else {
+            item.action = '<div class="btn-group">' +
+              '<a href="/edit.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+              '<a href="/delete.php?mailbox=' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+              '</div>';
+            }
+            item.in_use = '<div class="progress">' +
+              '<div class="progress-bar progress-bar-' + item.percent_class + ' role="progressbar" aria-valuenow="' + item.percent_in_use + '" aria-valuemin="0" aria-valuemax="100" ' +
+              'style="min-width:2em;width:' + item.percent_in_use + '%">' + item.percent_in_use + '%' + '</div></div>';
 
-  $.ajax({
-    dataType: 'json',
-    url: '/api/v1/get/alias/all',
-    jsonp: false,
-    error: function () {
-      alert('Cannot draw alias table');
-    },
-    success: function (data) {
-      $.each(data, function (i, item) {
-        item.action = '<div class="btn-group">' +
-          '<a href="/edit.php?alias=' + encodeURI(item.address) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
-          '<a href="/delete.php?alias=' + encodeURI(item.address) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-pencil"></span> ' + lang.remove + '</a>' +
-					'</div>';
-        item.chkbox = '<input type="checkbox" class="alias_item" name="sel_aliases" value="' + item.address + '" />';
-        if (item.is_catch_all == 1) {
-          item.address = '<div class="label label-default">Catch-All</div> ' + item.address;
-        }
-        if (item.in_primary_domain !== "") {
-          item.domain = "↳ " + item.domain + " (" + item.in_primary_domain + ")";
+          });
         }
-      });
-      ft_aliases = FooTable.init("#alias_table", {
-        "columns": [
-          {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
-          {"sorted": true,"name":"address","title":lang.alias,"style":{"width":"250px"}},
-          {"name":"goto","title":lang.target_address},
-          {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
-          {"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active},
-          {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
-        ],
-        "empty": lang.empty,
-        "rows": data,
-        "paging": {
-          "enabled": true,
-          "limit": 5,
-          "size": pagination_size
-        },
-        "filtering": {
-          "enabled": true,
-          "position": "left",
-          "placeholder": lang.filter_table
+      }),
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
+  function draw_resource_table() {
+    ft_resource_table = FooTable.init('#resource_table', {
+      "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
+        {"sorted": true,"name":"description","title":lang.description,"style":{"width":"250px"}},
+        {"name":"kind","title":lang.kind},
+        {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
+        {"name":"multiple_bookings","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.multiple_bookings,"breakpoints":"xs sm"},
+        {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
+        {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
+      ],
+      "empty": lang.empty,
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/resource/all',
+        jsonp: false,
+        error: function () {
+          alert('Cannot draw resource table');
         },
-        "sorting": {
-          "enabled": true
-        }
-      });
-
-      var selected_aliases = [];
-
-      $(document).on('click', 'tr', function(e) {
-        if (e.target.type == "checkbox") {
-          e.stopPropagation();
-        } else {
-          var checkbox = $(this).find(':checkbox');
-          checkbox.trigger('click');
-        }
-      });
-
-      $(document).on('change', 'input[name=sel_aliases]:checkbox', function() {
-        if ($(this).is(':checked')) {
-          selected_aliases.push($(this).val());
-        }
-        else {
-          selected_aliases.splice($.inArray($(this).val(), selected_aliases),1);
-        }
-      });
-
-      $(document).on('click', '#select_all_aliases', function(e) {
-        e.preventDefault();
-        var alias_chkbxs = $("input[name=sel_aliases]");
-        alias_chkbxs.prop("checked", !alias_chkbxs.prop("checked")).change();
-      });
-
-      $(document).on('click', '#activate_selected_alias', function(e) {
-        e.preventDefault();
-        if (Object.keys(selected_aliases).length !== 0) {
-          $.ajax({
-            type: "POST",
-            dataType: "json",
-            data: { "address": JSON.stringify(selected_aliases), "active": "1" },
-            url: '/api/v1/edit/alias',
-            jsonp: false,
-            complete: function (data) {
-              window.location.href = window.location.href;
-            }
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.action = '<div class="btn-group">' +
+              '<a href="/edit.php?resource=' + encodeURI(item.name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+              '<a href="/delete.php?resource=' + encodeURI(item.name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+              '</div>';
+            item.chkbox = '<input type="checkbox" data-id="resource" name="multi_select" value="' + item.name + '" />';
           });
         }
-      });
+      }),
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
 
-      $(document).on('click', '#deactivate_selected_alias', function(e) {
-        e.preventDefault();
-        if (Object.keys(selected_aliases).length !== 0) {
-          $.ajax({
-            type: "POST",
-            dataType: "json",
-            data: { "address": JSON.stringify(selected_aliases), "active": "0" },
-            url: '/api/v1/edit/alias',
-            jsonp: false,
-            complete: function (data) {
-              window.location.href = window.location.href;
+  function draw_alias_table() {
+    ft_alias_table = FooTable.init('#alias_table', {
+      "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
+        {"sorted": true,"name":"address","title":lang.alias,"style":{"width":"250px"}},
+        {"name":"goto","title":lang.target_address},
+        {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
+        {"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active},
+        {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
+      ],
+      "empty": lang.empty,
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/alias/all',
+        jsonp: false,
+        error: function () {
+          alert('Cannot draw alias table');
+        },
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.action = '<div class="btn-group">' +
+              '<a href="/edit.php?alias=' + encodeURI(item.address) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+              '<a href="/delete.php?alias=' + encodeURI(item.address) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-pencil"></span> ' + lang.remove + '</a>' +
+              '</div>';
+            item.chkbox = '<input type="checkbox" data-id="alias" name="multi_select" value="' + item.address + '" />';
+            if (item.is_catch_all == 1) {
+              item.address = '<div class="label label-default">Catch-All</div> ' + item.address;
+            }
+            if (item.in_primary_domain !== "") {
+              item.domain = "↳ " + item.domain + " (" + item.in_primary_domain + ")";
             }
           });
         }
-      });
-
-      $(document).on('click', '#delete_selected_alias', function(e) {
-        e.preventDefault();
-        if (Object.keys(selected_aliases).length !== 0) {
-          $(document).on('show.bs.modal','#ConfirmDeleteModal', function () {
-            $("#ItemsToDelete").empty();
-            for (var i in selected_aliases) {
-              $("#ItemsToDelete").append("<li>" + selected_aliases[i] + "</li>");
-            }
-          })
-          $('#ConfirmDeleteModal').modal({
-            backdrop: 'static',
-            keyboard: false
-          })
-          .one('click', '#IsConfirmed', function(e) {
-            $.ajax({
-              type: "POST",
-              dataType: "json",
-              data: { "address": JSON.stringify(selected_aliases) },
-              url: '/api/v1/delete/alias',
-              jsonp: false,
-              complete: function (data) {
-              window.location.href = window.location.href;
-              }
-            });
-          })
-          .one('click', '#isCanceled', function(e) {
-            $('#ConfirmDeleteModal').modal('hide');
-          });;
+      }),
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
 
+  function draw_aliasdomain_table() {
+    ft_aliasdomain_table = FooTable.init('#aliasdomain_table', {
+      "columns": [
+        {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
+        {"sorted": true,"name":"alias_domain","title":lang.alias,"style":{"width":"250px"}},
+        {"name":"target_domain","title":lang.target_domain},
+        {"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active},
+        {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
+      ],
+      "empty": lang.empty,
+      "rows": $.ajax({
+        dataType: 'json',
+        url: '/api/v1/get/alias-domain/all',
+        jsonp: false,
+        error: function () {
+          alert('Cannot draw alias domain table');
+        },
+        success: function (data) {
+          $.each(data, function (i, item) {
+            item.action = '<div class="btn-group">' +
+              '<a href="/edit.php?aliasdomain=' + encodeURI(item.alias_domain) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
+              '<a href="/delete.php?aliasdomain=' + encodeURI(item.alias_domain) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
+              '</div>';
+            item.chkbox = '<input type="checkbox" data-id="alias-domain" name="multi_select" value="' + item.alias_domain + '" />';
+          });
         }
-      });
-
-    }
+      }),
+      "paging": {
+        "enabled": true,
+        "limit": 5,
+        "size": pagination_size
+      },
+      "filtering": {
+        "enabled": true,
+        "position": "left",
+        "placeholder": lang.filter_table
+      },
+      "sorting": {
+        "enabled": true
+      }
+    });
+  }
 
-  });
-});
+  draw_domain_table();
+  draw_mailbox_table();
+  draw_resource_table();
+  draw_alias_table();
+  draw_aliasdomain_table();
+});
\ No newline at end of file
diff --git a/data/web/js/notify.min.js b/data/web/js/notify.min.js
deleted file mode 100644
index 6766fd1d..00000000
--- a/data/web/js/notify.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(e){typeof define=="function"&&define.amd?define(["jquery"],e):typeof module=="object"&&module.exports?module.exports=function(t,n){return n===undefined&&(typeof window!="undefined"?n=require("jquery"):n=require("jquery")(t)),e(n),n}:e(jQuery)})(function(e){function A(t,n,i){typeof i=="string"&&(i={className:i}),this.options=E(w,e.isPlainObject(i)?i:{}),this.loadHTML(),this.wrapper=e(h.html),this.options.clickToHide&&this.wrapper.addClass(r+"-hidable"),this.wrapper.data(r,this),this.arrow=this.wrapper.find("."+r+"-arrow"),this.container=this.wrapper.find("."+r+"-container"),this.container.append(this.userContainer),t&&t.length&&(this.elementType=t.attr("type"),this.originalElement=t,this.elem=N(t),this.elem.data(r,this),this.elem.before(this.wrapper)),this.container.hide(),this.run(n)}var t=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(t in this&&this[t]===e)return t;return-1},n="notify",r=n+"js",i=n+"!blank",s={t:"top",m:"middle",b:"bottom",l:"left",c:"center",r:"right"},o=["l","c","r"],u=["t","m","b"],a=["t","b","l","r"],f={t:"b",m:null,b:"t",l:"r",c:null,r:"l"},l=function(t){var n;return n=[],e.each(t.split(/\W+/),function(e,t){var r;r=t.toLowerCase().charAt(0);if(s[r])return n.push(r)}),n},c={},h={name:"core",html:'<div class="'+r+'-wrapper">\n	<div class="'+r+'-arrow"></div>\n	<div class="'+r+'-container"></div>\n</div>',css:"."+r+"-corner {\n	position: fixed;\n	margin: 5px;\n	z-index: 1050;\n}\n\n."+r+"-corner ."+r+"-wrapper,\n."+r+"-corner ."+r+"-container {\n	position: relative;\n	display: block;\n	height: inherit;\n	width: inherit;\n	margin: 3px;\n}\n\n."+r+"-wrapper {\n	z-index: 1;\n	position: absolute;\n	display: inline-block;\n	height: 0;\n	width: 0;\n}\n\n."+r+"-container {\n	display: none;\n	z-index: 1;\n	position: absolute;\n}\n\n."+r+"-hidable {\n	cursor: pointer;\n}\n\n[data-notify-text],[data-notify-html] {\n	position: relative;\n}\n\n."+r+"-arrow {\n	position: absolute;\n	z-index: 2;\n	width: 0;\n	height: 0;\n}"},p={"border-radius":["-webkit-","-moz-"]},d=function(e){return c[e]},v=function(e){if(!e)throw"Missing Style name";c[e]&&delete c[e]},m=function(t,i){if(!t)throw"Missing Style name";if(!i)throw"Missing Style definition";if(!i.html)throw"Missing Style HTML";var s=c[t];s&&s.cssElem&&(window.console&&console.warn(n+": overwriting style '"+t+"'"),c[t].cssElem.remove()),i.name=t,c[t]=i;var o="";i.classes&&e.each(i.classes,function(t,n){return o+="."+r+"-"+i.name+"-"+t+" {\n",e.each(n,function(t,n){return p[t]&&e.each(p[t],function(e,r){return o+="	"+r+t+": "+n+";\n"}),o+="	"+t+": "+n+";\n"}),o+="}\n"}),i.css&&(o+="/* styles for "+i.name+" */\n"+i.css),o&&(i.cssElem=g(o),i.cssElem.attr("id","notify-"+i.name));var u={},a=e(i.html);y("html",a,u),y("text",a,u),i.fields=u},g=function(t){var n,r,i;r=x("style"),r.attr("type","text/css"),e("head").append(r);try{r.html(t)}catch(s){r[0].styleSheet.cssText=t}return r},y=function(t,n,r){var s;return t!=="html"&&(t="text"),s="data-notify-"+t,b(n,"["+s+"]").each(function(){var n;n=e(this).attr(s),n||(n=i),r[n]=t})},b=function(e,t){return e.is(t)?e:e.find(t)},w={clickToHide:!0,autoHide:!0,autoHideDelay:5e3,arrowShow:!0,arrowSize:5,breakNewLines:!0,elementPosition:"bottom",globalPosition:"top right",style:"bootstrap",className:"error",showAnimation:"slideDown",showDuration:400,hideAnimation:"slideUp",hideDuration:200,gap:5},E=function(t,n){var r;return r=function(){},r.prototype=t,e.extend(!0,new r,n)},S=function(t){return e.extend(w,t)},x=function(t){return e("<"+t+"></"+t+">")},T={},N=function(t){var n;return t.is("[type=radio]")&&(n=t.parents("form:first").find("[type=radio]").filter(function(n,r){return e(r).attr("name")===t.attr("name")}),t=n.first()),t},C=function(e,t,n){var r,i;if(typeof n=="string")n=parseInt(n,10);else if(typeof n!="number")return;if(isNaN(n))return;return r=s[f[t.charAt(0)]],i=t,e[r]!==undefined&&(t=s[r.charAt(0)],n=-n),e[t]===undefined?e[t]=n:e[t]+=n,null},k=function(e,t,n){if(e==="l"||e==="t")return 0;if(e==="c"||e==="m")return n/2-t/2;if(e==="r"||e==="b")return n-t;throw"Invalid alignment"},L=function(e){return L.e=L.e||x("div"),L.e.text(e).html()};A.prototype.loadHTML=function(){var t;t=this.getStyle(),this.userContainer=e(t.html),this.userFields=t.fields},A.prototype.show=function(e,t){var n,r,i,s,o;r=function(n){return function(){!e&&!n.elem&&n.destroy();if(t)return t()}}(this),o=this.container.parent().parents(":hidden").length>0,i=this.container.add(this.arrow),n=[];if(o&&e)s="show";else if(o&&!e)s="hide";else if(!o&&e)s=this.options.showAnimation,n.push(this.options.showDuration);else{if(!!o||!!e)return r();s=this.options.hideAnimation,n.push(this.options.hideDuration)}return n.push(r),i[s].apply(i,n)},A.prototype.setGlobalPosition=function(){var t=this.getPosition(),n=t[0],i=t[1],o=s[n],u=s[i],a=n+"|"+i,f=T[a];if(!f||!document.body.contains(f[0])){f=T[a]=x("div");var l={};l[o]=0,u==="middle"?l.top="45%":u==="center"?l.left="45%":l[u]=0,f.css(l).addClass(r+"-corner"),e("body").append(f)}return f.prepend(this.wrapper)},A.prototype.setElementPosition=function(){var n,r,i,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,L,A,O,M,_,D,P,H,B,j;H=this.getPosition(),_=H[0],O=H[1],M=H[2],g=this.elem.position(),d=this.elem.outerHeight(),y=this.elem.outerWidth(),v=this.elem.innerHeight(),m=this.elem.innerWidth(),j=this.wrapper.position(),c=this.container.height(),h=this.container.width(),T=s[_],L=f[_],A=s[L],p={},p[A]=_==="b"?d:_==="r"?y:0,C(p,"top",g.top-j.top),C(p,"left",g.left-j.left),B=["top","left"];for(w=0,S=B.length;w<S;w++)D=B[w],N=parseInt(this.elem.css("margin-"+D),10),N&&C(p,D,N);b=Math.max(0,this.options.gap-(this.options.arrowShow?i:0)),C(p,A,b);if(!this.options.arrowShow)this.arrow.hide();else{i=this.options.arrowSize,r=e.extend({},p),n=this.userContainer.css("border-color")||this.userContainer.css("border-top-color")||this.userContainer.css("background-color")||"white";for(E=0,x=a.length;E<x;E++){D=a[E],P=s[D];if(D===L)continue;l=P===T?n:"transparent",r["border-"+P]=i+"px solid "+l}C(p,s[L],i),t.call(a,O)>=0&&C(r,s[O],i*2)}t.call(u,_)>=0?(C(p,"left",k(O,h,y)),r&&C(r,"left",k(O,i,m))):t.call(o,_)>=0&&(C(p,"top",k(O,c,d)),r&&C(r,"top",k(O,i,v))),this.container.is(":visible")&&(p.display="block"),this.container.removeAttr("style").css(p);if(r)return this.arrow.removeAttr("style").css(r)},A.prototype.getPosition=function(){var e,n,r,i,s,f,c,h;h=this.options.position||(this.elem?this.options.elementPosition:this.options.globalPosition),e=l(h),e.length===0&&(e[0]="b");if(n=e[0],t.call(a,n)<0)throw"Must be one of ["+a+"]";if(e.length===1||(r=e[0],t.call(u,r)>=0)&&(i=e[1],t.call(o,i)<0)||(s=e[0],t.call(o,s)>=0)&&(f=e[1],t.call(u,f)<0))e[1]=(c=e[0],t.call(o,c)>=0)?"m":"l";return e.length===2&&(e[2]=e[1]),e},A.prototype.getStyle=function(e){var t;e||(e=this.options.style),e||(e="default"),t=c[e];if(!t)throw"Missing style: "+e;return t},A.prototype.updateClasses=function(){var t,n;return t=["base"],e.isArray(this.options.className)?t=t.concat(this.options.className):this.options.className&&t.push(this.options.className),n=this.getStyle(),t=e.map(t,function(e){return r+"-"+n.name+"-"+e}).join(" "),this.userContainer.attr("class",t)},A.prototype.run=function(t,n){var r,s,o,u,a;e.isPlainObject(n)?e.extend(this.options,n):e.type(n)==="string"&&(this.options.className=n);if(this.container&&!t){this.show(!1);return}if(!this.container&&!t)return;s={},e.isPlainObject(t)?s=t:s[i]=t;for(o in s){r=s[o],u=this.userFields[o];if(!u)continue;u==="text"&&(r=L(r),this.options.breakNewLines&&(r=r.replace(/\n/g,"<br/>"))),a=o===i?"":"="+o,b(this.userContainer,"[data-notify-"+u+a+"]").html(r)}this.updateClasses(),this.elem?this.setElementPosition():this.setGlobalPosition(),this.show(!0),this.options.autoHide&&(clearTimeout(this.autohideTimer),this.autohideTimer=setTimeout(this.show.bind(this,!1),this.options.autoHideDelay))},A.prototype.destroy=function(){this.wrapper.data(r,null),this.wrapper.remove()},e[n]=function(t,r,i){return t&&t.nodeName||t.jquery?e(t)[n](r,i):(i=r,r=t,new A(null,r,i)),t},e.fn[n]=function(t,n){return e(this).each(function(){var i=N(e(this)).data(r);i&&i.destroy();var s=new A(e(this),t,n)}),this},e.extend(e[n],{defaults:S,addStyle:m,removeStyle:v,pluginOptions:w,getStyle:d,insertCSS:g}),m("bootstrap",{html:"<div>\n<span data-notify-text></span>\n</div>",classes:{base:{"font-weight":"bold",padding:"8px 15px 8px 14px","text-shadow":"0 1px 0 rgba(255, 255, 255, 0.5)","background-color":"#fcf8e3",border:"1px solid #fbeed5","border-radius":"4px","white-space":"nowrap","padding-left":"25px","background-repeat":"no-repeat","background-position":"3px 7px"},error:{color:"#B94A48","background-color":"#F2DEDE","border-color":"#EED3D7","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=)"},success:{color:"#468847","background-color":"#DFF0D8","border-color":"#D6E9C6","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAutJREFUeNq0lctPE0Ecx38zu/RFS1EryqtgJFA08YCiMZIAQQ4eRG8eDGdPJiYeTIwHTfwPiAcvXIwXLwoXPaDxkWgQ6islKlJLSQWLUraPLTv7Gme32zoF9KSTfLO7v53vZ3d/M7/fIth+IO6INt2jjoA7bjHCJoAlzCRw59YwHYjBnfMPqAKWQYKjGkfCJqAF0xwZjipQtA3MxeSG87VhOOYegVrUCy7UZM9S6TLIdAamySTclZdYhFhRHloGYg7mgZv1Zzztvgud7V1tbQ2twYA34LJmF4p5dXF1KTufnE+SxeJtuCZNsLDCQU0+RyKTF27Unw101l8e6hns3u0PBalORVVVkcaEKBJDgV3+cGM4tKKmI+ohlIGnygKX00rSBfszz/n2uXv81wd6+rt1orsZCHRdr1Imk2F2Kob3hutSxW8thsd8AXNaln9D7CTfA6O+0UgkMuwVvEFFUbbAcrkcTA8+AtOk8E6KiQiDmMFSDqZItAzEVQviRkdDdaFgPp8HSZKAEAL5Qh7Sq2lIJBJwv2scUqkUnKoZgNhcDKhKg5aH+1IkcouCAdFGAQsuWZYhOjwFHQ96oagWgRoUov1T9kRBEODAwxM2QtEUl+Wp+Ln9VRo6BcMw4ErHRYjH4/B26AlQoQQTRdHWwcd9AH57+UAXddvDD37DmrBBV34WfqiXPl61g+vr6xA9zsGeM9gOdsNXkgpEtTwVvwOklXLKm6+/p5ezwk4B+j6droBs2CsGa/gNs6RIxazl4Tc25mpTgw/apPR1LYlNRFAzgsOxkyXYLIM1V8NMwyAkJSctD1eGVKiq5wWjSPdjmeTkiKvVW4f2YPHWl3GAVq6ymcyCTgovM3FzyRiDe2TaKcEKsLpJvNHjZgPNqEtyi6mZIm4SRFyLMUsONSSdkPeFtY1n0mczoY3BHTLhwPRy9/lzcziCw9ACI+yql0VLzcGAZbYSM5CCSZg1/9oc/nn7+i8N9p/8An4JMADxhH+xHfuiKwAAAABJRU5ErkJggg==)"},info:{color:"#3A87AD","background-color":"#D9EDF7","border-color":"#BCE8F1","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYFAhkSsdes/QAAA8dJREFUOMvVlGtMW2UYx//POaWHXg6lLaW0ypAtw1UCgbniNOLcVOLmAjHZolOYlxmTGXVZdAnRfXQm+7SoU4mXaOaiZsEpC9FkiQs6Z6bdCnNYruM6KNBw6YWewzl9z+sHImEWv+vz7XmT95f/+3/+7wP814v+efDOV3/SoX3lHAA+6ODeUFfMfjOWMADgdk+eEKz0pF7aQdMAcOKLLjrcVMVX3xdWN29/GhYP7SvnP0cWfS8caSkfHZsPE9Fgnt02JNutQ0QYHB2dDz9/pKX8QjjuO9xUxd/66HdxTeCHZ3rojQObGQBcuNjfplkD3b19Y/6MrimSaKgSMmpGU5WevmE/swa6Oy73tQHA0Rdr2Mmv/6A1n9w9suQ7097Z9lM4FlTgTDrzZTu4StXVfpiI48rVcUDM5cmEksrFnHxfpTtU/3BFQzCQF/2bYVoNbH7zmItbSoMj40JSzmMyX5qDvriA7QdrIIpA+3cdsMpu0nXI8cV0MtKXCPZev+gCEM1S2NHPvWfP/hL+7FSr3+0p5RBEyhEN5JCKYr8XnASMT0xBNyzQGQeI8fjsGD39RMPk7se2bd5ZtTyoFYXftF6y37gx7NeUtJJOTFlAHDZLDuILU3j3+H5oOrD3yWbIztugaAzgnBKJuBLpGfQrS8wO4FZgV+c1IxaLgWVU0tMLEETCos4xMzEIv9cJXQcyagIwigDGwJgOAtHAwAhisQUjy0ORGERiELgG4iakkzo4MYAxcM5hAMi1WWG1yYCJIcMUaBkVRLdGeSU2995TLWzcUAzONJ7J6FBVBYIggMzmFbvdBV44Corg8vjhzC+EJEl8U1kJtgYrhCzgc/vvTwXKSib1paRFVRVORDAJAsw5FuTaJEhWM2SHB3mOAlhkNxwuLzeJsGwqWzf5TFNdKgtY5qHp6ZFf67Y/sAVadCaVY5YACDDb3Oi4NIjLnWMw2QthCBIsVhsUTU9tvXsjeq9+X1d75/KEs4LNOfcdf/+HthMnvwxOD0wmHaXr7ZItn2wuH2SnBzbZAbPJwpPx+VQuzcm7dgRCB57a1uBzUDRL4bfnI0RE0eaXd9W89mpjqHZnUI5Hh2l2dkZZUhOqpi2qSmpOmZ64Tuu9qlz/SEXo6MEHa3wOip46F1n7633eekV8ds8Wxjn37Wl63VVa+ej5oeEZ/82ZBETJjpJ1Rbij2D3Z/1trXUvLsblCK0XfOx0SX2kMsn9dX+d+7Kf6h8o4AIykuffjT8L20LU+w4AZd5VvEPY+XpWqLV327HR7DzXuDnD8r+ovkBehJ8i+y8YAAAAASUVORK5CYII=)"},warn:{color:"#C09853","background-color":"#FCF8E3","border-color":"#FBEED5","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABJlBMVEXr6eb/2oD/wi7/xjr/0mP/ykf/tQD/vBj/3o7/uQ//vyL/twebhgD/4pzX1K3z8e349vK6tHCilCWbiQymn0jGworr6dXQza3HxcKkn1vWvV/5uRfk4dXZ1bD18+/52YebiAmyr5S9mhCzrWq5t6ufjRH54aLs0oS+qD751XqPhAybhwXsujG3sm+Zk0PTwG6Shg+PhhObhwOPgQL4zV2nlyrf27uLfgCPhRHu7OmLgAafkyiWkD3l49ibiAfTs0C+lgCniwD4sgDJxqOilzDWowWFfAH08uebig6qpFHBvH/aw26FfQTQzsvy8OyEfz20r3jAvaKbhgG9q0nc2LbZxXanoUu/u5WSggCtp1anpJKdmFz/zlX/1nGJiYmuq5Dx7+sAAADoPUZSAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfdBgUBGhh4aah5AAAAlklEQVQY02NgoBIIE8EUcwn1FkIXM1Tj5dDUQhPU502Mi7XXQxGz5uVIjGOJUUUW81HnYEyMi2HVcUOICQZzMMYmxrEyMylJwgUt5BljWRLjmJm4pI1hYp5SQLGYxDgmLnZOVxuooClIDKgXKMbN5ggV1ACLJcaBxNgcoiGCBiZwdWxOETBDrTyEFey0jYJ4eHjMGWgEAIpRFRCUt08qAAAAAElFTkSuQmCC)"}}}),e(function(){g(h.css).attr("id","core-notify"),e(document).on("click","."+r+"-hidable",function(t){e(this).trigger("notify-hide")}),e(document).on("notify-hide","."+r+"-wrapper",function(t){var n=e(this).data(r);n&&n.show(!1)})})})
\ No newline at end of file
diff --git a/data/web/js/noty.min.js b/data/web/js/noty.min.js
deleted file mode 100644
index 2cdeac52..00000000
--- a/data/web/js/noty.min.js
+++ /dev/null
@@ -1,9 +0,0 @@
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Noty",[],e):"object"==typeof exports?exports.Noty=e():t.Noty=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var i=n[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=6)}([function(t,e,n){"use strict";function o(t,e,n){var o=void 0;if(!n){for(o in e)if(e.hasOwnProperty(o)&&e[o]===t)return!0}else for(o in e)if(e.hasOwnProperty(o)&&e[o]===t)return!0;return!1}function i(t){t=t||window.event,void 0!==t.stopPropagation?t.stopPropagation():t.cancelBubble=!0}function r(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e="noty_"+t+"_";return e+="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)})}function s(t){var e=t.offsetHeight,n=window.getComputedStyle(t);return e+=parseInt(n.marginTop)+parseInt(n.marginBottom)}function u(t,e,n){var o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];e=e.split(" ");for(var i=0;i<e.length;i++)document.addEventListener?t.addEventListener(e[i],n,o):document.attachEvent&&t.attachEvent("on"+e[i],n)}function a(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function c(t,e){var n=f(t),o=n+e;a(n,e)||(t.className=o.substring(1))}function l(t,e){var n=f(t),o=void 0;a(t,e)&&(o=n.replace(" "+e+" "," "),t.className=o.substring(1,o.length-1))}function d(t){t.parentNode&&t.parentNode.removeChild(t)}function f(t){return(" "+(t&&t.className||"")+" ").replace(/\s+/gi," ")}function h(){function t(){b.PageHidden=document[s],o()}function e(){b.PageHidden=!0,o()}function n(){b.PageHidden=!1,o()}function o(){b.PageHidden?i():r()}function i(){setTimeout(function(){Object.keys(b.Store).forEach(function(t){b.Store.hasOwnProperty(t)&&b.Store[t].options.visibilityControl&&b.Store[t].stop()})},100)}function r(){setTimeout(function(){Object.keys(b.Store).forEach(function(t){b.Store.hasOwnProperty(t)&&b.Store[t].options.visibilityControl&&b.Store[t].resume()}),b.queueRenderAll()},100)}var s=void 0,a=void 0;void 0!==document.hidden?(s="hidden",a="visibilitychange"):void 0!==document.msHidden?(s="msHidden",a="msvisibilitychange"):void 0!==document.webkitHidden&&(s="webkitHidden",a="webkitvisibilitychange"),u(document,a,t),u(window,"blur",e),u(window,"focus",n)}function p(t){if(t.hasSound){var e=document.createElement("audio");t.options.sounds.sources.forEach(function(t){var n=document.createElement("source");n.src=t,n.type="audio/"+m(t),e.appendChild(n)}),t.barDom?t.barDom.appendChild(e):document.querySelector("body").appendChild(e),e.volume=t.options.sounds.volume,t.soundPlayed||(e.play(),t.soundPlayed=!0),e.onended=function(){d(e)}}}function m(t){return t.match(/\.([^.]+)$/)[1]}Object.defineProperty(e,"__esModule",{value:!0}),e.css=e.deepExtend=e.animationEndEvents=void 0;var v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};e.inArray=o,e.stopPropagation=i,e.generateID=r,e.outerHeight=s,e.addListener=u,e.hasClass=a,e.addClass=c,e.removeClass=l,e.remove=d,e.classList=f,e.visibilityChangeFlow=h,e.createAudioElements=p;var y=n(1),b=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}(y);e.animationEndEvents="webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",e.deepExtend=function t(e){e=e||{};for(var n=1;n<arguments.length;n++){var o=arguments[n];if(o)for(var i in o)o.hasOwnProperty(i)&&(Array.isArray(o[i])?e[i]=o[i]:"object"===v(o[i])&&null!==o[i]?e[i]=t(e[i],o[i]):e[i]=o[i])}return e},e.css=function(){function t(t){return t.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(t,e){return e.toUpperCase()})}function e(t){var e=document.body.style;if(t in e)return t;for(var n=i.length,o=t.charAt(0).toUpperCase()+t.slice(1),r=void 0;n--;)if((r=i[n]+o)in e)return r;return t}function n(n){return n=t(n),r[n]||(r[n]=e(n))}function o(t,e,o){e=n(e),t.style[e]=o}var i=["Webkit","O","Moz","ms"],r={};return function(t,e){var n=arguments,i=void 0,r=void 0;if(2===n.length)for(i in e)e.hasOwnProperty(i)&&void 0!==(r=e[i])&&e.hasOwnProperty(i)&&o(t,i,r);else o(t,n[1],n[2])}}()},function(t,e,n){"use strict";function o(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"global",e=0,n=x;return E.hasOwnProperty(t)&&(n=E[t].maxVisible,Object.keys(P).forEach(function(n){P[n].options.queue!==t||P[n].closed||e++})),{current:e,maxVisible:n}}function i(t){E.hasOwnProperty(t.options.queue)||(E[t.options.queue]={maxVisible:x,queue:[]}),E[t.options.queue].queue.push(t)}function r(t){if(E.hasOwnProperty(t.options.queue)){var e=[];Object.keys(E[t.options.queue].queue).forEach(function(n){E[t.options.queue].queue[n].id!==t.id&&e.push(E[t.options.queue].queue[n])}),E[t.options.queue].queue=e}}function s(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"global";if(E.hasOwnProperty(t)){var e=E[t].queue.shift();e&&e.show()}}function u(){Object.keys(E).forEach(function(t){s(t)})}function a(t){var e=k.generateID("ghost"),n=document.createElement("div");n.setAttribute("id",e),k.css(n,{height:k.outerHeight(t.barDom)+"px"}),t.barDom.insertAdjacentHTML("afterend",n.outerHTML),k.remove(t.barDom),n=document.getElementById(e),k.addClass(n,"noty_fix_effects_height"),k.addListener(n,k.animationEndEvents,function(){k.remove(n)})}function c(t){m(t);var e='<div class="noty_body">'+t.options.text+"</div>"+d(t)+'<div class="noty_progressbar"></div>';t.barDom=document.createElement("div"),t.barDom.setAttribute("id",t.id),k.addClass(t.barDom,"noty_bar noty_type__"+t.options.type+" noty_theme__"+t.options.theme),t.barDom.innerHTML=e,b(t,"onTemplate")}function l(t){return!(!t.options.buttons||!Object.keys(t.options.buttons).length)}function d(t){if(l(t)){var e=document.createElement("div");return k.addClass(e,"noty_buttons"),Object.keys(t.options.buttons).forEach(function(n){e.appendChild(t.options.buttons[n].dom)}),t.options.buttons.forEach(function(t){e.appendChild(t.dom)}),e.outerHTML}return""}function f(t){t.options.modal&&(0===S&&p(),e.DocModalCount=S+=1)}function h(t){if(t.options.modal&&S>0&&(e.DocModalCount=S-=1,S<=0)){var n=document.querySelector(".noty_modal");n&&(k.removeClass(n,"noty_modal_open"),k.addClass(n,"noty_modal_close"),k.addListener(n,k.animationEndEvents,function(){k.remove(n)}))}}function p(){var t=document.querySelector("body"),e=document.createElement("div");k.addClass(e,"noty_modal"),t.insertBefore(e,t.firstChild),k.addClass(e,"noty_modal_open"),k.addListener(e,k.animationEndEvents,function(){k.removeClass(e,"noty_modal_open")})}function m(t){if(t.options.container)return void(t.layoutDom=document.querySelector(t.options.container));var e="noty_layout__"+t.options.layout;t.layoutDom=document.querySelector("div#"+e),t.layoutDom||(t.layoutDom=document.createElement("div"),t.layoutDom.setAttribute("id",e),k.addClass(t.layoutDom,"noty_layout"),document.querySelector("body").appendChild(t.layoutDom))}function v(t){t.options.timeout&&(t.options.progressBar&&t.progressDom&&k.css(t.progressDom,{transition:"width "+t.options.timeout+"ms linear",width:"0%"}),clearTimeout(t.closeTimer),t.closeTimer=setTimeout(function(){t.close()},t.options.timeout))}function y(t){t.options.timeout&&t.closeTimer&&(clearTimeout(t.closeTimer),t.closeTimer=-1,t.options.progressBar&&t.progressDom&&k.css(t.progressDom,{transition:"width 0ms linear",width:"100%"}))}function b(t,e){t.listeners.hasOwnProperty(e)&&t.listeners[e].forEach(function(e){"function"==typeof e&&e.apply(t)})}function w(t){b(t,"afterShow"),v(t),k.addListener(t.barDom,"mouseenter",function(){y(t)}),k.addListener(t.barDom,"mouseleave",function(){v(t)})}function g(t){delete P[t.id],t.closing=!1,b(t,"afterClose"),k.remove(t.barDom),0!==t.layoutDom.querySelectorAll(".noty_bar").length||t.options.container||k.remove(t.layoutDom),(k.inArray("docVisible",t.options.titleCount.conditions)||k.inArray("docHidden",t.options.titleCount.conditions))&&D.decrement(),s(t.options.queue)}Object.defineProperty(e,"__esModule",{value:!0}),e.Defaults=e.Store=e.Queues=e.DefaultMaxVisible=e.docTitle=e.DocModalCount=e.PageHidden=void 0,e.getQueueCounts=o,e.addToQueue=i,e.removeFromQueue=r,e.queueRender=s,e.queueRenderAll=u,e.ghostFix=a,e.build=c,e.hasButtons=l,e.handleModal=f,e.handleModalClose=h,e.queueClose=v,e.dequeueClose=y,e.fire=b,e.openFlow=w,e.closeFlow=g;var _=n(0),k=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}(_),S=(e.PageHidden=!1,e.DocModalCount=0),C={originalTitle:null,count:0,changed:!1,timer:-1},D=e.docTitle={increment:function(){C.count++,D._update()},decrement:function(){if(--C.count<=0)return void D._clear();D._update()},_update:function(){var t=document.title;C.changed?document.title="("+C.count+") "+C.originalTitle:(C.originalTitle=t,document.title="("+C.count+") "+t,C.changed=!0)},_clear:function(){C.changed&&(C.count=0,document.title=C.originalTitle,C.changed=!1)}},x=e.DefaultMaxVisible=5,E=e.Queues={global:{maxVisible:x,queue:[]}},P=e.Store={};e.Defaults={type:"alert",layout:"topRight",theme:"mint",text:"",timeout:!1,progressBar:!0,closeWith:["click"],animation:{open:"noty_effects_open",close:"noty_effects_close"},id:!1,force:!1,killer:!1,queue:"global",container:!1,buttons:[],callbacks:{beforeShow:null,onShow:null,afterShow:null,onClose:null,afterClose:null,onHover:null,onTemplate:null},sounds:{sources:[],volume:1,conditions:[]},titleCount:{conditions:[]},modal:!1,visibilityControl:!0}},function(t,e,n){"use strict";function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0}),e.NotyButton=void 0;var i=n(0),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}(i);e.NotyButton=function t(e,n,i){var s=this,u=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};return o(this,t),this.dom=document.createElement("button"),this.dom.innerHTML=e,this.id=u.id=u.id||r.generateID("button"),this.cb=i,Object.keys(u).forEach(function(t){s.dom.setAttribute(t,u[t])}),r.addClass(this.dom,n||"noty_btn"),this}},function(t,e,n){"use strict";function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var i=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}();e.Push=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"/service-worker.js";return o(this,t),this.subData={},this.workerPath=e,this.listeners={onPermissionGranted:[],onPermissionDenied:[],onSubscriptionSuccess:[],onSubscriptionCancel:[],onWorkerError:[],onWorkerSuccess:[],onWorkerNotSupported:[]},this}return i(t,[{key:"on",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){};return"function"==typeof e&&this.listeners.hasOwnProperty(t)&&this.listeners[t].push(e),this}},{key:"fire",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];this.listeners.hasOwnProperty(t)&&this.listeners[t].forEach(function(t){"function"==typeof t&&t.apply(e,n)})}},{key:"create",value:function(){console.log("NOT IMPLEMENTED YET")}},{key:"isSupported",value:function(){var t=!1;try{t=window.Notification||window.webkitNotifications||navigator.mozNotification||window.external&&void 0!==window.external.msIsSiteMode()}catch(t){}return t}},{key:"getPermissionStatus",value:function(){var t="default";if(window.Notification&&window.Notification.permissionLevel)t=window.Notification.permissionLevel;else if(window.webkitNotifications&&window.webkitNotifications.checkPermission)switch(window.webkitNotifications.checkPermission()){case 1:t="default";break;case 0:t="granted";break;default:t="denied"}else window.Notification&&window.Notification.permission?t=window.Notification.permission:navigator.mozNotification?t="granted":window.external&&void 0!==window.external.msIsSiteMode()&&(t=window.external.msIsSiteMode()?"granted":"default");return t.toString().toLowerCase()}},{key:"getEndpoint",value:function(t){var e=t.endpoint,n=t.subscriptionId;return n&&-1===e.indexOf(n)&&(e+="/"+n),e}},{key:"isSWRegistered",value:function(){try{return"activated"===navigator.serviceWorker.controller.state}catch(t){return!1}}},{key:"unregisterWorker",value:function(){var t=this;"serviceWorker"in navigator&&navigator.serviceWorker.getRegistrations().then(function(e){var n=!0,o=!1,i=void 0;try{for(var r,s=e[Symbol.iterator]();!(n=(r=s.next()).done);n=!0){r.value.unregister(),t.fire("onSubscriptionCancel")}}catch(t){o=!0,i=t}finally{try{!n&&s.return&&s.return()}finally{if(o)throw i}}})}},{key:"requestSubscription",value:function(){var t=this,e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],n=this,o=this.getPermissionStatus(),i=function(o){"granted"===o?(t.fire("onPermissionGranted"),"serviceWorker"in navigator?navigator.serviceWorker.register(t.workerPath).then(function(){navigator.serviceWorker.ready.then(function(t){n.fire("onWorkerSuccess"),t.pushManager.subscribe({userVisibleOnly:e}).then(function(t){var e=t.getKey("p256dh"),o=t.getKey("auth");n.subData={endpoint:n.getEndpoint(t),p256dh:e?window.btoa(String.fromCharCode.apply(null,new Uint8Array(e))):null,auth:o?window.btoa(String.fromCharCode.apply(null,new Uint8Array(o))):null},n.fire("onSubscriptionSuccess",[n.subData])}).catch(function(t){n.fire("onWorkerError",[t])})})}):n.fire("onWorkerNotSupported")):"denied"===o&&(t.fire("onPermissionDenied"),t.unregisterWorker())};"default"===o?window.Notification&&window.Notification.requestPermission?window.Notification.requestPermission(i):window.webkitNotifications&&window.webkitNotifications.checkPermission&&window.webkitNotifications.requestPermission(i):i(o)}}]),t}()},function(t,e,n){(function(e,o){/*!
- * @overview es6-promise - a tiny implementation of Promises/A+.
- * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
- * @license   Licensed under MIT license
- *            See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
- * @version   4.1.0
- */
-!function(e,n){t.exports=n()}(0,function(){"use strict";function t(t){return"function"==typeof t||"object"==typeof t&&null!==t}function i(t){return"function"==typeof t}function r(t){z=t}function s(t){U=t}function u(){return void 0!==R?function(){R(c)}:a()}function a(){var t=setTimeout;return function(){return t(c,1)}}function c(){for(var t=0;t<Q;t+=2){(0,X[t])(X[t+1]),X[t]=void 0,X[t+1]=void 0}Q=0}function l(t,e){var n=arguments,o=this,i=new this.constructor(f);void 0===i[tt]&&A(i);var r=o._state;return r?function(){var t=n[r-1];U(function(){return P(r,i,t,o._result)})}():C(o,i,t,e),i}function d(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(f);return g(n,t),n}function f(){}function h(){return new TypeError("You cannot resolve a promise with itself")}function p(){return new TypeError("A promises callback cannot return that same promise.")}function m(t){try{return t.then}catch(t){return it.error=t,it}}function v(t,e,n,o){try{t.call(e,n,o)}catch(t){return t}}function y(t,e,n){U(function(t){var o=!1,i=v(n,e,function(n){o||(o=!0,e!==n?g(t,n):k(t,n))},function(e){o||(o=!0,S(t,e))},"Settle: "+(t._label||" unknown promise"));!o&&i&&(o=!0,S(t,i))},t)}function b(t,e){e._state===nt?k(t,e._result):e._state===ot?S(t,e._result):C(e,void 0,function(e){return g(t,e)},function(e){return S(t,e)})}function w(t,e,n){e.constructor===t.constructor&&n===l&&e.constructor.resolve===d?b(t,e):n===it?(S(t,it.error),it.error=null):void 0===n?k(t,e):i(n)?y(t,e,n):k(t,e)}function g(e,n){e===n?S(e,h()):t(n)?w(e,n,m(n)):k(e,n)}function _(t){t._onerror&&t._onerror(t._result),D(t)}function k(t,e){t._state===et&&(t._result=e,t._state=nt,0!==t._subscribers.length&&U(D,t))}function S(t,e){t._state===et&&(t._state=ot,t._result=e,U(_,t))}function C(t,e,n,o){var i=t._subscribers,r=i.length;t._onerror=null,i[r]=e,i[r+nt]=n,i[r+ot]=o,0===r&&t._state&&U(D,t)}function D(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var o=void 0,i=void 0,r=t._result,s=0;s<e.length;s+=3)o=e[s],i=e[s+n],o?P(n,o,i,r):i(r);t._subscribers.length=0}}function x(){this.error=null}function E(t,e){try{return t(e)}catch(t){return rt.error=t,rt}}function P(t,e,n,o){var r=i(n),s=void 0,u=void 0,a=void 0,c=void 0;if(r){if(s=E(n,o),s===rt?(c=!0,u=s.error,s.error=null):a=!0,e===s)return void S(e,p())}else s=o,a=!0;e._state!==et||(r&&a?g(e,s):c?S(e,u):t===nt?k(e,s):t===ot&&S(e,s))}function T(t,e){try{e(function(e){g(t,e)},function(e){S(t,e)})}catch(e){S(t,e)}}function O(){return st++}function A(t){t[tt]=st++,t._state=void 0,t._result=void 0,t._subscribers=[]}function M(t,e){this._instanceConstructor=t,this.promise=new t(f),this.promise[tt]||A(this.promise),I(e)?(this._input=e,this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?k(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&k(this.promise,this._result))):S(this.promise,q())}function q(){return new Error("Array Methods must be provided an Array")}function j(t){return new M(this,t).promise}function N(t){var e=this;return new e(I(t)?function(n,o){for(var i=t.length,r=0;r<i;r++)e.resolve(t[r]).then(n,o)}:function(t,e){return e(new TypeError("You must pass an array to race."))})}function H(t){var e=this,n=new e(f);return S(n,t),n}function L(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function W(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function V(t){this[tt]=O(),this._result=this._state=void 0,this._subscribers=[],f!==t&&("function"!=typeof t&&L(),this instanceof V?T(this,t):W())}function B(){var t=void 0;if(void 0!==o)t=o;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(t){throw new Error("polyfill failed because global object is unavailable in this environment")}var e=t.Promise;if(e){var n=null;try{n=Object.prototype.toString.call(e.resolve())}catch(t){}if("[object Promise]"===n&&!e.cast)return}t.Promise=V}var F=void 0;F=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var I=F,Q=0,R=void 0,z=void 0,U=function(t,e){X[Q]=t,X[Q+1]=e,2===(Q+=2)&&(z?z(c):Z())},Y="undefined"!=typeof window?window:void 0,K=Y||{},G=K.MutationObserver||K.WebKitMutationObserver,$="undefined"==typeof self&&void 0!==e&&"[object process]"==={}.toString.call(e),J="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,X=new Array(1e3),Z=void 0;Z=$?function(){return function(){return e.nextTick(c)}}():G?function(){var t=0,e=new G(c),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}():J?function(){var t=new MessageChannel;return t.port1.onmessage=c,function(){return t.port2.postMessage(0)}}():void 0===Y?function(){try{var t=n(9);return R=t.runOnLoop||t.runOnContext,u()}catch(t){return a()}}():a();var tt=Math.random().toString(36).substring(16),et=void 0,nt=1,ot=2,it=new x,rt=new x,st=0;return M.prototype._enumerate=function(){for(var t=this.length,e=this._input,n=0;this._state===et&&n<t;n++)this._eachEntry(e[n],n)},M.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,o=n.resolve;if(o===d){var i=m(t);if(i===l&&t._state!==et)this._settledAt(t._state,e,t._result);else if("function"!=typeof i)this._remaining--,this._result[e]=t;else if(n===V){var r=new n(f);w(r,t,i),this._willSettleAt(r,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(o(t),e)},M.prototype._settledAt=function(t,e,n){var o=this.promise;o._state===et&&(this._remaining--,t===ot?S(o,n):this._result[e]=n),0===this._remaining&&k(o,this._result)},M.prototype._willSettleAt=function(t,e){var n=this;C(t,void 0,function(t){return n._settledAt(nt,e,t)},function(t){return n._settledAt(ot,e,t)})},V.all=j,V.race=N,V.resolve=d,V.reject=H,V._setScheduler=r,V._setAsap=s,V._asap=U,V.prototype={constructor:V,then:l,catch:function(t){return this.then(null,t)}},V.polyfill=B,V.Promise=V,V})}).call(e,n(7),n(8))},function(t,e){},function(t,e,n){"use strict";function o(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var r=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}();n(5);var s=n(4),u=function(t){return t&&t.__esModule?t:{default:t}}(s),a=n(0),c=o(a),l=n(1),d=o(l),f=n(2),h=n(3),p=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return i(this,t),this.options=c.deepExtend({},d.Defaults,e),this.id=this.options.id||c.generateID("bar"),this.closeTimer=-1,this.barDom=null,this.layoutDom=null,this.progressDom=null,this.showing=!1,this.shown=!1,this.closed=!1,this.closing=!1,this.killable=this.options.timeout||this.options.closeWith.length>0,this.hasSound=this.options.sounds.sources.length>0,this.soundPlayed=!1,this.listeners={beforeShow:[],onShow:[],afterShow:[],onClose:[],afterClose:[],onHover:[],onTemplate:[]},this.promises={show:null,close:null},this.on("beforeShow",this.options.callbacks.beforeShow),this.on("onShow",this.options.callbacks.onShow),this.on("afterShow",this.options.callbacks.afterShow),this.on("onClose",this.options.callbacks.onClose),this.on("afterClose",this.options.callbacks.afterClose),this.on("onHover",this.options.callbacks.onHover),this.on("onTemplate",this.options.callbacks.onTemplate),this}return r(t,[{key:"on",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){};return"function"==typeof e&&this.listeners.hasOwnProperty(t)&&this.listeners[t].push(e),this}},{key:"show",value:function(){var e=this;if(!0!==this.options.killer||d.PageHidden)if("string"!=typeof this.options.killer||d.PageHidden){var n=d.getQueueCounts(this.options.queue);if(n.current>=n.maxVisible||d.PageHidden)return d.addToQueue(this),d.PageHidden&&this.hasSound&&c.inArray("docHidden",this.options.sounds.conditions)&&c.createAudioElements(this),d.PageHidden&&c.inArray("docHidden",this.options.titleCount.conditions)&&d.docTitle.increment(),this}else t.closeAll(this.options.killer);else t.closeAll();if(d.Store[this.id]=this,d.fire(this,"beforeShow"),this.showing=!0,this.closing)return this.showing=!1,this;if(d.build(this),d.handleModal(this),this.options.force?this.layoutDom.insertBefore(this.barDom,this.layoutDom.firstChild):this.layoutDom.appendChild(this.barDom),this.hasSound&&!this.soundPlayed&&c.inArray("docVisible",this.options.sounds.conditions)&&c.createAudioElements(this),c.inArray("docVisible",this.options.titleCount.conditions)&&d.docTitle.increment(),this.shown=!0,this.closed=!1,d.hasButtons(this)&&Object.keys(this.options.buttons).forEach(function(t){var n=e.barDom.querySelector("#"+e.options.buttons[t].id);c.addListener(n,"click",function(n){c.stopPropagation(n),e.options.buttons[t].cb()})}),this.progressDom=this.barDom.querySelector(".noty_progressbar"),c.inArray("click",this.options.closeWith)&&(c.addClass(this.barDom,"noty_close_with_click"),c.addListener(this.barDom,"click",function(t){c.stopPropagation(t),e.close()},!1)),c.addListener(this.barDom,"mouseenter",function(){d.fire(e,"onHover")},!1),this.options.timeout&&c.addClass(this.barDom,"noty_has_timeout"),c.inArray("button",this.options.closeWith)){c.addClass(this.barDom,"noty_close_with_button");var o=document.createElement("div");c.addClass(o,"noty_close_button"),o.innerHTML="×",this.barDom.appendChild(o),c.addListener(o,"click",function(t){c.stopPropagation(t),e.close()},!1)}return d.fire(this,"onShow"),null===this.options.animation.open?this.promises.show=new u.default(function(t){t()}):"function"==typeof this.options.animation.open?this.promises.show=new u.default(this.options.animation.open.bind(this)):(c.addClass(this.barDom,this.options.animation.open),this.promises.show=new u.default(function(t){c.addListener(e.barDom,c.animationEndEvents,function(){c.removeClass(e.barDom,e.options.animation.open),t()})})),this.promises.show.then(function(){var t=e;setTimeout(function(){d.openFlow(t)},100)}),this}},{key:"stop",value:function(){return d.dequeueClose(this),this}},{key:"resume",value:function(){return d.queueClose(this),this}},{key:"setTimeout",value:function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}(function(t){if(this.stop(),this.options.timeout=t,this.barDom){this.options.timeout?c.addClass(this.barDom,"noty_has_timeout"):c.removeClass(this.barDom,"noty_has_timeout");var e=this;setTimeout(function(){e.resume()},100)}return this})},{key:"setText",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.barDom&&(this.barDom.querySelector(".noty_body").innerHTML=t),e&&(this.options.text=t),this}},{key:"setType",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.barDom){c.classList(this.barDom).split(" ").forEach(function(t){"noty_type__"===t.substring(0,11)&&c.removeClass(e.barDom,t)}),c.addClass(this.barDom,"noty_type__"+t)}return n&&(this.options.type=t),this}},{key:"setTheme",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.barDom){c.classList(this.barDom).split(" ").forEach(function(t){"noty_theme__"===t.substring(0,12)&&c.removeClass(e.barDom,t)}),c.addClass(this.barDom,"noty_theme__"+t)}return n&&(this.options.theme=t),this}},{key:"close",value:function(){var t=this;return this.closed?this:this.shown?(d.fire(this,"onClose"),this.closing=!0,null===this.options.animation.close?this.promises.close=new u.default(function(t){t()}):"function"==typeof this.options.animation.close?this.promises.close=new u.default(this.options.animation.close.bind(this)):(c.addClass(this.barDom,this.options.animation.close),this.promises.close=new u.default(function(e){c.addListener(t.barDom,c.animationEndEvents,function(){t.options.force?c.remove(t.barDom):d.ghostFix(t),e()})})),this.promises.close.then(function(){d.closeFlow(t),d.handleModalClose(t)}),this.closed=!0,this):(d.removeFromQueue(this),this)}}],[{key:"closeAll",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Object.keys(d.Store).forEach(function(e){t?d.Store[e].options.queue===t&&d.Store[e].killable&&d.Store[e].close():d.Store[e].killable&&d.Store[e].close()}),this}},{key:"overrideDefaults",value:function(t){return d.Defaults=c.deepExtend({},d.Defaults,t),this}},{key:"setMaxVisible",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:d.DefaultMaxVisible,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"global";return d.Queues.hasOwnProperty(e)||(d.Queues[e]={maxVisible:t,queue:[]}),d.Queues[e].maxVisible=t,this}},{key:"button",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};return new f.NotyButton(t,e,n,o)}},{key:"version",value:function(){return"3.1.0"}},{key:"Push",value:function(t){return new h.Push(t)}}]),t}();e.default=p,c.visibilityChangeFlow(),t.exports=e.default},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function i(t){if(l===setTimeout)return setTimeout(t,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(t,0);try{return l(t,0)}catch(e){try{return l.call(null,t,0)}catch(e){return l.call(this,t,0)}}}function r(t){if(d===clearTimeout)return clearTimeout(t);if((d===o||!d)&&clearTimeout)return d=clearTimeout,clearTimeout(t);try{return d(t)}catch(e){try{return d.call(null,t)}catch(e){return d.call(this,t)}}}function s(){m&&h&&(m=!1,h.length?p=h.concat(p):v=-1,p.length&&u())}function u(){if(!m){var t=i(s);m=!0;for(var e=p.length;e;){for(h=p,p=[];++v<e;)h&&h[v].run();v=-1,e=p.length}h=null,m=!1,r(t)}}function a(t,e){this.fun=t,this.array=e}function c(){}var l,d,f=t.exports={};!function(){try{l="function"==typeof setTimeout?setTimeout:n}catch(t){l=n}try{d="function"==typeof clearTimeout?clearTimeout:o}catch(t){d=o}}();var h,p=[],m=!1,v=-1;f.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];p.push(new a(t,e)),1!==p.length||m||i(u)},a.prototype.run=function(){this.fun.apply(null,this.array)},f.title="browser",f.browser=!0,f.env={},f.argv=[],f.version="",f.versions={},f.on=c,f.addListener=c,f.once=c,f.off=c,f.removeListener=c,f.removeAllListeners=c,f.emit=c,f.binding=function(t){throw new Error("process.binding is not supported")},f.cwd=function(){return"/"},f.chdir=function(t){throw new Error("process.chdir is not supported")},f.umask=function(){return 0}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e){}])});
-//# sourceMappingURL=noty.min.js.map
\ No newline at end of file
diff --git a/data/web/json_api.php b/data/web/json_api.php
index 3d15d3f3..99dd1f16 100644
--- a/data/web/json_api.php
+++ b/data/web/json_api.php
@@ -356,18 +356,6 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
               return;
             }
           break;
-          case "csrf-cookie":
-            if (isset($_SESSION['mailcow_cc_username']) && isset($_SESSION['mailcow_cc_role'])) {
-              csrfprotector::refreshToken();
-              echo json_encode(array(
-                'type' => 'success',
-                'msg' => 'Cookie refreshed'
-              ));
-            }
-            else {
-              return;
-            }
-          break;
           default:
             echo '{}';
           break;
@@ -376,10 +364,10 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
       case "delete":
         switch ($category) {
           case "alias":
-            if (isset($_POST['address'])) {
-              $address = json_decode($_POST['address'], true);
-              if (is_array($address)) {
-                if (mailbox_delete_alias(array('address' => $address)) === false) {
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (mailbox_delete_alias(array('address' => $items)) === false) {
                   if (isset($_SESSION['return'])) {
                     echo json_encode($_SESSION['return']);
                   }
@@ -389,25 +377,38 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
                       'msg' => 'Deletion of items/s failed'
                     ));
                   }
-                  exit();
-                }
-                if (isset($_SESSION['return'])) {
-                  echo json_encode($_SESSION['return']);
                 }
                 else {
-                  echo json_encode(array(
-                    'type' => 'success',
-                    'msg' => 'Item/s deleted: ' . $domains
-                  ));
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
                 }
               }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find address array in post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find items in post data'
+              ));
             }
           break;
           case "fwdhost":
-            if (isset($_POST['forwardinghost'])) {
-              $forwardinghost = (array)json_decode($_POST['forwardinghost'], true);
-              if (is_array($forwardinghost)) {
-                if (delete_forwarding_host(array('forwardinghost' => $forwardinghost)) === false) {
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (delete_forwarding_host(array('forwardinghost' => $items)) === false) {
                   if (isset($_SESSION['return'])) {
                     echo json_encode($_SESSION['return']);
                   }
@@ -417,31 +418,38 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
                       'msg' => 'Deletion of items/s failed'
                     ));
                   }
-                  exit();
-                }
-                if (isset($_SESSION['return'])) {
-                  echo json_encode($_SESSION['return']);
                 }
                 else {
-                  echo json_encode(array(
-                    'type' => 'success',
-                    'msg' => 'Item/s deleted: ' . $domains
-                  ));
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
                 }
               }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find forwardinghost array in post data'
+                ));
+              }
             }
             else {
               echo json_encode(array(
                 'type' => 'error',
-                'msg' => 'Cannot find forwardinghost array in post data'
+                'msg' => 'Cannot find items in post data'
               ));
             }
           break;
           case "dkim":
-            if (isset($_POST['domains'])) {
-              $domains = (array)json_decode($_POST['domains'], true);
-              if (is_array($domains)) {
-                if (dkim_delete_key(array('domains' => $domains)) === false) {
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (dkim_delete_key(array('domains' => $items)) === false) {
                   if (isset($_SESSION['return'])) {
                     echo json_encode($_SESSION['return']);
                   }
@@ -451,23 +459,194 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
                       'msg' => 'Deletion of items/s failed'
                     ));
                   }
-                  exit();
                 }
-                if (isset($_SESSION['return'])) {
-                  echo json_encode($_SESSION['return']);
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find domains array in post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find items in post data'
+              ));
+            }
+          break;
+          case "domain":
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (mailbox_delete_domain(array('domain' => $items)) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Task failed'
+                    ));
+                  }
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find domain array in post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find items in post data'
+              ));
+            }
+          break;
+          case "alias-domain":
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (mailbox_delete_alias_domain(array('alias_domain' => $items)) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Task failed'
+                    ));
+                  }
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find alias_domain array in post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find items in post data'
+              ));
+            }
+          break;
+          case "mailbox":
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (mailbox_delete_mailbox(array('username' => $items)) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Task failed'
+                    ));
+                  }
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find username array in post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find items in post data'
+              ));
+            }
+          break;
+          case "resource":
+            if (isset($_POST['items'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              if (is_array($items)) {
+                if (mailbox_delete_resource(array('name' => $items)) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Task failed'
+                    ));
+                  }
                 }
                 else {
-                  echo json_encode(array(
-                    'type' => 'success',
-                    'msg' => 'Item/s deleted: ' . $domains
-                  ));
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
                 }
               }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Cannot find name array in post data'
+                ));
+              }
             }
             else {
               echo json_encode(array(
                 'type' => 'error',
-                'msg' => 'Cannot find domains array in post data'
+                'msg' => 'Cannot find items in post data'
               ));
             }
           break;
@@ -476,26 +655,222 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
       case "edit":
         switch ($category) {
           case "alias":
-            if (isset($_POST['address']) && isset($_POST['active'])) {
-              $address = (array)json_decode($_POST['address'], true);
-              if (is_array($address)) {
-                if (mailbox_edit_alias(array('address' => $address, 'active' => ($_POST['active'] == "1") ? $active = 1 : null)) === false) {
-                  echo json_encode(array(
-                    'type' => 'error',
-                    'msg' => 'Edit item failed'
-                  ));
+            if (isset($_POST['items']) && isset($_POST['attr'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              $attr = (array)json_decode($_POST['attr'], true);
+              $postarray = array_merge(array('address' => $items), $attr);
+              if (is_array($postarray['address'])) {
+                if (mailbox_edit_alias($postarray) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Edit failed'
+                    ));
+                  }
+                  exit();
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Incomplete post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Incomplete post data'
+              ));
+            }
+          break;
+          case "mailbox":
+            if (isset($_POST['items']) && isset($_POST['attr'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              $attr = (array)json_decode($_POST['attr'], true);
+              $postarray = array_merge(array('username' => $items), $attr);
+              if (is_array($postarray['username'])) {
+                if (mailbox_edit_mailbox($postarray) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Edit failed'
+                    ));
+                  }
+                  exit();
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Incomplete post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Incomplete post data'
+              ));
+            }
+          break;
+          case "resource":
+            if (isset($_POST['items']) && isset($_POST['attr'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              $attr = (array)json_decode($_POST['attr'], true);
+              $postarray = array_merge(array('name' => $items), $attr);
+              if (is_array($postarray['name'])) {
+                if (mailbox_edit_resource($postarray) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Edit failed'
+                    ));
+                  }
                   exit();
                 }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Incomplete post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Incomplete post data'
+              ));
+            }
+          break;
+          case "domain":
+            if (isset($_POST['items']) && isset($_POST['attr'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              $attr = (array)json_decode($_POST['attr'], true);
+              $postarray = array_merge(array('domain' => $items), $attr);
+              if (is_array($postarray['domain'])) {
+                if (mailbox_edit_domain($postarray) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Edit failed'
+                    ));
+                  }
+                  exit();
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
+                echo json_encode(array(
+                  'type' => 'error',
+                  'msg' => 'Incomplete post data'
+                ));
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Incomplete post data'
+              ));
+            }
+          break;
+          case "alias-domain":
+            if (isset($_POST['items']) && isset($_POST['attr'])) {
+              $items = (array)json_decode($_POST['items'], true);
+              $attr = (array)json_decode($_POST['attr'], true);
+              $postarray = array_merge(array('alias_domain' => $items), $attr);
+              if (is_array($postarray['alias_domain'])) {
+                if (mailbox_edit_alias_domain($postarray) === false) {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'error',
+                      'msg' => 'Edit failed'
+                    ));
+                  }
+                  exit();
+                }
+                else {
+                  if (isset($_SESSION['return'])) {
+                    echo json_encode($_SESSION['return']);
+                  }
+                  else {
+                    echo json_encode(array(
+                      'type' => 'success',
+                      'msg' => 'Task completed'
+                    ));
+                  }
+                }
+              }
+              else {
                 echo json_encode(array(
-                  'type' => 'success',
-                  'msg' => 'Task completed'
+                  'type' => 'error',
+                  'msg' => 'Incomplete post data'
                 ));
               }
             }
             else {
               echo json_encode(array(
                 'type' => 'error',
-                'msg' => 'Cannot find address array in post data'
+                'msg' => 'Incomplete post data'
               ));
             }
           break;
diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php
index bc254ccb..d1a8300d 100644
--- a/data/web/lang/lang.de.php
+++ b/data/web/lang/lang.de.php
@@ -70,12 +70,12 @@ $lang['danger']['login_failed'] = 'Anmeldung fehlgeschlagen';
 $lang['danger']['mailbox_invalid'] = 'Mailboxname ist ungültig';
 $lang['danger']['resource_invalid'] = 'Ressourcenname ist ungültig';
 $lang['danger']['description_invalid'] = 'Ressourcenbeschreibung ist ungültig';
-$lang['danger']['mailbox_invalid_suggest'] = 'Mailboxname ist ungültig, meinten Sie vielleicht "%s"?';
+$lang['danger']['mailbox_invalid_suggest'] = 'Mailboxname ist ungültig, meinten Sie vielleicht %s?';
 $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 "%s" 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']['max_alias_exceeded'] = 'Anzahl an Alias-Adressen überschritten';
 $lang['danger']['mailbox_quota_exceeded'] = 'Speicherplatz überschreitet das Limit (max. %d MiB)';
diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php
index af500355..f562d498 100644
--- a/data/web/lang/lang.en.php
+++ b/data/web/lang/lang.en.php
@@ -77,7 +77,7 @@ $lang['danger']['is_alias'] = "%s is already known as an alias address";
 $lang['danger']['is_alias_or_mailbox'] = "%s is already known as an alias or a mailbox";
 $lang['danger']['is_spam_alias'] = "%s is already known as a spam alias address";
 $lang['danger']['quota_not_0_not_numeric'] = "Quota must be numeric and >= 0";
-$lang['danger']['domain_not_found'] = "Domain not found.";
+$lang['danger']['domain_not_found'] = 'Domain "%s" not found';
 $lang['danger']['max_mailbox_exceeded'] = "Max. mailboxes exceeded (%d of %d)";
 $lang['danger']['max_alias_exceeded'] = 'Max. aliases exceeded';
 $lang['danger']['mailbox_quota_exceeded'] = "Quota exceeds the domain limit (max. %d MiB)";
diff --git a/data/web/mailbox.php b/data/web/mailbox.php
index 864ea676..e35a3601 100644
--- a/data/web/mailbox.php
+++ b/data/web/mailbox.php
@@ -31,16 +31,28 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
             <?php
             if ($_SESSION['mailcow_cc_role'] == "admin"):
             ?>
-              <a href="/add.php?domain"><span class="glyphicon glyphicon-plus"></span></a>
+            <a href="/add.php?domain"><span class="glyphicon glyphicon-plus"></span></a></li>
             <?php
             endif;
             ?>
             </div>
-            <h3 class="panel-title"><?=$lang['mailbox']['domains'];?></h3>
+            <?=$lang['mailbox']['domains'];?>
             </div>
             <div class="table-responsive">
               <table id="domain_table" class="table table-striped"></table>
             </div>
+            <div class="mass-actions-mailbox">
+              <div class="btn-group">
+                <a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
+                <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
+                <ul class="dropdown-menu">
+                  <li><a id="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
+                  <li><a id="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
+                  <li role="separator" class="divider"></li>
+                  <li><a id="delete_selected" data-id="domain" data-api-url='delete/domain' href="#"><?=$lang['mailbox']['remove'];?></a></li>
+                </ul>
+              </div>
+            </div>
             <span class="footer-add-item"><a href="/add.php?domain"><?=$lang['mailbox']['add_domain'];?></a></span>
           </div>
         </div>
@@ -56,6 +68,18 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
             <div class="table-responsive">
               <table id="mailbox_table" class="table table-striped"></table>
             </div>
+            <div class="mass-actions-mailbox">
+              <div class="btn-group">
+                <a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="mailbox" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
+                <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
+                <ul class="dropdown-menu">
+                  <li><a id="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
+                  <li><a id="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
+                  <li role="separator" class="divider"></li>
+                  <li><a id="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#"><?=$lang['mailbox']['remove'];?></a></li>
+                </ul>
+              </div>
+            </div>
             <span class="footer-add-item"><a href="/add.php?mailbox"><?=$lang['mailbox']['add_mailbox'];?></a></span>
           </div>
         </div>
@@ -71,6 +95,18 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
             <div class="table-responsive">
               <table id="resources_table" class="table table-striped"></table>
             </div>
+            <div class="mass-actions-mailbox">
+              <div class="btn-group">
+                <a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="resource" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
+                <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
+                <ul class="dropdown-menu">
+                  <li><a id="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
+                  <li><a id="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
+                  <li role="separator" class="divider"></li>
+                  <li><a id="delete_selected" data-id="resource" data-api-url='delete/resource' href="#"><?=$lang['mailbox']['remove'];?></a></li>
+                </ul>
+              </div>
+            </div>
             <span class="footer-add-item"><a href="/add.php?resource"><?=$lang['mailbox']['add_resource'];?></a></span>
           </div>
         </div>
@@ -86,6 +122,18 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
             <div class="table-responsive">
               <table id="aliasdomain_table" class="table table-striped"></table>
             </div>
+            <div class="mass-actions-mailbox">
+              <div class="btn-group">
+                <a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="alias-domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
+                <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
+                <ul class="dropdown-menu">
+                  <li><a id="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
+                  <li><a id="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
+                  <li role="separator" class="divider"></li>
+                  <li><a id="delete_selected" data-id="alias-domain" data-api-url='delete/alias-domain' href="#"><?=$lang['mailbox']['remove'];?></a></li>
+                </ul>
+              </div>
+            </div>
             <span class="footer-add-item"><a href="/add.php?aliasdomain"><?=$lang['mailbox']['add_domain_alias'];?></a></span>
           </div>
         </div>
@@ -99,18 +147,19 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
             <div class="table-responsive">
               <table id="alias_table" class="table table-striped"></table>
             </div>
-            <div class="mass-actions">
-              <p id="select_all_aliases" class="mass-select-all">
-                ↪ <?=$lang['mailbox']['toggle_all'];?>
-              </p>
-            </div>
-            <div class="footer-add-item">
-              <a class="pull-right" href="/add.php?alias"><span class="glyphicon glyphicon-plus"></span></a>
-              <b><?=$lang['mailbox']['quick_actions'];?>:</b>
-              <a id="delete_selected_alias" href="#" class="mass-each-action"><?=$lang['mailbox']['remove'];?></a> |
-              <a id="activate_selected_alias" href="#" class="mass-each-action"><?=$lang['mailbox']['activate'];?></a> |
-              <a id="deactivate_selected_alias" href="#" class="mass-each-action"><?=$lang['mailbox']['deactivate'];?></a>
+            <div class="mass-actions-mailbox">
+              <div class="btn-group">
+                <a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="alias" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
+                <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
+                <ul class="dropdown-menu">
+                  <li><a id="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"1","active1":"12"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
+                  <li><a id="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
+                  <li role="separator" class="divider"></li>
+                  <li><a id="delete_selected" data-id="alias" data-api-url='delete/alias' href="#"><?=$lang['mailbox']['remove'];?></a></li>
+                </ul>
+              </div>
             </div>
+            <span class="footer-add-item"><a href="/add.php?alias"><?=$lang['mailbox']['add_alias'];?></a></span>
           </div>
         </div>
 
diff --git a/data/web/user.php b/data/web/user.php
index ec25dc94..d5c75abc 100644
--- a/data/web/user.php
+++ b/data/web/user.php
@@ -382,18 +382,20 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
 	</div>
 	<div role="tabpanel" class="tab-pane" id="TLSPolicy">
 		<form class="form-horizontal" role="form" method="post">
+      <input type="hidden" value="0" name="tls_in">
+      <input type="hidden" value="0" name="tls_out">
 			<p class="help-block"><?=$lang['user']['tls_policy_warning'];?></p>
 			<div class="form-group">
 				<div class="col-sm-6">
 					<div class="checkbox">
 						<h4><span class="glyphicon glyphicon-download" aria-hidden="true"></span> <?=$lang['user']['tls_enforce_in'];?></h4>
-						<input type="checkbox" id="tls_in" name="tls_in" <?=($get_tls_policy['tls_enforce_in'] == "1") ? "checked" : null;?> data-on-text="<?=$lang['user']['on'];?>" data-off-text="<?=$lang['user']['off'];?>">
+						<input type="checkbox" value="1" id="tls_in" name="tls_in" <?=($get_tls_policy['tls_enforce_in'] == "1") ? "checked" : null;?> data-on-text="<?=$lang['user']['on'];?>" data-off-text="<?=$lang['user']['off'];?>">
 					</div>
 				</div>
 				<div class="col-sm-6">
 					<div class="checkbox">
 						<h4><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?=$lang['user']['tls_enforce_out'];?></h4>
-						<input type="checkbox" id="tls_out" name="tls_out" <?=($get_tls_policy['tls_enforce_out'] == "1") ? "checked" : null;?> data-on-text="<?=$lang['user']['on'];?>" data-off-text="<?=$lang['user']['off'];?>">
+						<input type="checkbox" value="1" id="tls_out" name="tls_out" <?=($get_tls_policy['tls_enforce_out'] == "1") ? "checked" : null;?> data-on-text="<?=$lang['user']['on'];?>" data-off-text="<?=$lang['user']['off'];?>">
 					</div>
 				</div>
 			</div>