diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php
index 3d73591293355563458e3b2052dd3ac35da6dfdf..12440105af55fa94451bde61d5854402f35ed336 100644
--- a/install/lib/installer_base.lib.php
+++ b/install/lib/installer_base.lib.php
@@ -3850,6 +3850,10 @@ class installer_base {
 			$root_cron_jobs[] = "0 0 * * * ".$install_dir."/server/scripts/create_daily_nginx_access_logs.sh &> /dev/null";
 		}
 
+		if ($conf['services']['mail'] == 1) {
+			$root_cron_jobs[] = "30 23 * * * ".$install_dir."/server/scripts/handle_mailbox_soft_deleted.sh &> /dev/null";
+		}
+
 		foreach($root_cron_jobs as $cron_job) {
 			if(!in_array($cron_job."\n", $existing_root_cron_jobs)) {
 				$existing_root_cron_jobs[] = $cron_job."\n";
diff --git a/install/sql/incremental/upd_dev_collection.sql b/install/sql/incremental/upd_dev_collection.sql
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c99596926b399b22291c617dc1479211de493ea7 100644
--- a/install/sql/incremental/upd_dev_collection.sql
+++ b/install/sql/incremental/upd_dev_collection.sql
@@ -0,0 +1 @@
+ALTER TABLE `sys_user` ADD `otp_type` SET('none', 'email') NOT NULL DEFAULT 'none' AFTER `lost_password_reqtime`, ADD `otp_data` VARCHAR(255) NULL AFTER `otp_type`, ADD `otp_recovery` VARCHAR(64) NULL AFTER `otp_data`, ADD `otp_attempts` TINYINT NOT NULL DEFAULT '0' AFTER `otp_recovery`;
diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql
index ec6596bc779e4274d5612273e5f9fa96fd9a27cd..cf340bda0170cb77039941455303d76ee28066ca 100644
--- a/install/sql/ispconfig3.sql
+++ b/install/sql/ispconfig3.sql
@@ -1842,6 +1842,10 @@ CREATE TABLE `sys_user` (
   `lost_password_function` tinyint(1) NOT NULL default '1',
   `lost_password_hash` VARCHAR(50) NOT NULL default '',
   `lost_password_reqtime` DATETIME NULL default NULL,
+  `otp_type` set('none', 'email') NOT NULL DEFAULT 'none',
+  `otp_data` varchar(255) DEFAULT NULL,
+  `otp_recovery` varchar(64) DEFAULT NULL,
+  `otp_attempts` tinyint(4) NOT NULL DEFAULT 0,
   PRIMARY KEY  (`userid`)
 ) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
 
diff --git a/install/tpl/debian6_dovecot-sql.conf.master b/install/tpl/debian6_dovecot-sql.conf.master
index 32a25c995de7f3ac0d739bc7272434d5176b0ffd..d0b5269e13fc8519b1a41d6608c2ae2495421fdb 100644
--- a/install/tpl/debian6_dovecot-sql.conf.master
+++ b/install/tpl/debian6_dovecot-sql.conf.master
@@ -1,13 +1,4 @@
 # http://wiki.dovecot.org/AuthDatabase/SQL
-#
-# CREATE TABLE users (
-#     userid VARCHAR(128) NOT NULL,
-#     password VARCHAR(64) NOT NULL,
-#     home VARCHAR(255) NOT NULL,
-#     uid INTEGER NOT NULL,
-#     gid INTEGER NOT NULL,
-#     active CHAR(1) DEFAULT 'Y' NOT NULL
-# );
 
 driver = mysql
 connect = host={mysql_server_host} dbname={mysql_server_database} user={mysql_server_ispconfig_user} password={mysql_server_ispconfig_password} port={mysql_server_port}
@@ -20,4 +11,4 @@ user_query = SELECT email as user, maildir as home, CONCAT( maildir_format, ':',
 
 # The iterate_query is required for the doveadm command only and works only on dovecot 2 servers.
 # Do not enable it on Dovecot 1.x servers
-# iterate_query = SELECT email as user FROM mail_user WHERE server_id = '{server_id}'
+# iterate_query = SELECT email as user FROM mail_user WHERE disabledoveadm='n' AND server_id = '{server_id}'
diff --git a/install/tpl/debian_dovecot-sql.conf.master b/install/tpl/debian_dovecot-sql.conf.master
index f067d6ba108dc547ab48d6c1e11eea1557fc72d8..d0b5269e13fc8519b1a41d6608c2ae2495421fdb 100644
--- a/install/tpl/debian_dovecot-sql.conf.master
+++ b/install/tpl/debian_dovecot-sql.conf.master
@@ -1,120 +1,4 @@
-# This file is opened as root, so it should be owned by root and mode 0600.
-#
 # http://wiki.dovecot.org/AuthDatabase/SQL
-#
-# For the sql passdb module, you'll need a database with a table that
-# contains fields for at least the userid and password. If you want to
-# use the user@domain syntax, you might want to have a separate domain
-# field as well.
-#
-# If your users all have the same uig/gid, and have predictable home
-# directories, you can use the static userdb module to generate the home
-# dir based on the userid and domain. In this case, you won't need fields
-# for home, uid, or gid in the database.
-#
-# If you prefer to use the sql userdb module, you'll want to add fields
-# for home, uid, and gid. Here is an example table:
-#
-# CREATE TABLE users (
-#     userid VARCHAR(128) NOT NULL,
-#     password VARCHAR(64) NOT NULL,
-#     home VARCHAR(255) NOT NULL,
-#     uid INTEGER NOT NULL,
-#     gid INTEGER NOT NULL,
-#     active CHAR(1) DEFAULT 'Y' NOT NULL
-# );
-
-# Database driver: mysql, pgsql, sqlite
-#driver = 
-
-# Database connection string. This is driver-specific setting.
-#
-# pgsql:
-#   For available options, see the PostgreSQL documention for the
-#   PQconnectdb function of libpq.
-#
-# mysql:
-#   Basic options emulate PostgreSQL option names:
-#     host, port, user, password, dbname
-#
-#   But also adds some new settings:
-#     client_flags        - See MySQL manual
-#     ssl_ca, ssl_ca_path - Set either one or both to enable SSL
-#     ssl_cert, ssl_key   - For sending client-side certificates to server
-#     ssl_cipher          - Set minimum allowed cipher security (default: HIGH)
-# 
-#   You can connect to UNIX sockets by using host: host=/var/run/mysqld/mysqld.sock
-#   Note that currently you can't use spaces in parameters.
-#
-# sqlite:
-#   The path to the database file.
-#
-# Examples:
-#   connect = host=192.168.1.1 dbname=users
-#   connect = host=sql.example.com dbname=virtual user=virtual password=blarg
-#   connect = /etc/dovecot/authdb.sqlite
-#
-#connect = dbname=virtual user=virtual
-
-# Default password scheme.
-#
-# List of supported schemes is in
-# http://wiki.dovecot.org/Authentication/PasswordSchemes
-#
-#default_pass_scheme = PLAIN-MD5
-
-# Query to retrieve the password.
-#
-# This query must return only one row with "user" and "password" columns.
-# The query can also return other fields which have a special meaning, see
-# http://wiki.dovecot.org/PasswordDatabase/ExtraFields
-#
-# The "user" column is needed to make sure the username gets used with exactly
-# the same casing as it's in the database. Note that if you store username and
-# domain in separate fields, you most likely want to return a combination of
-# them as the "user" column, otherwise the domain gets stripped.
-#
-# Commonly used available substitutions (see
-# http://wiki.dovecot.org/Variables for full list):
-#   %u = entire userid
-#   %n = user part of user@domain
-#   %d = domain part of user@domain
-# 
-# Note that these can be used only as input to SQL query. If the query outputs
-# any of these substitutions, they're not touched. Otherwise it would be
-# difficult to have eg. usernames containing '%' characters.
-#
-# Example:
-#   password_query = SELECT concat(userid, '@', domain) AS user, password FROM users WHERE userid = '%n' AND domain = '%d'
-#   password_query = SELECT pw AS password FROM users WHERE userid = '%u' AND active = 'Y'
-#
-#password_query = SELECT userid as user, password FROM users WHERE userid = '%u'
-
-# Query to retrieve the user information.
-#
-# The query must return only one row. Commonly returned columns are:
-#   uid - System UID
-#   gid - System GID
-#   home - Home directory
-#   mail - Mail location
-#
-# Either home or mail is required. uid and gid are required. If more than one
-# row is returned or there are missing fields, the login will fail. For a list
-# of all fields that can be returned, see 
-# http://wiki.dovecot.org/UserDatabase/ExtraFields
-#
-# Examples
-#   user_query = SELECT home, uid, gid FROM users WHERE userid = '%n' AND domain = '%d'
-#   user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u'
-#   user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u'
-#
-#user_query = SELECT home, uid, gid FROM users WHERE userid = '%u'
-
-# If you wish to avoid two SQL lookups (passdb + userdb), you can use
-# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll
-# also have to return userdb fields in password_query prefixed with "userdb_"
-# string. For example:
-#password_query = SELECT userid as user, password, home as userdb_home, uid as userdb_uid, gid as userdb_gid FROM users WHERE userid = '%u'
 
 driver = mysql
 connect = host={mysql_server_host} dbname={mysql_server_database} user={mysql_server_ispconfig_user} password={mysql_server_ispconfig_password} port={mysql_server_port}
@@ -127,5 +11,4 @@ user_query = SELECT email as user, maildir as home, CONCAT( maildir_format, ':',
 
 # The iterate_query is required for the doveadm command only and works only on dovecot 2 servers.
 # Do not enable it on Dovecot 1.x servers
-# iterate_query = SELECT email as user FROM mail_user WHERE server_id = '{server_id}'
-
+# iterate_query = SELECT email as user FROM mail_user WHERE disabledoveadm='n' AND server_id = '{server_id}'
diff --git a/install/tpl/fedora_dovecot-sql.conf.master b/install/tpl/fedora_dovecot-sql.conf.master
index bac4c9d13d9955027a403c08781b054547794565..d0b5269e13fc8519b1a41d6608c2ae2495421fdb 100644
--- a/install/tpl/fedora_dovecot-sql.conf.master
+++ b/install/tpl/fedora_dovecot-sql.conf.master
@@ -1,133 +1,4 @@
-# This file is opened as root, so it should be owned by root and mode 0600.
-#
 # http://wiki.dovecot.org/AuthDatabase/SQL
-#
-# For the sql passdb module, you'll need a database with a table that
-# contains fields for at least the username and password. If you want to
-# use the user@domain syntax, you might want to have a separate domain
-# field as well.
-#
-# If your users all have the same uig/gid, and have predictable home
-# directories, you can use the static userdb module to generate the home
-# dir based on the username and domain. In this case, you won't need fields
-# for home, uid, or gid in the database.
-#
-# If you prefer to use the sql userdb module, you'll want to add fields
-# for home, uid, and gid. Here is an example table:
-#
-# CREATE TABLE users (
-#     username VARCHAR(128) NOT NULL,
-#     domain VARCHAR(128) NOT NULL,
-#     password VARCHAR(64) NOT NULL,
-#     home VARCHAR(255) NOT NULL,
-#     uid INTEGER NOT NULL,
-#     gid INTEGER NOT NULL,
-#     active CHAR(1) DEFAULT 'Y' NOT NULL
-# );
-
-# Database driver: mysql, pgsql, sqlite
-#driver = 
-
-# Database connection string. This is driver-specific setting.
-#
-# pgsql:
-#   For available options, see the PostgreSQL documention for the
-#   PQconnectdb function of libpq.
-#
-# mysql:
-#   Basic options emulate PostgreSQL option names:
-#     host, port, user, password, dbname
-#
-#   But also adds some new settings:
-#     client_flags        - See MySQL manual
-#     ssl_ca, ssl_ca_path - Set either one or both to enable SSL
-#     ssl_cert, ssl_key   - For sending client-side certificates to server
-#     ssl_cipher          - Set minimum allowed cipher security (default: HIGH)
-#     option_file         - Read options from the given file instead of
-#                           the default my.cnf location
-#     option_group        - Read options from the given group (default: client)
-# 
-#   You can connect to UNIX sockets by using host: host=/var/run/mysql.sock
-#   Note that currently you can't use spaces in parameters.
-#
-#   MySQL supports multiple host parameters for load balancing / HA.
-#
-# sqlite:
-#   The path to the database file.
-#
-# Examples:
-#   connect = host=192.168.1.1 dbname=users
-#   connect = host=sql.example.com dbname=virtual user=virtual password=blarg
-#   connect = /etc/dovecot/authdb.sqlite
-#
-#connect =
-
-# Default password scheme.
-#
-# List of supported schemes is in
-# http://wiki.dovecot.org/Authentication/PasswordSchemes
-#
-#default_pass_scheme = MD5
-
-# passdb query to retrieve the password. It can return fields:
-#   password - The user's password. This field must be returned.
-#   user - user@domain from the database. Needed with case-insensitive lookups.
-#   username and domain - An alternative way to represent the "user" field.
-#
-# The "user" field is often necessary with case-insensitive lookups to avoid
-# e.g. "name" and "nAme" logins creating two different mail directories. If
-# your user and domain names are in separate fields, you can return "username"
-# and "domain" fields instead of "user".
-#
-# The query can also return other fields which have a special meaning, see
-# http://wiki.dovecot.org/PasswordDatabase/ExtraFields
-#
-# Commonly used available substitutions (see http://wiki.dovecot.org/Variables
-# for full list):
-#   %u = entire user@domain
-#   %n = user part of user@domain
-#   %d = domain part of user@domain
-# 
-# Note that these can be used only as input to SQL query. If the query outputs
-# any of these substitutions, they're not touched. Otherwise it would be
-# difficult to have eg. usernames containing '%' characters.
-#
-# Example:
-#   password_query = SELECT userid AS user, pw AS password \
-#     FROM users WHERE userid = '%u' AND active = 'Y'
-#
-#password_query = \
-#  SELECT username, domain, password \
-#  FROM users WHERE username = '%n' AND domain = '%d'
-
-# userdb query to retrieve the user information. It can return fields:
-#   uid - System UID (overrides mail_uid setting)
-#   gid - System GID (overrides mail_gid setting)
-#   home - Home directory
-#   mail - Mail location (overrides mail_location setting)
-#
-# None of these are strictly required. If you use a single UID and GID, and
-# home or mail directory fits to a template string, you could use userdb static
-# instead. For a list of all fields that can be returned, see
-# http://wiki.dovecot.org/UserDatabase/ExtraFields
-#
-# Examples:
-#   user_query = SELECT home, uid, gid FROM users WHERE userid = '%u'
-#   user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u'
-#   user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u'
-#
-#user_query = \
-#  SELECT home, uid, gid \
-#  FROM users WHERE username = '%n' AND domain = '%d'
-
-# If you wish to avoid two SQL lookups (passdb + userdb), you can use
-# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll
-# also have to return userdb fields in password_query prefixed with "userdb_"
-# string. For example:
-#password_query = \
-#  SELECT userid AS user, password, \
-#    home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \
-#  FROM users WHERE userid = '%u'
 
 driver = mysql
 connect = host={mysql_server_host} dbname={mysql_server_database} user={mysql_server_ispconfig_user} password={mysql_server_ispconfig_password} port={mysql_server_port}
@@ -140,4 +11,4 @@ user_query = SELECT email as user, maildir as home, CONCAT( maildir_format, ':',
 
 # The iterate_query is required for the doveadm command only and works only on dovecot 2 servers.
 # Do not enable it on Dovecot 1.x servers
-# iterate_query = SELECT email as user FROM mail_user WHERE server_id = '{server_id}'
+# iterate_query = SELECT email as user FROM mail_user WHERE disabledoveadm='n' AND server_id = '{server_id}'
diff --git a/install/tpl/opensuse_dovecot-sql.conf.master b/install/tpl/opensuse_dovecot-sql.conf.master
index bac4c9d13d9955027a403c08781b054547794565..d0b5269e13fc8519b1a41d6608c2ae2495421fdb 100644
--- a/install/tpl/opensuse_dovecot-sql.conf.master
+++ b/install/tpl/opensuse_dovecot-sql.conf.master
@@ -1,133 +1,4 @@
-# This file is opened as root, so it should be owned by root and mode 0600.
-#
 # http://wiki.dovecot.org/AuthDatabase/SQL
-#
-# For the sql passdb module, you'll need a database with a table that
-# contains fields for at least the username and password. If you want to
-# use the user@domain syntax, you might want to have a separate domain
-# field as well.
-#
-# If your users all have the same uig/gid, and have predictable home
-# directories, you can use the static userdb module to generate the home
-# dir based on the username and domain. In this case, you won't need fields
-# for home, uid, or gid in the database.
-#
-# If you prefer to use the sql userdb module, you'll want to add fields
-# for home, uid, and gid. Here is an example table:
-#
-# CREATE TABLE users (
-#     username VARCHAR(128) NOT NULL,
-#     domain VARCHAR(128) NOT NULL,
-#     password VARCHAR(64) NOT NULL,
-#     home VARCHAR(255) NOT NULL,
-#     uid INTEGER NOT NULL,
-#     gid INTEGER NOT NULL,
-#     active CHAR(1) DEFAULT 'Y' NOT NULL
-# );
-
-# Database driver: mysql, pgsql, sqlite
-#driver = 
-
-# Database connection string. This is driver-specific setting.
-#
-# pgsql:
-#   For available options, see the PostgreSQL documention for the
-#   PQconnectdb function of libpq.
-#
-# mysql:
-#   Basic options emulate PostgreSQL option names:
-#     host, port, user, password, dbname
-#
-#   But also adds some new settings:
-#     client_flags        - See MySQL manual
-#     ssl_ca, ssl_ca_path - Set either one or both to enable SSL
-#     ssl_cert, ssl_key   - For sending client-side certificates to server
-#     ssl_cipher          - Set minimum allowed cipher security (default: HIGH)
-#     option_file         - Read options from the given file instead of
-#                           the default my.cnf location
-#     option_group        - Read options from the given group (default: client)
-# 
-#   You can connect to UNIX sockets by using host: host=/var/run/mysql.sock
-#   Note that currently you can't use spaces in parameters.
-#
-#   MySQL supports multiple host parameters for load balancing / HA.
-#
-# sqlite:
-#   The path to the database file.
-#
-# Examples:
-#   connect = host=192.168.1.1 dbname=users
-#   connect = host=sql.example.com dbname=virtual user=virtual password=blarg
-#   connect = /etc/dovecot/authdb.sqlite
-#
-#connect =
-
-# Default password scheme.
-#
-# List of supported schemes is in
-# http://wiki.dovecot.org/Authentication/PasswordSchemes
-#
-#default_pass_scheme = MD5
-
-# passdb query to retrieve the password. It can return fields:
-#   password - The user's password. This field must be returned.
-#   user - user@domain from the database. Needed with case-insensitive lookups.
-#   username and domain - An alternative way to represent the "user" field.
-#
-# The "user" field is often necessary with case-insensitive lookups to avoid
-# e.g. "name" and "nAme" logins creating two different mail directories. If
-# your user and domain names are in separate fields, you can return "username"
-# and "domain" fields instead of "user".
-#
-# The query can also return other fields which have a special meaning, see
-# http://wiki.dovecot.org/PasswordDatabase/ExtraFields
-#
-# Commonly used available substitutions (see http://wiki.dovecot.org/Variables
-# for full list):
-#   %u = entire user@domain
-#   %n = user part of user@domain
-#   %d = domain part of user@domain
-# 
-# Note that these can be used only as input to SQL query. If the query outputs
-# any of these substitutions, they're not touched. Otherwise it would be
-# difficult to have eg. usernames containing '%' characters.
-#
-# Example:
-#   password_query = SELECT userid AS user, pw AS password \
-#     FROM users WHERE userid = '%u' AND active = 'Y'
-#
-#password_query = \
-#  SELECT username, domain, password \
-#  FROM users WHERE username = '%n' AND domain = '%d'
-
-# userdb query to retrieve the user information. It can return fields:
-#   uid - System UID (overrides mail_uid setting)
-#   gid - System GID (overrides mail_gid setting)
-#   home - Home directory
-#   mail - Mail location (overrides mail_location setting)
-#
-# None of these are strictly required. If you use a single UID and GID, and
-# home or mail directory fits to a template string, you could use userdb static
-# instead. For a list of all fields that can be returned, see
-# http://wiki.dovecot.org/UserDatabase/ExtraFields
-#
-# Examples:
-#   user_query = SELECT home, uid, gid FROM users WHERE userid = '%u'
-#   user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u'
-#   user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u'
-#
-#user_query = \
-#  SELECT home, uid, gid \
-#  FROM users WHERE username = '%n' AND domain = '%d'
-
-# If you wish to avoid two SQL lookups (passdb + userdb), you can use
-# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll
-# also have to return userdb fields in password_query prefixed with "userdb_"
-# string. For example:
-#password_query = \
-#  SELECT userid AS user, password, \
-#    home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \
-#  FROM users WHERE userid = '%u'
 
 driver = mysql
 connect = host={mysql_server_host} dbname={mysql_server_database} user={mysql_server_ispconfig_user} password={mysql_server_ispconfig_password} port={mysql_server_port}
@@ -140,4 +11,4 @@ user_query = SELECT email as user, maildir as home, CONCAT( maildir_format, ':',
 
 # The iterate_query is required for the doveadm command only and works only on dovecot 2 servers.
 # Do not enable it on Dovecot 1.x servers
-# iterate_query = SELECT email as user FROM mail_user WHERE server_id = '{server_id}'
+# iterate_query = SELECT email as user FROM mail_user WHERE disabledoveadm='n' AND server_id = '{server_id}'
diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master
index 8799e1f34c7efec3ec6e375659ea31b1ef31f833..7c371a217168daccacdedd378f76b4b532367bb6 100644
--- a/install/tpl/server.ini.master
+++ b/install/tpl/server.ini.master
@@ -56,10 +56,12 @@ relayhost_user=
 relayhost_password=
 mailbox_size_limit=0
 message_size_limit=0
+mailbox_soft_delete=n
 mailbox_quota_stats=y
 realtime_blackhole_list=zen.spamhaus.org
 overquota_notify_threshold=90
 overquota_notify_admin=y
+overquota_notify_reseller=y
 overquota_notify_client=y
 overquota_notify_freq=7
 overquota_notify_onok=n
@@ -103,6 +105,7 @@ enable_sni=y
 skip_le_check=n
 enable_ip_wildcard=y
 overtraffic_notify_admin=y
+overtraffic_notify_reseller=y
 overtraffic_notify_client=y
 nginx_cgi_socket=/var/run/fcgiwrap.socket
 php_fpm_init_script=php5-fpm
@@ -121,10 +124,12 @@ php_ini_check_minutes=1
 overtraffic_disable_web=y
 overquota_notify_threshold=90
 overquota_notify_admin=y
+overquota_notify_reseller=y
 overquota_notify_client=y
 overquota_notify_freq=7
 overquota_db_notify_threshold=90
 overquota_db_notify_admin=y
+overquota_db_notify_reseller=y
 overquota_db_notify_client=y
 overquota_notify_onok=n
 logging=yes
diff --git a/interface/lib/app.inc.php b/interface/lib/app.inc.php
old mode 100755
new mode 100644
index 96e8a1ddef0892b1ca35186ea08d263af75b21be..6a8e563d80fade4e9ccb9482004017b8e6149c5e
--- a/interface/lib/app.inc.php
+++ b/interface/lib/app.inc.php
@@ -212,6 +212,12 @@ class app {
 		}
 	}
 
+	public function auth_log($msg) {
+		$authlog_handle = fopen($this->_conf['ispconfig_log_dir'].'/auth.log', 'a');
+		fwrite($authlog_handle, $msg . PHP_EOL);
+		fclose($authlog_handle);
+	}
+
 	/** Priority values are: 0 = DEBUG, 1 = WARNING,  2 = ERROR */
 	public function error($msg, $next_link = '', $stop = true, $priority = 1) {
 		//$this->uses("error");
diff --git a/interface/lib/classes/remote.d/client.inc.php b/interface/lib/classes/remote.d/client.inc.php
index 5af1592db9347d60932f5f05b44b27d2274a6d05..b5a0b421d72869b74809b0140ca791ae812a62fb 100644
--- a/interface/lib/classes/remote.d/client.inc.php
+++ b/interface/lib/classes/remote.d/client.inc.php
@@ -397,6 +397,8 @@ class remoting_client extends remoting {
 			return false;
 		}
 
+		// DUPLICATE CODE IN interface/web/client/client_del.php
+
 		$client_id = $app->functions->intval($client_id);
 
 		if($client_id > 0) {
@@ -413,7 +415,7 @@ class remoting_client extends remoting {
 			$app->db->query("DELETE FROM sys_user WHERE client_id = ?", $client_id);
 
 			//* Delete all records (sub-clients, mail, web, etc....)  of this client.
-			$tables = 'cron,dns_rr,dns_soa,dns_slave,ftp_user,mail_access,mail_content_filter,mail_domain,mail_forwarding,mail_get,mail_user,mail_user_filter,shell_user,spamfilter_users,support_message,web_database,web_database_user,web_domain,web_traffic,domain,mail_mailinglist,client,spamfilter_wblist';
+			$tables = 'cron,dns_rr,dns_soa,dns_slave,ftp_user,mail_access,mail_content_filter,mail_forwarding,mail_get,mail_user,mail_user_filter,shell_user,spamfilter_users,mail_domain,support_message,web_database,web_database_user,web_domain,web_traffic,domain,mail_mailinglist,client,spamfilter_wblist';
 			$tables_array = explode(',', $tables);
 			$client_group_id = $app->functions->intval($client_group['groupid']);
 			if($client_group_id > 1) {
diff --git a/interface/lib/classes/remote.d/mail.inc.php b/interface/lib/classes/remote.d/mail.inc.php
index cad598043593bdddb82befe954ab665e428b2528..dfbad2759581518228cdd5f3805c6421ace0e652 100644
--- a/interface/lib/classes/remote.d/mail.inc.php
+++ b/interface/lib/classes/remote.d/mail.inc.php
@@ -196,6 +196,24 @@ class remoting_mail extends remoting {
 		return $app->remoting_lib->getDataRecord($primary_id);
 	}
 
+	//* Get mail user details for all account that belong to a client.
+	public function mail_user_get_all_by_client($session_id, $client_id)
+	{
+		global $app;
+
+		if(!$this->checkPerm($session_id, 'mail_user_get_all_by_client')) {
+			throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
+			return false;
+		}
+		$app->uses('remoting_lib');
+		$sql = "SELECT u.* FROM `mail_user` u
+			LEFT JOIN `sys_group` g ON (u.sys_groupid=g.groupid)
+			WHERE g.client_id=?";
+		$params[] = $client_id;
+
+		$result = $app->db->queryAllRecords($sql, true, $params);
+		return $result;
+	}
 
 	//* Add mail domain
 	public function mail_user_add($session_id, $client_id, $params){
@@ -1110,4 +1128,4 @@ class remoting_mail extends remoting {
 
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/interface/lib/lang/ar.lng b/interface/lib/lang/ar.lng
index c2bc19a6b9f483c11d8fe2e5bcc48ac2af5ef109..4aa87ee5aa3b5095ab8f4b233811930e515e6921 100644
--- a/interface/lib/lang/ar.lng
+++ b/interface/lib/lang/ar.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/bg.lng b/interface/lib/lang/bg.lng
index e0a0bfcdaba846f50de030d2bc1c07d7849eb154..67c2b67b6f8cab74042d96a0cab6d4310679c7e3 100644
--- a/interface/lib/lang/bg.lng
+++ b/interface/lib/lang/bg.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Неограничен';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/br.lng b/interface/lib/lang/br.lng
index 7e78ddaf364953e5d0f567aa6bf63384c8ef513b..02f4697deeb4a34dc94a71989ba7723a44355ce2 100644
--- a/interface/lib/lang/br.lng
+++ b/interface/lib/lang/br.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Ilimitado';
 $wb['server_id_0_error_txt'] = 'Por favor, selecione um servidor válido. O ID do servidor deve ser > 0.';
 $wb['datalog_changes_close_txt'] = 'Fechar';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/ca.lng b/interface/lib/lang/ca.lng
index 308aba545bfb2fffbfdb63b2076988f51e91f7fa..0aa69997e543e3fe4f1c576310343bb6fdf5028a 100644
--- a/interface/lib/lang/ca.lng
+++ b/interface/lib/lang/ca.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Illimité';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/cz.lng b/interface/lib/lang/cz.lng
index 84ce72a4c0bc98a423932e90904306ee9256fcf4..1eccd3c8e58331dacddc1d05852f694a911f2a6b 100644
--- a/interface/lib/lang/cz.lng
+++ b/interface/lib/lang/cz.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Neomezený';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/de.lng b/interface/lib/lang/de.lng
index 38e9c2b40c04df1deaea832f89681ea96ed1b5d2..d6cef498d367270e0b33722c9ebd20a401cf9ee2 100644
--- a/interface/lib/lang/de.lng
+++ b/interface/lib/lang/de.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'unlimitiert';
 $wb['server_id_0_error_txt'] = 'Bitte Server auswählen. Server ID muss > als 0 sein.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/dk.lng b/interface/lib/lang/dk.lng
index de52b0e704f00f5c6b9d1808ff09ad6845203aa7..85cee5865942261351b84e04021edd9674a25ac2 100644
--- a/interface/lib/lang/dk.lng
+++ b/interface/lib/lang/dk.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Ubegrænset';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/el.lng b/interface/lib/lang/el.lng
index 42d991401d696eeef8a1b9e0ed9720438ac70884..d5b980722a43d7c111428445a15eabb9ccea7154 100644
--- a/interface/lib/lang/el.lng
+++ b/interface/lib/lang/el.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Απεριόριστα';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/en.lng b/interface/lib/lang/en.lng
index 57c8d1f79f88ac69ced6a397e5bb5dd8fe7d5806..6024cc69a74e74c977e80715f9e1e787c63e057b 100644
--- a/interface/lib/lang/en.lng
+++ b/interface/lib/lang/en.lng
@@ -174,3 +174,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/es.lng b/interface/lib/lang/es.lng
index 2d120a2b97603a0d962508aa425e9158272c4baf..e3ba1d41e067e1246daf7105810cc817328a27e9 100644
--- a/interface/lib/lang/es.lng
+++ b/interface/lib/lang/es.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Ilimitado';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Cerrar';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/fi.lng b/interface/lib/lang/fi.lng
index 7974914e0e9eab89775f76fdbad6febbbaa166f9..87f2dc24edd263eb58ecd961aa5ed5b4c2896d02 100644
--- a/interface/lib/lang/fi.lng
+++ b/interface/lib/lang/fi.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/fr.lng b/interface/lib/lang/fr.lng
index b4bb837e7df140a132009910c64221a5ab227d3c..7f8413d11c1a2b5906deff3033755a3c594dd932 100644
--- a/interface/lib/lang/fr.lng
+++ b/interface/lib/lang/fr.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Illimité';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/hr.lng b/interface/lib/lang/hr.lng
index bef42f1814ce5d93bc603c69d31b3cb630b7faeb..167073f837b63bf9d3058507ab26d7f22549ff7c 100644
--- a/interface/lib/lang/hr.lng
+++ b/interface/lib/lang/hr.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'neograničeno';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/hu.lng b/interface/lib/lang/hu.lng
index e3913462fe0adc3a0152e4c39425d62bfb634dbf..a07c6810ce77c10add4de441f6008e2eee732b0c 100644
--- a/interface/lib/lang/hu.lng
+++ b/interface/lib/lang/hu.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Korlátlan';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/id.lng b/interface/lib/lang/id.lng
index aea01a061486780e671c2d12e03f1e95cc18b866..51e1fd6aef00388230029ca8f704d1bb1361fc30 100644
--- a/interface/lib/lang/id.lng
+++ b/interface/lib/lang/id.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Tak terbatas';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/it.lng b/interface/lib/lang/it.lng
index ff08d6f6337a6fdf84ed4b6befc103344e12b1e1..a56224e6d538b545f1758be32789cf37095a348c 100644
--- a/interface/lib/lang/it.lng
+++ b/interface/lib/lang/it.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'illimitati';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Chiudi';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/ja.lng b/interface/lib/lang/ja.lng
index 7235de393e3c7d4a7878eeb13554b791f048084f..00db30317075d490d0b6d8e1b502e217f8260990 100644
--- a/interface/lib/lang/ja.lng
+++ b/interface/lib/lang/ja.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/nl.lng b/interface/lib/lang/nl.lng
index 54e7045e612ff200bad7be702f0ddd74141f3e29..582c5ffe53b222ce8bd434d025bef88826de011f 100644
--- a/interface/lib/lang/nl.lng
+++ b/interface/lib/lang/nl.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Ongelimiteerd';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Sluiten';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Kopieer naar klembord';
+?>
diff --git a/interface/lib/lang/pl.lng b/interface/lib/lang/pl.lng
index ccd3347324793d50ead081987c6f3d1c49ee55ba..d22b0d485029a8c681b298d0865b883bd5e2c57a 100644
--- a/interface/lib/lang/pl.lng
+++ b/interface/lib/lang/pl.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'nielimitowane';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/pt.lng b/interface/lib/lang/pt.lng
index e2dc2f72acba3a877f0463fff46f38b4931641c1..23b1cd2079584cfbe6798026b6e59c02535b15cb 100644
--- a/interface/lib/lang/pt.lng
+++ b/interface/lib/lang/pt.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/ro.lng b/interface/lib/lang/ro.lng
index 6a9f596a0b74fd64d85099ce0f8b3ed941421407..b4da89bc12e4b077a1e871ac3c1257b3dbd0a87d 100644
--- a/interface/lib/lang/ro.lng
+++ b/interface/lib/lang/ro.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/ru.lng b/interface/lib/lang/ru.lng
index dca0c7a53e4cb9fc8cfaf82529d6fb6f9358efe8..cfd805010b094c43689cfdf9f79e42ef72c9c1f3 100644
--- a/interface/lib/lang/ru.lng
+++ b/interface/lib/lang/ru.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Безлимитный';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/se.lng b/interface/lib/lang/se.lng
index 2d3c38fd3892654599a4b616b23755062d4d70b0..03d818ec560ddd2eb9c2d95c00740a28466de0cb 100644
--- a/interface/lib/lang/se.lng
+++ b/interface/lib/lang/se.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Obegränsat';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/sk.lng b/interface/lib/lang/sk.lng
index d8e06d1ab3a1c024260ee1fc3fed89f00f35d8e8..dfad74552bff2a6ae80935dccd92be7fcc27624d 100644
--- a/interface/lib/lang/sk.lng
+++ b/interface/lib/lang/sk.lng
@@ -173,3 +173,5 @@ $wb['unlimited_txt'] = 'Unlimited';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/lib/lang/tr.lng b/interface/lib/lang/tr.lng
index ec5f1bfd930ecd2d3de74f48b3ddcb48f3440511..5b7afc3afa7b5db68f82763be2f092ed1178afda 100644
--- a/interface/lib/lang/tr.lng
+++ b/interface/lib/lang/tr.lng
@@ -174,3 +174,5 @@ $wb['unlimited_txt'] = 'Sınırsız';
 $wb['server_id_0_error_txt'] = 'Please select a valid Server. Server ID must be > 0.';
 $wb['datalog_changes_close_txt'] = 'Close';
 $wb['non_admin_error'] = 'Requires administrator level permissions';
+$wb['copy_to_clipboard_txt'] = 'Copy to clipboard';
+?>
diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php
index 185fa892c86a62f9d531a4e7d983ace5ff068185..bede61a3ddde653c85f7581940b2cb19a31c25ff 100644
--- a/interface/web/admin/form/server_config.tform.php
+++ b/interface/web/admin/form/server_config.tform.php
@@ -734,6 +734,12 @@ $form["tabs"]['mail'] = array(
 			'default' => 'y',
 			'value' => array(0 => 'n', 1 => 'y')
 		),
+		'mailbox_soft_delete' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'n',
+			'value' => array(0 => 'n', 1 => 'y')
+		),
 		'mailbox_quota_stats' => array (
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
@@ -758,6 +764,12 @@ $form["tabs"]['mail'] = array(
 			'default' => 'y',
 			'value' => array(0 => 'n', 1 => 'y')
 		),
+		'overquota_notify_reseller' => array(
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'y',
+			'value' => array(0 => 'n', 1 => 'y')
+		),
 		'overquota_notify_client' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
@@ -1082,6 +1094,12 @@ $form["tabs"]['web'] = array(
 			'default' => 'y',
 			'value' => array(0 => 'n', 1 => 'y')
 		),
+		'overtraffic_notify_reseller' => array(
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'y',
+			'value' => array(0 => 'n', 1 => 'y')
+		),
 		'overtraffic_notify_client' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
@@ -1112,6 +1130,12 @@ $form["tabs"]['web'] = array(
 			'default' => 'y',
 			'value' => array(0 => 'n', 1 => 'y')
 		),
+		'overquota_notify_reseller' => array(
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'y',
+			'value' => array(0 => 'n', 1 => 'y')
+		),
 		'overquota_notify_client' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
@@ -1136,6 +1160,12 @@ $form["tabs"]['web'] = array(
 			'default' => 'y',
 			'value' => array(0 => 'n', 1 => 'y')
 		),
+		'overquota_db_notify_reseller' => array(
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'y',
+			'value' => array(0 => 'n', 1 => 'y')
+		),
 		'overquota_db_notify_client' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
diff --git a/interface/web/admin/form/users.tform.php b/interface/web/admin/form/users.tform.php
index 1aab0a42985bb8b28932393366e4de14d67f8aa2..bc77087e2852c71d10f416e559b23291ab86b243 100644
--- a/interface/web/admin/form/users.tform.php
+++ b/interface/web/admin/form/users.tform.php
@@ -94,6 +94,11 @@ while ($file = @readdir($handle)) {
 	}
 }
 
+$otp_method_list = array(
+	'none' => 'none',
+	'email' => 'email',
+);
+
 //* Load themes
 $themes_list = array();
 $handle = @opendir(ISPC_THEMES_PATH);
@@ -254,6 +259,25 @@ $form['tabs']['users'] = array (
 			'rows'  => '',
 			'cols'  => ''
 		),
+		'otp_type' => array(
+				'datatype' => 'VARCHAR',
+				'formtype' => 'SELECT',
+				'validators' => array (  0 => array (    'type' => 'NOTEMPTY',
+						'errmsg'=> 'otp_auth_empty'),
+					1 => array (    'type' => 'REGEX',
+						'regex' => '/^[a-z0-9\_]{0,64}$/',
+						'errmsg'=> 'otp_auth_regex'),
+					),
+				'regex'  => '',
+				'errmsg' => '',
+				'default' => '',
+				'value'  => $otp_method_list,
+				'separator' => '',
+				'width'  => '30',
+				'maxlength' => '255',
+				'rows'  => '',
+				'cols'  => ''
+				),
 		'language' => array (
 			'datatype' => 'VARCHAR',
 			'formtype' => 'SELECT',
diff --git a/interface/web/admin/lib/lang/ar_server_config.lng b/interface/web/admin/lib/lang/ar_server_config.lng
index 58e7833fd6ef457ecb796e7099df3dc8db778497..a58dbaaf442c274b590cbd7727519b9b22977c44 100644
--- a/interface/web/admin/lib/lang/ar_server_config.lng
+++ b/interface/web/admin/lib/lang/ar_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/ar_users.lng b/interface/web/admin/lib/lang/ar_users.lng
index 369d56559510f445a96d40969035f4cbfde07ca5..d4acbf4e807d1a9ad740c14e6c5bfbdd12d1d594 100644
--- a/interface/web/admin/lib/lang/ar_users.lng
+++ b/interface/web/admin/lib/lang/ar_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/bg_server_config.lng b/interface/web/admin/lib/lang/bg_server_config.lng
index 0d87a4daa0fbd6d6416e187a5501422d89d54035..c856e7640f22a2ff2403c35f690ad969c44ffbf5 100644
--- a/interface/web/admin/lib/lang/bg_server_config.lng
+++ b/interface/web/admin/lib/lang/bg_server_config.lng
@@ -192,12 +192,14 @@ $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attribu
 $wb['website_autoalias_txt'] = 'Website auto alias';
 $wb['website_autoalias_note_txt'] = 'Placeholders:';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/bg_users.lng b/interface/web/admin/lib/lang/bg_users.lng
index a7d669bd2284be54fffb0e9c9f7be1989db24aac..3bd134b40ba3fd2b52502329e1e409dac4f5f4fe 100644
--- a/interface/web/admin/lib/lang/bg_users.lng
+++ b/interface/web/admin/lib/lang/bg_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/br_server_config.lng b/interface/web/admin/lib/lang/br_server_config.lng
index e749dcc0235250e07f77b135dc19302b7cdd8554..1041676ceb8e7768b22f4fad64451671ba6596fd 100644
--- a/interface/web/admin/lib/lang/br_server_config.lng
+++ b/interface/web/admin/lib/lang/br_server_config.lng
@@ -199,12 +199,14 @@ $wb['mailbox_quota_stats_txt'] = 'Estatísticas das cotas para contas de email';
 $wb['enable_ip_wildcard_txt'] = 'Habilitar curingas IP (*)';
 $wb['web_folder_protection_txt'] = 'Tornar pastas Web imutáveis (atributos estendidos)';
 $wb['overtraffic_notify_admin_txt'] = 'Enviar notificação de tráfego excedido para o administrador';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Enviar notificação de tráfego excedido para o cliente';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Por favor, insira nomes de host válidos para RBLs.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Enviar alerta da cota para o administrador';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Enviar alerta da cota para o cliente';
 $wb['overquota_notify_onok_txt'] = 'Enviar mensagem da cota para o cliente';
 $wb['overquota_notify_freq_txt'] = 'Enviar alerta da cota a cada N dias';
@@ -229,6 +231,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Comando mount, se o diretório não está mon
 $wb['backup_delete_txt'] = 'Remover backups de domínios/site';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Enviar alerta da cota do Banco de Dados para o administrador';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Enviar alerta da cota do Banco de Dados para o cliente';
 $wb['monitor_system_updates_txt'] = 'Verificar por atualizações do sistema';
 $wb['php_handler_txt'] = 'Manipulador padrão PHP';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Usar links físicos é inseguro, mas eco
 $wb['jailkit_hardlinks_allow_txt'] = 'Permitir links físicos enjaulados';
 $wb['jailkit_hardlinks_no_txt'] = 'Não, remover arquivos de links físicos';
 $wb['jailkit_hardlinks_yes_txt'] = 'Sim, usar links físicos quando possível';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/br_users.lng b/interface/web/admin/lib/lang/br_users.lng
index 2e60a744c0c0ed605b0bfed34cd159495d57d490..022d723c97720740209c2897b0b80ab0854440be 100644
--- a/interface/web/admin/lib/lang/br_users.lng
+++ b/interface/web/admin/lib/lang/br_users.lng
@@ -38,3 +38,4 @@ $wb['startmodule_empty'] = 'O módulo inicial está vazio.';
 $wb['startmodule_regex'] = 'Caracteres inválidos no módulo inicial.';
 $wb['app_theme_empty'] = 'Tema está vazio.';
 $wb['app_theme_regex'] = 'Caracteres inválidos no tema.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
diff --git a/interface/web/admin/lib/lang/ca_server_config.lng b/interface/web/admin/lib/lang/ca_server_config.lng
index 50125cf334c1024a86b57e38c3c4adc38b5e39dd..3d4ad3a70ccccede67f36108b25e4b92961fef71 100644
--- a/interface/web/admin/lib/lang/ca_server_config.lng
+++ b/interface/web/admin/lib/lang/ca_server_config.lng
@@ -195,12 +195,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -225,6 +227,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounte
 $wb['backup_delete_txt'] = 'Delete backups on domain/website delete';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['monitor_system_updates_txt'] = 'Check for Linux updates';
 $wb['php_handler_txt'] = 'Default PHP Handler';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/ca_users.lng b/interface/web/admin/lib/lang/ca_users.lng
index 369d56559510f445a96d40969035f4cbfde07ca5..d4acbf4e807d1a9ad740c14e6c5bfbdd12d1d594 100644
--- a/interface/web/admin/lib/lang/ca_users.lng
+++ b/interface/web/admin/lib/lang/ca_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/cz_server_config.lng b/interface/web/admin/lib/lang/cz_server_config.lng
index 36d009dbcee76290d6fdd8ada60e252d2a0b0668..bdc1152cbc8fb47580f456932221a30c8567cc04 100644
--- a/interface/web/admin/lib/lang/cz_server_config.lng
+++ b/interface/web/admin/lib/lang/cz_server_config.lng
@@ -178,12 +178,14 @@ $wb['mailbox_quota_stats_txt'] = 'Statistika kvóty poštovní schránky';
 $wb['enable_ip_wildcard_txt'] = 'Aktivovat IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Při překročení limitu přenesených dat, poslat oznámení adminovi';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Při překročení limitu přenesených dat, poslat oznámení klientovi';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Poslat varování o překročení nebo vyčerpání kvót adminovi';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Poslat varování o překročení nebo vyčerpání kvót klientovi';
 $wb['overquota_notify_onok_txt'] = 'Poslat zprávu klientovi, že kvóta je již v pořádku';
 $wb['overquota_notify_freq_txt'] = 'Poslat varování o kvótách každý X dní';
@@ -275,6 +277,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounte
 $wb['backup_delete_txt'] = 'Odstranit zálohy pokud byla smazána doména/webové stránky';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Poslat varování o překročení nebo vyčerpání DB kvót adminovi';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Poslat varování o překročení nebo vyčerpání DB kvót klientovi';
 $wb['php_handler_txt'] = 'Výchozí PHP obslužná rutina';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'Ne, odstranit soubory s pevným odkazem';
 $wb['jailkit_hardlinks_yes_txt'] = 'Ano, pokud je to možné, použijte pevné odkazy';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/cz_users.lng b/interface/web/admin/lib/lang/cz_users.lng
index c973ea2f8044ee67504a22e3c6d8ca6422d32883..6ad957242a28ffa42c4929c4ada7b55f542949bd 100644
--- a/interface/web/admin/lib/lang/cz_users.lng
+++ b/interface/web/admin/lib/lang/cz_users.lng
@@ -38,3 +38,4 @@ $wb['startmodule_empty'] = 'Startmodule empty.';
 $wb['startmodule_regex'] = 'Invalid chars in Startmodule.';
 $wb['app_theme_empty'] = 'App theme empty.';
 $wb['app_theme_regex'] = 'Invalid chars in App theme.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
diff --git a/interface/web/admin/lib/lang/de_server_config.lng b/interface/web/admin/lib/lang/de_server_config.lng
index 2536731433f5154af62ddcf3b4bb1246fd3f476c..6dc7844c4cf8d1ec51c2bf17a7e5c31785935d86 100644
--- a/interface/web/admin/lib/lang/de_server_config.lng
+++ b/interface/web/admin/lib/lang/de_server_config.lng
@@ -198,12 +198,14 @@ $wb['mailbox_quota_stats_txt'] = 'E-Mailkonto Beschränkung Statistiken';
 $wb['enable_ip_wildcard_txt'] = 'IP Adressen Wildcard (*) aktivieren';
 $wb['web_folder_protection_txt'] = 'Webverzeichnis unveränderlich machen (erweiterte Attribute)';
 $wb['overtraffic_notify_admin_txt'] = 'Ãœberschreiten des Datentransfer Limits an den Administrator senden';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Ãœberschreiten des Datentransfer Limits an den Kunden senden';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Bitte geben Sie gültige RBL-Hostnamen an.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Quota-Warnungen an den Administrator senden';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Quota-Warnungen an den Kunden senden';
 $wb['overquota_notify_onok_txt'] = 'Meldung an den Kunden senden, wenn Belegung wieder ok';
 $wb['overquota_notify_freq_txt'] = 'Quota-Warnung alle X Tage versenden';
@@ -282,6 +284,7 @@ $wb['cron_wget_error_regex'] = 'Invalid cron wget path.';
 $wb['network_filesystem_txt'] = 'Netzwerk-Dateisystem';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Datenbank-Quota-Warnungen an den Administrator senden';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Datenbank-Quota-Warnungen an den Kunden senden';
 $wb['php_ini_check_minutes_txt'] = 'Prüfe php.ini alle X Minuten auf Änderungen';
 $wb['php_ini_check_minutes_error_empty'] = 'Bitte geben Sie einen Wert an, wie oft die php.ini auf Änderungen geprüft werden soll.';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/de_users.lng b/interface/web/admin/lib/lang/de_users.lng
index e52090dceaef804ea83f49f7deac564978dc7405..2747595da72aaf30b5f8beffa0bb233d8bb9bfbc 100644
--- a/interface/web/admin/lib/lang/de_users.lng
+++ b/interface/web/admin/lib/lang/de_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Der Benutzername darf nicht <b>web<b> oder <b
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Passwort vergessen Funktion steht zur Verfügung';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/dk_server_config.lng b/interface/web/admin/lib/lang/dk_server_config.lng
index e83fa0e09e6811556aa7a3c78093897b28523c1c..d7b081150d835177796a524cf2c7c4731a1edd3d 100644
--- a/interface/web/admin/lib/lang/dk_server_config.lng
+++ b/interface/web/admin/lib/lang/dk_server_config.lng
@@ -181,12 +181,14 @@ $wb['mailbox_quota_stats_txt'] = 'Postboks kvota statistik';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Gør web mapper immume (udvidede attributter)';
 $wb['overtraffic_notify_admin_txt'] = 'Send over-trafik meddelelse til admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send over-trafik meddelelse til kunde';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Angiv gyldige RBL værtsnavne.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send kvote advarsler til admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send kvote advarsler til kunde';
 $wb['overquota_notify_onok_txt'] = 'Send kvote ok meddelelse til kunde';
 $wb['overquota_notify_freq_txt'] = 'Send kvote advarsler X dage';
@@ -278,6 +280,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounte
 $wb['backup_delete_txt'] = 'Delete backups on domain/website delete';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/dk_users.lng b/interface/web/admin/lib/lang/dk_users.lng
index fa595ed18415832f257a8bcab11a6bdd0bfae91c..351cd091afce3513693700c8d09a8a704b9d65fb 100644
--- a/interface/web/admin/lib/lang/dk_users.lng
+++ b/interface/web/admin/lib/lang/dk_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Brugernavn må ikke være web eller web plus
 $wb['client_not_admin_err'] = 'En bruger der hører til en klient kan ikke indstilles til typen: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/el_server_config.lng b/interface/web/admin/lib/lang/el_server_config.lng
index c87c151f8cdfc05d65b237a0ae44a50e764bf325..40af42057f56a1edac7f89be55462fdbd0ef073d 100644
--- a/interface/web/admin/lib/lang/el_server_config.lng
+++ b/interface/web/admin/lib/lang/el_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounte
 $wb['backup_delete_txt'] = 'Delete backups on domain/website delete';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/el_users.lng b/interface/web/admin/lib/lang/el_users.lng
index 6d07d6632457fc5dc1d854d7243669fffbadfeb6..0b46b3a52247913458c777f15ec09637d11db65b 100644
--- a/interface/web/admin/lib/lang/el_users.lng
+++ b/interface/web/admin/lib/lang/el_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng
index 452f698fd7a53fdfc8d1d00d79d042b365f7b07b..748e4c6d581bd9c9533e5c7d00fe4bcad3ec75c7 100644
--- a/interface/web/admin/lib/lang/en_server_config.lng
+++ b/interface/web/admin/lib/lang/en_server_config.lng
@@ -205,12 +205,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -235,6 +237,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounte
 $wb['backup_delete_txt'] = 'Delete backups on domain/website delete';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['monitor_system_updates_txt'] = 'Check for Linux updates';
 $wb['php_handler_txt'] = 'Default PHP Handler';
@@ -345,3 +348,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/en_users.lng b/interface/web/admin/lib/lang/en_users.lng
index 88fa9430d3837b06fff7ee78535e1cd227e3f44f..855146d171063b86d81b3b2835090e266d9f5a1a 100644
--- a/interface/web/admin/lib/lang/en_users.lng
+++ b/interface/web/admin/lib/lang/en_users.lng
@@ -38,4 +38,5 @@ $wb['startmodule_empty'] = 'Startmodule empty.';
 $wb['startmodule_regex'] = 'Invalid chars in Startmodule.';
 $wb['app_theme_empty'] = 'App theme empty.';
 $wb['app_theme_regex'] = 'Invalid chars in App theme.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/es_server_config.lng b/interface/web/admin/lib/lang/es_server_config.lng
index 83b03af94cf53b1462f47cb667d2d4324094e42e..528dfe36afd0f2e36cf87a1894fcf4e243232956 100644
--- a/interface/web/admin/lib/lang/es_server_config.lng
+++ b/interface/web/admin/lib/lang/es_server_config.lng
@@ -191,15 +191,18 @@ $wb['nginx_vhost_conf_enabled_dir_txt'] = 'Directorio de configuración de host
 $wb['no_notifications_txt'] = 'Sin notificaciones';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Enviar advertencias de cuota de base de datos al administrador';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Enviar advertencias de cuota de base de datos a los clientes';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Enviar advertencias de cuota excedida al administrador';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Enviar advertencias de cuota excedida al cliente';
 $wb['overquota_notify_freq_note_txt'] = '0 = enviar mensaje solo una vez, sin volver a notificar';
 $wb['overquota_notify_freq_txt'] = 'Enviar advertencia de cuota cada X días';
 $wb['overquota_notify_onok_txt'] = 'Enviar al cliente información de cuota correcta';
 $wb['overtraffic_notify_admin_txt'] = 'Enviar notificación de tráfico sobrepasado al administrador';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Enviar notificación de tráfico sobrepasado al cliente';
 $wb['permissions_txt'] = 'Permisos';
 $wb['php_fpm_ini_path_error_empty'] = 'La ruta al archivo php.ini de PHP-FPM está vacío.';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/es_users.lng b/interface/web/admin/lib/lang/es_users.lng
index 5a06c7ed3e3a3319245b7f031391bed4879c2fa5..44c67b1832cc45f978d257efaa64eb49c26eaf09 100644
--- a/interface/web/admin/lib/lang/es_users.lng
+++ b/interface/web/admin/lib/lang/es_users.lng
@@ -34,4 +34,5 @@ $wb['username_txt'] = 'Nombre de usuario';
 $wb['username_unique'] = 'Ya existe un usuario con ese nombre de usuario.';
 $wb['vorname_txt'] = 'Primer nombre';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/fi_server_config.lng b/interface/web/admin/lib/lang/fi_server_config.lng
index 6bd628411b1145ef45f0d290a60cdd47b0ed89ed..906013f7858a1cc25e9c4cdbd0dbd3c7dbb089ac 100644
--- a/interface/web/admin/lib/lang/fi_server_config.lng
+++ b/interface/web/admin/lib/lang/fi_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/fi_users.lng b/interface/web/admin/lib/lang/fi_users.lng
index 1e5bb588559e0eb4577bc05a9eb65decd3a572ab..02bc863bb7f49e178a8645b39f53b2c5e4564e36 100644
--- a/interface/web/admin/lib/lang/fi_users.lng
+++ b/interface/web/admin/lib/lang/fi_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/fr_server_config.lng b/interface/web/admin/lib/lang/fr_server_config.lng
index 3d4bfb14cde4780f11b41292d891f5d23295118a..274c2b6804d2e4614db220eb40daeeaa33386c7f 100644
--- a/interface/web/admin/lib/lang/fr_server_config.lng
+++ b/interface/web/admin/lib/lang/fr_server_config.lng
@@ -180,12 +180,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -277,6 +279,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounte
 $wb['backup_delete_txt'] = 'Delete backups on domain/website delete';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/fr_users.lng b/interface/web/admin/lib/lang/fr_users.lng
index 0f50d10d67c97698be1a92ad9b7b49854c1f3736..5013698f16b97b52e29cb3dc21e6ce8592149c64 100644
--- a/interface/web/admin/lib/lang/fr_users.lng
+++ b/interface/web/admin/lib/lang/fr_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Le nom d\'utilisateur ne peut pas commencer p
 $wb['client_not_admin_err'] = 'Un utilisateur affilié à un client ne peut pas être changé en type admin';
 $wb['lost_password_function_txt'] = 'La fonction mot de passe oublié est disponible';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/hr_server_config.lng b/interface/web/admin/lib/lang/hr_server_config.lng
index 1f970f8638b0c7e545f5e93f6c6c5fab4e9e6f14..5d35d0d33f0f54f2d3db52e00a4d392d84adb9b0 100644
--- a/interface/web/admin/lib/lang/hr_server_config.lng
+++ b/interface/web/admin/lib/lang/hr_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Statistika limita sandučića';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['apps_vhost_enabled_txt'] = 'Apps-vhost enabled';
 $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/hr_users.lng b/interface/web/admin/lib/lang/hr_users.lng
index 3a7da2a422baea63b92c33b16d33c341b932117d..e317aa923a6fc456bc6380bb85bb9ae6e898e951 100644
--- a/interface/web/admin/lib/lang/hr_users.lng
+++ b/interface/web/admin/lib/lang/hr_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Korisničko ime ne može biti web ili web sa
 $wb['client_not_admin_err'] = 'Korisnik koji je u grupi klijenti ne može biti admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/hu_server_config.lng b/interface/web/admin/lib/lang/hu_server_config.lng
index 25d30c24515a24a0010ec852083a2b82e43299f7..74a5b15701a1cfe7e62aceae242b43380a60d3ce 100644
--- a/interface/web/admin/lib/lang/hu_server_config.lng
+++ b/interface/web/admin/lib/lang/hu_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/hu_users.lng b/interface/web/admin/lib/lang/hu_users.lng
index 6f1ded0b70b1a36c0744badc8fc6af0643ca78f1..dc1089b76fdb295707d737c7c973cbf7aa1812dd 100644
--- a/interface/web/admin/lib/lang/hu_users.lng
+++ b/interface/web/admin/lib/lang/hu_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/id_server_config.lng b/interface/web/admin/lib/lang/id_server_config.lng
index f6a54151f30aa69629b02bcde54503f6fe93c263..2419ee63f11e5c0de004df8184588a8640b1b4b4 100644
--- a/interface/web/admin/lib/lang/id_server_config.lng
+++ b/interface/web/admin/lib/lang/id_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/id_users.lng b/interface/web/admin/lib/lang/id_users.lng
index bc546d4df4e050b30ee5aeec15926a76e288139e..032613d1e543049aad7ffedd6ac1d4ee61c1a4d3 100644
--- a/interface/web/admin/lib/lang/id_users.lng
+++ b/interface/web/admin/lib/lang/id_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/it_server_config.lng b/interface/web/admin/lib/lang/it_server_config.lng
index 7d67123662c722bfd20962d11914acf4cc48a581..4d01d70b22a266f1f3be3472b759a01f2318597a 100644
--- a/interface/web/admin/lib/lang/it_server_config.lng
+++ b/interface/web/admin/lib/lang/it_server_config.lng
@@ -180,12 +180,14 @@ $wb['mailbox_quota_stats_txt'] = 'Statistiche Quota Casella di Posta';
 $wb['enable_ip_wildcard_txt'] = 'Abilita  IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Imposta cartelle sito in moaniera non modificabile (attributi estesi)';
 $wb['overtraffic_notify_admin_txt'] = 'Trasmetti notifiche superamento traffico ad admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Trasmetti notifiche superamento traffico al cliente';
 $wb['overtraffic_disable_web_txt'] = 'Disabilita i siti web che eccedono il limiti di traffico';
 $wb['rbl_error_regex'] = 'Per cortesia specificare nomi host RBL validi.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Trasmetti allarmi quota ad admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Trasmetti allarmi quota al cliente';
 $wb['overquota_notify_onok_txt'] = 'Trasmetti messaggio quota ok al cliente';
 $wb['overquota_notify_freq_txt'] = 'Trasmetti allarmi quota ogni X giorni';
@@ -276,6 +278,7 @@ $wb['v6_prefix_length'] = 'Prefisso troppo lungo secondo le regole IPv6';
 $wb['backup_dir_mount_cmd_txt'] = 'Comanda mount se la directory di backup non è montata';
 $wb['backup_delete_txt'] = 'Cancellare i backup alla cancellazione dei domini/siti web';
 $wb['overquota_db_notify_admin_txt'] = 'Invia avviso di quota DB all\'amministratore';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Invia avviso di quota DB al cliente';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -338,3 +341,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'L\'uso di hardlinks è meno sicuro però
 $wb['jailkit_hardlinks_allow_txt'] = 'Consenti hardlinks all\'interno di jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, rimuovi i file con hardlink';
 $wb['jailkit_hardlinks_yes_txt'] = 'Si, usa hardlinks se possibile';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/it_users.lng b/interface/web/admin/lib/lang/it_users.lng
index 2c5dbeda480b1c84f05caf7237c37e95edfda014..57a462394aa55abfe9f5c0e8c32c04a4b6b51d26 100644
--- a/interface/web/admin/lib/lang/it_users.lng
+++ b/interface/web/admin/lib/lang/it_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Il nome utente non può essere web o web+un n
 $wb['client_not_admin_err'] = 'Un utente che appartiene ad un cliente non può essere del tipo: admin';
 $wb['lost_password_function_txt'] = 'La funzione password dimenticata è disponibile';
 $wb['no_user_insert'] = 'CP-Utente di tipo -utente- viene aggiunto automaticamente quando aggiungi un cliente o un rivenditore.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/ja_server_config.lng b/interface/web/admin/lib/lang/ja_server_config.lng
index a78f0900d81481bd6a55a9e5db99becaae380af1..66d505562bf7ce665e7fcdd99a25778b2bf2a1f3 100644
--- a/interface/web/admin/lib/lang/ja_server_config.lng
+++ b/interface/web/admin/lib/lang/ja_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/ja_users.lng b/interface/web/admin/lib/lang/ja_users.lng
index 45b1faec67c05eadb93286c6826aa7153608c4b0..9786f8b57647670f316bd266fbc365923d480bde 100644
--- a/interface/web/admin/lib/lang/ja_users.lng
+++ b/interface/web/admin/lib/lang/ja_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/nl_server_config.lng b/interface/web/admin/lib/lang/nl_server_config.lng
index fc39a2a25683542b2a2b7504996775bacbb05ae4..8ea60a21a8149f93d439e81e914ac1d55a5b56cb 100644
--- a/interface/web/admin/lib/lang/nl_server_config.lng
+++ b/interface/web/admin/lib/lang/nl_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/nl_users.lng b/interface/web/admin/lib/lang/nl_users.lng
index e1e6609c27d5e998244b8db740709464d7c18ffe..9013af5901e530ef3654c209092a1086d343b780 100644
--- a/interface/web/admin/lib/lang/nl_users.lng
+++ b/interface/web/admin/lib/lang/nl_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = 'Twee-factor authenticatie';
 ?>
diff --git a/interface/web/admin/lib/lang/pl_server_config.lng b/interface/web/admin/lib/lang/pl_server_config.lng
index 4b838bd3ea3efbd9c9d247f0f2845cb3b83eff3a..c186f5d2a60f4651593689a5743ade0a44aabe45 100644
--- a/interface/web/admin/lib/lang/pl_server_config.lng
+++ b/interface/web/admin/lib/lang/pl_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Statystyki użycia skrzynek email';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Prześlij informacje o przekroczeniu transferu do admina';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Prześlij informacje o przekroczeniu transferu do klienta';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/pl_users.lng b/interface/web/admin/lib/lang/pl_users.lng
index f5439f4f5f5fe86dee7e7e7161be928071d6b4de..b879f671e298d52c7eb0b12136a074d5293fe35f 100644
--- a/interface/web/admin/lib/lang/pl_users.lng
+++ b/interface/web/admin/lib/lang/pl_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Nazwa użytkownika nie może być web lub web
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/pt_server_config.lng b/interface/web/admin/lib/lang/pt_server_config.lng
index d42a415958513eeb320e5cc77a8fcd4871e06f58..2e398500dbc950c85d9809fb52d88d84edacdce8 100644
--- a/interface/web/admin/lib/lang/pt_server_config.lng
+++ b/interface/web/admin/lib/lang/pt_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/pt_users.lng b/interface/web/admin/lib/lang/pt_users.lng
index 7522fb0270d615bcbe2e3d6197ab16baffce1d08..f1cf858176002e2589ad2ead532bbe05a6574ea9 100644
--- a/interface/web/admin/lib/lang/pt_users.lng
+++ b/interface/web/admin/lib/lang/pt_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/ro_server_config.lng b/interface/web/admin/lib/lang/ro_server_config.lng
index 81488177c015041ca0bca2488f99e4c98973c5ad..2756ae7acda0737e5cd50482bfdef5884611fdca 100644
--- a/interface/web/admin/lib/lang/ro_server_config.lng
+++ b/interface/web/admin/lib/lang/ro_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/ro_users.lng b/interface/web/admin/lib/lang/ro_users.lng
index 369d56559510f445a96d40969035f4cbfde07ca5..d4acbf4e807d1a9ad740c14e6c5bfbdd12d1d594 100644
--- a/interface/web/admin/lib/lang/ro_users.lng
+++ b/interface/web/admin/lib/lang/ro_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/ru_server_config.lng b/interface/web/admin/lib/lang/ru_server_config.lng
index bce96e9339a72100c11e5c6c13fcd04a18c4fd2e..2fbf9cf7d6e416f68ca60d6759ac47f94c242a3a 100644
--- a/interface/web/admin/lib/lang/ru_server_config.lng
+++ b/interface/web/admin/lib/lang/ru_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Статистика квоты почтово
 $wb['enable_ip_wildcard_txt'] = 'Включить IP подстановочный знак (*)';
 $wb['web_folder_protection_txt'] = 'Сделать веб-папки неизменяемыми (расширенные атрибуты)';
 $wb['overtraffic_notify_admin_txt'] = 'Присылать уведомление трафика администратору';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Присылать уведомление трафика клиенту';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Пожалуйста, укажите действительные имена хостов RBL.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Присылать предупреждения квоты администратору';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Присылать предупреждения квоты клиенту';
 $wb['overquota_notify_onok_txt'] = 'Присылать сообщение квоты ОК клиенту';
 $wb['overquota_notify_freq_txt'] = 'Присылать предупреждения квоты каждые Х дней';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Отключить мониторинг
 $wb['backup_dir_mount_cmd_txt'] = 'Выполните команду монтирования, если каталог резервного копирования не установлен';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Присылать предупреждения квоты DB администратору';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Присылать предупреждения квоты DB клиенту';
 $wb['php_handler_txt'] = 'Обработчик PHP по умолчанию';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/ru_users.lng b/interface/web/admin/lib/lang/ru_users.lng
index d805b939116e50996d59f9ef73103b98476a69c0..5d67479d701ba0f83803f00a81a8e1a3c2bb0d7f 100644
--- a/interface/web/admin/lib/lang/ru_users.lng
+++ b/interface/web/admin/lib/lang/ru_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Имя пользователя не може
 $wb['client_not_admin_err'] = 'Пользователь, который принадлежит к клиенту не может быть установлен тип: admin';
 $wb['lost_password_function_txt'] = 'Функция восстановления пароля доступна';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/se_server_config.lng b/interface/web/admin/lib/lang/se_server_config.lng
index 4f8d24411785d3b608c600a4e8e6995eba60cd6a..e21017769cbec9fca8e56a5db4e53da3f50cb0ff 100644
--- a/interface/web/admin/lib/lang/se_server_config.lng
+++ b/interface/web/admin/lib/lang/se_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/se_users.lng b/interface/web/admin/lib/lang/se_users.lng
index 60f3829adc9237e5453a4bbe9029e58f2bada62f..a8baa7ee79886fdcd1cb201adef121b9637e42c0 100644
--- a/interface/web/admin/lib/lang/se_users.lng
+++ b/interface/web/admin/lib/lang/se_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Användarnamnet får inte vara web  eller web
 $wb['client_not_admin_err'] = 'En användare som tillhör en kund kan inte sättas som admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/sk_server_config.lng b/interface/web/admin/lib/lang/sk_server_config.lng
index b13462584ea441f8bc34d002070a4ed00b749346..9ec5367be5a296f294d8b227c5ec503519fdcb67 100644
--- a/interface/web/admin/lib/lang/sk_server_config.lng
+++ b/interface/web/admin/lib/lang/sk_server_config.lng
@@ -192,12 +192,14 @@ $wb['mailbox_quota_stats_txt'] = 'Mailbox quota statistics';
 $wb['enable_ip_wildcard_txt'] = 'Enable IP wildcard (*)';
 $wb['web_folder_protection_txt'] = 'Make web folders immutable (extended attributes)';
 $wb['overtraffic_notify_admin_txt'] = 'Send overtraffic notification to admin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Send overtraffic notification to client';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Please specify valid RBL hostnames.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Send quota warnings to admin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Send quota warnings to client';
 $wb['overquota_notify_onok_txt'] = 'Send quota ok message to client';
 $wb['overquota_notify_freq_txt'] = 'Send quota warning each X days';
@@ -279,6 +281,7 @@ $wb['do_not_try_rescue_mongodb_txt'] = 'Disable MongoDB monitoring';
 $wb['backup_dir_mount_cmd_txt'] = 'Mount command, if backup directory not mounted';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Send DB quota warnings to admin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Send DB quota warnings to client';
 $wb['php_handler_txt'] = 'Default PHP Handler';
 $wb['php_fpm_default_chroot_txt'] = 'Default chrooted PHP-FPM';
@@ -339,3 +342,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/sk_users.lng b/interface/web/admin/lib/lang/sk_users.lng
index 9cc7f87e0d23dc6feb43ad2d26664c3b336e7918..f0c863d749ed2190a06956dd65b6c7f2c6a99c5b 100644
--- a/interface/web/admin/lib/lang/sk_users.lng
+++ b/interface/web/admin/lib/lang/sk_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'The username may not be web or web plus a num
 $wb['client_not_admin_err'] = 'A user that belongs to a client can not be set to type: admin';
 $wb['lost_password_function_txt'] = 'Forgot password function is available';
 $wb['no_user_insert'] = 'CP-Users of type -user- get added and updated automatically when you add a client or reseller.';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/lib/lang/tr_server_config.lng b/interface/web/admin/lib/lang/tr_server_config.lng
index e15677aa3d5ac8d274f1a4fbd4202deddc4dca64..29ccbe6129a1ed1d5bf8af6bb942a4c87031865e 100644
--- a/interface/web/admin/lib/lang/tr_server_config.lng
+++ b/interface/web/admin/lib/lang/tr_server_config.lng
@@ -199,12 +199,14 @@ $wb['mailbox_quota_stats_txt'] = 'E-posta Kutusu Kota Ä°statistikleri';
 $wb['enable_ip_wildcard_txt'] = 'IP Genel Karakteri (*) Kullanılsın';
 $wb['web_folder_protection_txt'] = 'Web klasörleri ayarlanamasın (genişletilmiş öznitelikler)';
 $wb['overtraffic_notify_admin_txt'] = 'Trafik Aşımı Bildirimi Yöneticiye Gönderilsin';
+$wb['overtraffic_notify_reseller_txt'] = 'Send overtraffic notification to reseller';
 $wb['overtraffic_notify_client_txt'] = 'Trafik Aşımı Bildirimi Müşteriye Gönderilsin';
 $wb['overtraffic_disable_web_txt'] = 'Disable websites that exceed traffic limit';
 $wb['rbl_error_regex'] = 'Lütfen geçerli RBL sunucu adları yazın.';
 $wb['overquota_notify_threshold_txt'] = 'Quota warning usage level';
 $wb['overquota_notify_threshold_error'] = 'Quota warning usage level must be between 0-100%';
 $wb['overquota_notify_admin_txt'] = 'Kota Uyarıları Yöneticiye Gönderilsin';
+$wb['overquota_notify_reseller_txt'] = 'Send quota warnings to reseller';
 $wb['overquota_notify_client_txt'] = 'Kota Uyarıları Müşteriye Gönderilsin';
 $wb['overquota_notify_onok_txt'] = 'Kota Tamam İletisi Müşteriye Gönderilsin';
 $wb['overquota_notify_freq_txt'] = 'Kota Uyarısı Gönderim Sıklığı (Gün)';
@@ -229,6 +231,7 @@ $wb['backup_dir_mount_cmd_txt'] = 'Mount komutu, yedek klasörü takılı değil
 $wb['backup_delete_txt'] = 'Etki alanı ya da web sitesi silindiğinde yedekler de silinsin';
 $wb['overquota_db_notify_threshold_txt'] = 'DB quota warning usage level';
 $wb['overquota_db_notify_admin_txt'] = 'Veritabanı Kotası Bildirimleri Yöneticiye Gönderilsin';
+$wb['overquota_db_notify_reseller_txt'] = 'Send DB quota warnings to reseller';
 $wb['overquota_db_notify_client_txt'] = 'Veritabanı Kotası Bildirimleri Müşteriye Gönderilsin';
 $wb['monitor_system_updates_txt'] = 'Linux Güncellemeleri Denetlensin';
 $wb['php_handler_txt'] = 'Varsayılan PHP İşleyici';
@@ -336,3 +339,5 @@ $wb['tooltip_jailkit_hardlinks_txt'] = 'Using hardlinks is insecure, but saves d
 $wb['jailkit_hardlinks_allow_txt'] = 'Allow hardlinks within the jail';
 $wb['jailkit_hardlinks_no_txt'] = 'No, remove hardlinked files';
 $wb['jailkit_hardlinks_yes_txt'] = 'Yes, use hardlinks if possible';
+$wb['mailbox_soft_delete_txt'] = 'Mailbox soft delete';
+$wb['mailbox_soft_delete_info_txt'] = 'by default cleaned up after 7 days.';
diff --git a/interface/web/admin/lib/lang/tr_users.lng b/interface/web/admin/lib/lang/tr_users.lng
index 84826357b7a91726f0e2120f36c4489ac5b6d210..3483c48fb984f665d575428e3a766bb528753424 100644
--- a/interface/web/admin/lib/lang/tr_users.lng
+++ b/interface/web/admin/lib/lang/tr_users.lng
@@ -34,4 +34,5 @@ $wb['username_error_collision'] = 'Kullanıcı adı -web- ya da -web- sözcüğ
 $wb['client_not_admin_err'] = 'Bir müşteriye ait bir kullanıcının türü admin olarak atanamaz';
 $wb['lost_password_function_txt'] = 'Parolamı unuttum özelliği kullanılabilir';
 $wb['no_user_insert'] = 'Bir müşteri ya da bayi eklediğinizde -user- türündeki kontrol panosu kullanıcıları otomatik olarak eklenir ve güncellenir .';
+$wb['otp_auth_txt'] = '2-Factor Authentication';
 ?>
diff --git a/interface/web/admin/templates/server_config_mail_edit.htm b/interface/web/admin/templates/server_config_mail_edit.htm
index d23a23a59cd998984660055106df4d92327bdb56..84683191c804141cc6024a207dd92d3e1cb47af4 100644
--- a/interface/web/admin/templates/server_config_mail_edit.htm
+++ b/interface/web/admin/templates/server_config_mail_edit.htm
@@ -140,6 +140,12 @@
                     <a data-toggle="tooltip" title="{tmpl_var name='tooltip_stress_adaptive_txt'}">{tmpl_var name="stress_adaptive"}</a>
                 </div>
             </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='mailbox_soft_delete_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='mailbox_soft_delete'}&nbsp;{tmpl_var name='mailbox_soft_delete_info_txt'}
+                </div>
+            </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label">{tmpl_var name='mailbox_quota_stats_txt'}</label>
                 <div class="col-sm-9">
@@ -157,6 +163,12 @@
                     {tmpl_var name='overquota_notify_admin'}
                 </div>
             </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='overquota_notify_reseller_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='overquota_notify_reseller'}
+                </div>
+            </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label">{tmpl_var name='overquota_notify_client_txt'}</label>
                 <div class="col-sm-9">
diff --git a/interface/web/admin/templates/server_config_web_edit.htm b/interface/web/admin/templates/server_config_web_edit.htm
index 5cf5c43a75826bce63f1c089366bf87bb3383fec..2161907cb5d76790f06e1daf94b5eb1d33070bef 100644
--- a/interface/web/admin/templates/server_config_web_edit.htm
+++ b/interface/web/admin/templates/server_config_web_edit.htm
@@ -133,6 +133,12 @@
                     {tmpl_var name='overtraffic_notify_admin'}
                 </div>
             </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='overtraffic_notify_reseller_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='overtraffic_notify_reseller'}
+                </div>
+            </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label">{tmpl_var name='overtraffic_notify_client_txt'}</label>
                 <div class="col-sm-9">
@@ -156,6 +162,12 @@
                     {tmpl_var name='overquota_notify_admin'}
                 </div>
             </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='overquota_notify_reseller_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='overquota_notify_reseller'}
+                </div>
+            </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label">{tmpl_var name='overquota_notify_client_txt'}</label>
                 <div class="col-sm-9">
@@ -173,6 +185,12 @@
 					{tmpl_var name='overquota_db_notify_admin'}
 				 </div>
 			</div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">{tmpl_var name='overquota_db_notify_reseller_txt'}</label>
+                <div class="col-sm-9">
+                    {tmpl_var name='overquota_db_notify_reseller'}
+                </div>
+            </div>
 			<div class="form-group">
 				<label class="col-sm-3 control-label">{tmpl_var name='overquota_db_notify_client_txt'}</label>
 				<div class="col-sm-9">
diff --git a/interface/web/admin/templates/users_user_edit.htm b/interface/web/admin/templates/users_user_edit.htm
index 234f40f25ef0a11cac4d20389061ad388bd71efa..4e8e3da496fb368a6c90017e669519ff92ccdc7b 100644
--- a/interface/web/admin/templates/users_user_edit.htm
+++ b/interface/web/admin/templates/users_user_edit.htm
@@ -28,6 +28,15 @@
 					<div id="confirmpasswordOK" style="display:none;" class="confirmpasswordok">{tmpl_var name='password_match_txt'}</div>
 				</div>
 			</div>
+            <div class="form-group">
+              <label for="otp_type" class="col-sm-3 control-label">{tmpl_var name='otp_auth_txt'}</label>
+              <div class="col-sm-9">
+                <select name="otp_type" id="otp_type" class="form-control">
+                  {tmpl_var name='otp_type'}
+                </select>
+              </div>
+            </div>
+
             <div class="form-group">
                 <label class="col-sm-3 control-label">{tmpl_var name='modules_txt'}</label>
                 <div class="col-sm-9">
diff --git a/interface/web/client/client_del.php b/interface/web/client/client_del.php
index dadcae0bdff53f2152b17a59e596d0d906902def..d28e14a5c2bd175f0e613cf077a0dc641d678f23 100644
--- a/interface/web/client/client_del.php
+++ b/interface/web/client/client_del.php
@@ -62,12 +62,12 @@ class page_action extends tform_actions {
 		'ftp_user' => 'username', 
 		'mail_access' => 'source', 
 		'mail_content_filter' => '', 
-		'mail_domain' => 'domain', 
 		'mail_forwarding' => '', 
 		'mail_get' => '', 
 		'mail_mailinglist' => 'listname',
 		'mail_user' => 'email', 
 		'mail_user_filter' => '', 
+		'mail_domain' => 'domain',
 		'shell_user' => 'username', 
 		'spamfilter_users' => '',
 		'spamfilter_wblist' => '',
@@ -76,6 +76,7 @@ class page_action extends tform_actions {
 		'web_folder' => 'path', 
 		'web_folder_user' => 'username', 
 		'web_database_user' => 'database_user', 
+		'web_database' => 'database_name',
 	);
 
 	function onDelete() {
@@ -110,6 +111,11 @@ class page_action extends tform_actions {
 			$table_list = array();
 			$client_group_id = $app->functions->intval($client_group['groupid']);
 			if($client_group_id > 1) {
+
+				$client = $app->db->queryOneRecord("SELECT CONCAT(IF(client.company_name != '', CONCAT(client.company_name, ' :: '), ''), IF(client.contact_firstname != '', CONCAT(client.contact_firstname, ' '), ''), client.contact_name, ' (', client.username, IF(client.customer_no != '', CONCAT(', ', client.customer_no), ''), ')') as contactname FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
+
+				$app->tpl->setVar('contactname', $client['contactname']);
+
 				foreach($this->tables as $table => $field) {
 					if($table != '') {
 						$records = $app->db->queryAllRecords("SELECT * FROM ?? WHERE sys_groupid = ?", $table, $client_group_id);
@@ -151,6 +157,8 @@ class page_action extends tform_actions {
 	function onBeforeDelete() {
 		global $app, $conf;
 
+		// DUPLICATE CODE IN interface/lib/classes/remote.d/client.inc.php
+
 		$client_id = $app->functions->intval($this->dataRecord['client_id']);
 
 		if($client_id > 0) {
diff --git a/interface/web/client/templates/client_del.htm b/interface/web/client/templates/client_del.htm
index 5e7201ce5c31ace8d8a4dbb563108b37832b23cf..3fbd16643a3fccab380936503b0dd2979617dfce 100644
--- a/interface/web/client/templates/client_del.htm
+++ b/interface/web/client/templates/client_del.htm
@@ -1,4 +1,4 @@
-<div class='page-header'><h1><tmpl_var name="list_head_txt"></h1></div>
+<div class='page-header'><h1><tmpl_var name="list_head_txt"> <tmpl_var name="contactname"></h1></div>
 <tmpl_if name='number_records'>
 	<tmpl_var name="delete_explanation">:<br /><br />
 	<div class="table-wrapper marginTop15">
diff --git a/interface/web/dns/form/dns_txt.tform.php b/interface/web/dns/form/dns_txt.tform.php
index 564e26aa186ad14bd17d39bc41c04b164e5878d5..886d6e5e095b970c4f0fa393979476371bd345b5 100644
--- a/interface/web/dns/form/dns_txt.tform.php
+++ b/interface/web/dns/form/dns_txt.tform.php
@@ -170,7 +170,7 @@ $form["tabs"]['dns'] = array (
 	)
 );
 
-if($_SESSION["s"]["user"]["typ"] == 'admin') {
+if($app->auth->is_admin()) {
 	unset($form["tabs"]['dns']['fields']['data']['validators']);
 	$form["tabs"]['dns']['fields']['data']['validators'][0]['type'] = 'NOTEMPTY';
 	$form["tabs"]['dns']['fields']['data']['validators'][0]['errmsg'] = 'data_error_empty';
diff --git a/interface/web/dns/templates/dns_spf_edit.htm b/interface/web/dns/templates/dns_spf_edit.htm
index 61d64b642a7a033acef7dd88b0f44ade42b51822..44dd9458906c9d1f739692dd482ed4a28e816d7a 100644
--- a/interface/web/dns/templates/dns_spf_edit.htm
+++ b/interface/web/dns/templates/dns_spf_edit.htm
@@ -53,7 +53,9 @@
             
         <div class="clear"><div class="right">
             <button class="btn btn-default formbutton-success" type="button" value="{tmpl_var name='btn_save_txt'}" data-submit-form="pageForm" data-form-action="dns/dns_spf_edit.php">{tmpl_var name='btn_save_txt'}</button>
+            <tmpl_if name="is_admin">
             <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_edit_as_txt_record_txt'}" data-load-content="dns/dns_txt_edit.php?id={tmpl_var name='id'}&zone={tmpl_var name='zone'}&edit_raw=1">{tmpl_var name='btn_edit_as_txt_record_txt'}</button>
+            </tmpl_if>
             <button class="btn btn-default formbutton-default" type="button" value="{tmpl_var name='btn_cancel_txt'}" data-load-content="dns/dns_soa_edit.php?id={tmpl_var name='zone'}&next_tab=dns_records">{tmpl_var name='btn_cancel_txt'}</button>
         </div></div>
 
diff --git a/interface/web/login/index.php b/interface/web/login/index.php
index d59d24efc8273dc6ab5781f117a5f640a667daa8..c4643f4ed2f9f7c076df06a15106b40c1ba93cb8 100644
--- a/interface/web/login/index.php
+++ b/interface/web/login/index.php
@@ -126,13 +126,6 @@ function process_login_request(app $app, &$error, $conf, $module)
 			}
 		}
 
-		$app->plugin->raiseEvent('login', $username);
-
-		//* Save successful login message to var
-		$authlog = 'Successful login for user \''.$username.'\' from '.$_SERVER['REMOTE_ADDR'].' at '.date('Y-m-d H:i:s').' with session ID '.session_id();
-		$authlog_handle = fopen($conf['ispconfig_log_dir'].'/auth.log', 'a');
-		fwrite($authlog_handle, $authlog."\n");
-		fclose($authlog_handle);
 
 		/*
 		* We need LOGIN_REDIRECT instead of HEADER_REDIRECT to load the
@@ -141,10 +134,33 @@ function process_login_request(app $app, &$error, $conf, $module)
 
 		if ($loginAs) {
 			echo 'LOGIN_REDIRECT:'.$_SESSION['s']['module']['startpage'];
+			$app->plugin->raiseEvent('login', $username);
+			$app->auth_log('Successful login for user \''. $username .'\' ' . $msg . ' from '. $_SERVER['REMOTE_ADDR'] .' at '. date('Y-m-d H:i:s') . ' with session ID ' .session_id());
 			exit;
 		} else {
-			header('Location: ../index.php');
-			die();
+
+			//* Do 2FA authentication
+			if($user['otp_type'] != 'none') {
+
+				//* Save session in pending state and destroy original session
+				$_SESSION['s_pending'] = $_SESSION['s'];
+				unset($_SESSION['s']);
+
+				//* Create OTP session
+				$_SESSION['otp']['session_attempts'] = 0;
+				$_SESSION['otp']['type'] = $user['otp_type'];
+				$_SESSION['otp']['data'] = $user['otp_data'];
+				//$_SESSION['otp']['recovery_debug'] = $user['otp_recovery']; // For DEBUG only.
+
+				//* Redirect to otp script
+				header('Location: otp.php');
+				die();
+			} else {
+				$app->plugin->raiseEvent('login', $username);
+				$app->auth_log('Successful login for user \''. $username .'\' ' . $msg . ' from '. $_SERVER['REMOTE_ADDR'] .' at '. date('Y-m-d H:i:s') . ' with session ID ' .session_id());
+				header('Location: ../index.php');
+				die();
+			}
 		}
 	} else {
 		if (!$alreadyfailed['times']) {
@@ -161,11 +177,7 @@ function process_login_request(app $app, &$error, $conf, $module)
 		if ($app->db->errorMessage != '') $error .= '<br />'.$app->db->errorMessage != '';
 
 		$app->plugin->raiseEvent('login_failed', $username);
-		//* Save failed login message to var
-		$authlog = 'Failed login for user \''.$username.'\' from '.$_SERVER['REMOTE_ADDR'].' at '.date('Y-m-d H:i:s');
-		$authlog_handle = fopen($conf['ispconfig_log_dir'].'/auth.log', 'a');
-		fwrite($authlog_handle, $authlog."\n");
-		fclose($authlog_handle);
+		$app->auth_log('Failed login for user \''. $username .'\ from '. $_SERVER['REMOTE_ADDR'] .' at '. date('Y-m-d H:i:s'));
 	}
 }
 
diff --git a/interface/web/login/lib/lang/ar.lng b/interface/web/login/lib/lang/ar.lng
index a50df19db41051fb421ffe9dc5673ba273bda9c9..79ff8def0bfad10129e96da146ec9a7629d29b32 100644
--- a/interface/web/login/lib/lang/ar.lng
+++ b/interface/web/login/lib/lang/ar.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/bg.lng b/interface/web/login/lib/lang/bg.lng
index 8081ec8097f2efe56bed1d001c7365be9b46e29a..18f46d6df8f5be5e44473db554981d8c28b95807 100644
--- a/interface/web/login/lib/lang/bg.lng
+++ b/interface/web/login/lib/lang/bg.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/br.lng b/interface/web/login/lib/lang/br.lng
index 382bd1b8ac14962c3ffd4104fed43758ffc4612e..1f5b41c369389027fae7cb32be3a66c392895a39 100644
--- a/interface/web/login/lib/lang/br.lng
+++ b/interface/web/login/lib/lang/br.lng
@@ -32,3 +32,12 @@ $wb['pw_reset_act_mail_msg'] = 'Por favor, confirme se você deseja reiniciar su
 $wb['lost_password_function_wait_txt'] = 'Você não pode requisitar uma nova senha ainda. Por favor, aguarde alguns minutos.';
 $wb['lost_password_function_expired_txt'] = 'Este link de ativação expirou. Por favor, faça uma nova requisição.';
 $wb['lost_password_function_denied_txt'] = 'Este link de ativação não é válido.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
diff --git a/interface/web/login/lib/lang/ca.lng b/interface/web/login/lib/lang/ca.lng
index 8c672b59c5caac8bbef310f796b5e283799f5f40..f4aa11776a941d8b506392f45007d051efa6700f 100644
--- a/interface/web/login/lib/lang/ca.lng
+++ b/interface/web/login/lib/lang/ca.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/cz.lng b/interface/web/login/lib/lang/cz.lng
index 9b22d7d3c776076375eef06dcfc64f313d871c32..a57ff3f7044885f0acae16a68495376c7e63e0bf 100644
--- a/interface/web/login/lib/lang/cz.lng
+++ b/interface/web/login/lib/lang/cz.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/de.lng b/interface/web/login/lib/lang/de.lng
index 446f04edc87eb44b17263d5b4754f1966679f848..dcb94af7168cafcdd4af58137fd246fe8933bb1f 100644
--- a/interface/web/login/lib/lang/de.lng
+++ b/interface/web/login/lib/lang/de.lng
@@ -32,4 +32,13 @@ $wb['lost_password_function_disabled_txt'] = 'Die Passwort vergessen Funktion st
 $wb['lost_password_function_wait_txt'] = 'Sie können im Moment kein neues Passwort anfordern. Bitte warten Sie einige Minuten.';
 $wb['lost_password_function_expired_txt'] = 'Der Passwortlink ist abgelaufen. Bitte fordern Sie einen neuen an.';
 $wb['lost_password_function_denied_txt'] = 'Dieser Passwortlink ist ungültig.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/dk.lng b/interface/web/login/lib/lang/dk.lng
index 8a104c45be9fdd0a364f519870d20134cd926b2e..37d41ddea1581710d1a24d512d35803ab79e27cc 100644
--- a/interface/web/login/lib/lang/dk.lng
+++ b/interface/web/login/lib/lang/dk.lng
@@ -32,4 +32,13 @@ $wb['lost_password_function_disabled_txt'] = 'The lost password function is not
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/el.lng b/interface/web/login/lib/lang/el.lng
index 8a6ed3387f8bb72829facb4051345e2197db9aa2..64a03b36f63e3bc1ec1856d7ac6aa87ce6397788 100644
--- a/interface/web/login/lib/lang/el.lng
+++ b/interface/web/login/lib/lang/el.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/en.lng b/interface/web/login/lib/lang/en.lng
index a99d0d3d092c47d3aa334bdef4de4c0d96cdf184..8dd94c6294f3c996fac2b331b7431323b0d7d1c3 100644
--- a/interface/web/login/lib/lang/en.lng
+++ b/interface/web/login/lib/lang/en.lng
@@ -32,4 +32,13 @@ $wb['lost_password_function_disabled_txt'] = 'The lost password function is not
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/es.lng b/interface/web/login/lib/lang/es.lng
index 273f69aabea71918947c92a351114595f2f3ae2c..dd8bd12bc4910604569c1d6576d2bf4aa54234ea 100644
--- a/interface/web/login/lib/lang/es.lng
+++ b/interface/web/login/lib/lang/es.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Por favor confirme que desea restablecer la cont
 $wb['lost_password_function_wait_txt'] = 'No puede solicitar una nueva contraseña todavía. Por favor, espere unos minutos.';
 $wb['lost_password_function_expired_txt'] = 'Este enlace de activación ha caducado. Por favor, solicite uno nuevo.';
 $wb['lost_password_function_denied_txt'] = 'Este enlace de activación no es válido.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/fi.lng b/interface/web/login/lib/lang/fi.lng
index 8198dd4822ae84dd7a2202b9e0b9ec726316148f..9bbcbdddabdd7cf09d666de995cf91194d15abe0 100644
--- a/interface/web/login/lib/lang/fi.lng
+++ b/interface/web/login/lib/lang/fi.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/fr.lng b/interface/web/login/lib/lang/fr.lng
index f067751aa9bc1499665c7126c494f4e78c51f48e..dfc04fd184601ab61b2bf3abe8648b5819bd07ea 100644
--- a/interface/web/login/lib/lang/fr.lng
+++ b/interface/web/login/lib/lang/fr.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/hr.lng b/interface/web/login/lib/lang/hr.lng
index 193123557a4b6931d20ef32de6c01ee782f3596b..1980c4292dcda9cbe5eef922e48e1c540b1e29d3 100644
--- a/interface/web/login/lib/lang/hr.lng
+++ b/interface/web/login/lib/lang/hr.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/hu.lng b/interface/web/login/lib/lang/hu.lng
index b6adb6b19d2dd3fb3ba25d24508061c972954ca1..99e2ca769bcc07b6de8534090e36af5feac6003b 100644
--- a/interface/web/login/lib/lang/hu.lng
+++ b/interface/web/login/lib/lang/hu.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/id.lng b/interface/web/login/lib/lang/id.lng
index 35e3675a9d9f630a024d13ca03b6e097b70b9331..615357f654f6b47fe4dc61eda6c32c2c0f88d1db 100644
--- a/interface/web/login/lib/lang/id.lng
+++ b/interface/web/login/lib/lang/id.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/it.lng b/interface/web/login/lib/lang/it.lng
index 7d83e22108a67d4d0a812dc76c3a551ddb5b7604..df498e978acc76c0f12db9149b0ab5891925a867 100644
--- a/interface/web/login/lib/lang/it.lng
+++ b/interface/web/login/lib/lang/it.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Per confermare il reset della password si prega
 $wb['lost_password_function_wait_txt'] = 'Non puoi richiedere una nuova password in questo momento. Riprova tra qualche minuto.';
 $wb['lost_password_function_expired_txt'] = 'Link di attivazione scaduto. Si prega di richiedere un nuovo link di attivazione.';
 $wb['lost_password_function_denied_txt'] = 'Link di attivazione non valido.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/ja.lng b/interface/web/login/lib/lang/ja.lng
index 4b9e2c62363720530033eee88a65e4639edd08be..bff26e9d83826f74edf744190f3a2737c0a72885 100644
--- a/interface/web/login/lib/lang/ja.lng
+++ b/interface/web/login/lib/lang/ja.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/nl.lng b/interface/web/login/lib/lang/nl.lng
index cd5f3b713df85fc5354847b9ec6a19d5a7d0bbfe..453aae6fac9bdc7ef6646a2fcd9e6db23c2f67f7 100644
--- a/interface/web/login/lib/lang/nl.lng
+++ b/interface/web/login/lib/lang/nl.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Twee-factor authenticatie';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'Een email is verstuurd aan';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authenticatie';
+$wb['otp_code_email_template_txt'] = 'Uw eenmalige login code is %s' . PHP_EOL . 'Deze code is geldig voor 10 minuten.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Aanvragen nieuwe code';
+$wb['otp_code_email_sent_failed_txt'] = 'Verzenden van email naar %s is mislukt.';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/pl.lng b/interface/web/login/lib/lang/pl.lng
index 9b2359b3eb7610481b194ff4aef087a835393804..f6937205425592ecc92a2903e5ca38fffc674404 100644
--- a/interface/web/login/lib/lang/pl.lng
+++ b/interface/web/login/lib/lang/pl.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'Nie możesz jeszcze zażądać nowego hasła. Poczekaj kilka minut.';
 $wb['lost_password_function_expired_txt'] = 'Link aktywacyjny wygasł. Poproś o nowy.';
 $wb['lost_password_function_denied_txt'] = 'Ten link aktywacyjny jest nieprawidłowy.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/pt.lng b/interface/web/login/lib/lang/pt.lng
index 4be018a50c72b54a1f4007b73e1a60b80b1a054a..fd453844ea22bee3cf366331f3135564623bbc38 100644
--- a/interface/web/login/lib/lang/pt.lng
+++ b/interface/web/login/lib/lang/pt.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/ro.lng b/interface/web/login/lib/lang/ro.lng
index 7676d928d57fbe6a18e2eb7182d9a80e7f6c714d..94950d6c069ab7652e9f75d7529d0d0bfa74cb33 100644
--- a/interface/web/login/lib/lang/ro.lng
+++ b/interface/web/login/lib/lang/ro.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/ru.lng b/interface/web/login/lib/lang/ru.lng
index 4f1b4e86fc8d4cd099161dd6d8f5fc5d7d31ad47..999723c2d6b378f775a7435d19fb2f1a7616f4a8 100644
--- a/interface/web/login/lib/lang/ru.lng
+++ b/interface/web/login/lib/lang/ru.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Для подтверждения сброса 
 $wb['lost_password_function_wait_txt'] = 'Вы не можете запросить новый пароль, пока нет. Пожалуйста, подождите несколько минут.';
 $wb['lost_password_function_expired_txt'] = 'Срок активации этой ссылки истек. Пожалуйста, запросите новую.';
 $wb['lost_password_function_denied_txt'] = 'Эта ссылка активации недействительна.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/se.lng b/interface/web/login/lib/lang/se.lng
index 4f8a8a44431c6787484fd280173fdd4b6e2c3b7b..db0aeba05ecba8c39d72a3858dd2981a5a0489e7 100644
--- a/interface/web/login/lib/lang/se.lng
+++ b/interface/web/login/lib/lang/se.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/sk.lng b/interface/web/login/lib/lang/sk.lng
index 8c211b19beab44a010faa95f82f731c0988b04ef..20ed8f74a79446c9e33e8f834276685dabbd3e09 100644
--- a/interface/web/login/lib/lang/sk.lng
+++ b/interface/web/login/lib/lang/sk.lng
@@ -32,4 +32,13 @@ $wb['pw_reset_act_mail_msg'] = 'Please confirm that your want to reset your ISPC
 $wb['lost_password_function_wait_txt'] = 'You cannot request a new password, yet. Please wait a few minutes.';
 $wb['lost_password_function_expired_txt'] = 'This activation link has expired. Please request a new one.';
 $wb['lost_password_function_denied_txt'] = 'This activation link is not valid.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/lib/lang/tr.lng b/interface/web/login/lib/lang/tr.lng
index 7bcc75f6942b52238d1c80546c0397d3c29d908d..f30f1fb35440cb52be0ab93803ccd10239acb32e 100644
--- a/interface/web/login/lib/lang/tr.lng
+++ b/interface/web/login/lib/lang/tr.lng
@@ -32,4 +32,13 @@ $wb['lost_password_function_disabled_txt'] = 'Bu kullanıcı parolamı unuttum 
 $wb['lost_password_function_wait_txt'] = 'Henüz yeni parola isteğinde bulunamazsınız. Lütfen bir kaç dakika bekleyin.';
 $wb['lost_password_function_expired_txt'] = 'Bu etkinleştirme bağlantısının süresi geçmiş. Lütfen yeni bir parola sıfırlama isteğinde bulunun.';
 $wb['lost_password_function_denied_txt'] = 'Bu etkinleştirme bağlantısı geçersiz.';
+$wb['otp_code_txt'] = 'Two Factor Authentication';
+$wb['otp_code_desc_txt'] = 'Enter the code you got from your authenticator app or via email.';
+$wb['otp_code_placeholder_txt'] = 'OTP code';
+$wb['otp_code_email_sent_txt'] = 'An email was sent to';
+$wb['otp_code_email_subject_txt'] = 'ISPConfig Login authentication';
+$wb['otp_code_email_template_txt'] = 'Your One time login code is %s' . PHP_EOL . 'This code is valid for 10 minutes.' . PHP_EOL;
+$wb['otp_code_resend_txt'] = 'Request new code';
+$wb['otp_code_email_sent_failed_txt'] = 'Failed sending an email to %s';
+$wb['otp_code_email_sent_wait_txt'] = 'Please wait, re-sending the code is only possible after %s seconds.';
 ?>
diff --git a/interface/web/login/otp.php b/interface/web/login/otp.php
new file mode 100644
index 0000000000000000000000000000000000000000..8b80691da6f20a626c518db9a89d12c8cc335d9e
--- /dev/null
+++ b/interface/web/login/otp.php
@@ -0,0 +1,231 @@
+<?php
+
+/*
+Copyright (c) 2021, Till Brehm, ISPConfig UG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once '../../lib/config.inc.php';
+require_once '../../lib/app.inc.php';
+
+// Check if we have an active users ession.
+if($_SESSION['s']['user']['active'] == 1) {
+	header('Location: /index.php');
+	die();
+}
+
+// If we don't have a 2fa session go back to login page.
+if(!isset($_SESSION['otp'])) {
+	header('Location: index.php');
+	die();
+}
+
+// Variables and settings.
+$error = '';
+$msg = '';
+$max_session_code_retry = 3;
+$max_global_code_retry = 10;
+$otp_recovery_code_length = 32;
+
+// CSRF Check if we got POST data.
+if(count($_POST) >= 1) {
+	$app->auth->csrf_token_check();
+}
+
+require ISPC_ROOT_PATH.'/web/login/lib/lang/'.$app->functions->check_language($conf['language']).'.lng';
+
+function finish_2fa_success($msg = '') {
+	global $app;
+	$_SESSION['s'] = $_SESSION['s_pending'];
+	unset($_SESSION['s_pending']);
+	unset($_SESSION['otp']);
+	$username = $_SESSION['s']['user']['username'];
+	if (!empty($msg)) {
+		$msg = ' ' . $msg;
+	}
+	$app->auth_log('Successful login for user \''. $username .'\'' . $msg . ' from '. $_SERVER['REMOTE_ADDR'] .' at '. date('Y-m-d H:i:s') . ' with session ID ' .session_id());
+	$app->db->query('UPDATE `sys_user` SET otp_attempts=0 WHERE userid = ?', $_SESSION['s']['user']['userid']);
+	session_write_close();
+	header('Location: ../index.php');
+	die();
+}
+
+// Handle recovery code
+if(isset($_POST['code']) && strlen($_POST['code']) == $otp_recovery_code_length) {
+	//* TODO Recovery code handling
+
+	$user = $app->db->queryOneRecord('SELECT otp_attempts, otp_recovery FROM sys_user WHERE userid = ?', $_SESSION['s_pending']['user']['userid']);
+
+	//* We allow one more try to enter recovery code
+	if($user['otp_attempts'] > $max_global_code_retry + 1) {
+		die("Sorry, contact your administrator.");
+	}
+
+	if (password_verify($_POST['code'], $user['otp_recovery'])) {
+		finish_2fa_success('via 2fa recovery code');
+	}
+	else {
+		$app->db->query('UPDATE `sys_user` SET otp_attempts=otp_attempts + 1 WHERE userid = ?', $_SESSION['s_pending']['user']['userid']);
+	}
+}
+
+
+// Begin 2fa via Email.
+if($_SESSION['otp']['type'] == 'email') {
+
+	//* Email 2fa handler settings
+	$max_code_resend = 3;
+	$max_time = 600; // time in seconds until the code gets invalidated
+	$code_length = 6;
+
+	if(isset($_POST['code']) && strlen($_POST['code']) == $code_length && isset($_SESSION['otp']['code_hash'])) {
+
+		$user = $app->db->queryOneRecord('SELECT otp_attempts FROM sys_user WHERE userid = ?', $_SESSION['s_pending']['user']['userid']);
+
+		//* Check if we reached limits
+		if($_SESSION['otp']['sent'] > $max_code_resend
+			|| $_SESSION['otp']['session_attempts'] > $max_session_code_retry
+			|| $user['otp_attempts'] > $max_global_code_retry
+			|| time() > $_SESSION['otp']['starttime'] + $max_time
+			) {
+			unset($_SESSION['otp']);
+			unset($_SESSION['s_pending']);
+			$app->error('2FA failed','index.php');
+		}
+
+		//* 2fa success
+		if(password_verify($_POST['code'], $_SESSION['otp']['code_hash'])) {
+			finish_2fa_success('with 2fa');
+		} else {
+			//* 2fa wrong code
+			$_SESSION['otp']['session_attempts']++;
+			$app->db->query('UPDATE `sys_user` SET otp_attempts=otp_attempts + 1 WHERE userid = ?', $_SESSION['s_pending']['user']['userid']);
+		}
+	}
+
+	// Send code via email.
+	if (!isset($_SESSION['otp']['sent']) || $_GET['action'] == 'resend') {
+
+		$mail_otp_code_retry_timeout = 30;
+		if (isset($_SESSION['otp']['starttime']) && $_SESSION['otp']['starttime'] > time() - $mail_otp_code_retry_timeout) {
+			$token_sent_message = sprintf($wb['otp_code_email_sent_wait_txt'], $mail_otp_code_retry_timeout);
+		}
+		else {
+
+			// Generate new code
+			$new_otp_code = random_int(100000, 999999);
+			$_SESSION['otp']['code_hash'] = password_hash($new_otp_code, PASSWORD_DEFAULT);
+			//$_SESSION['otp']['code_debug'] = $new_otp_code; # for DEBUG only.
+			$_SESSION['otp']['starttime'] = time();
+
+			// Ensure that code is not sent too often
+			if(isset($_SESSION['otp']['sent']) && $_SESSION['otp']['sent'] > $max_code_resend) {
+				$app->error('Code resend limit reached', 'index.php');
+			}
+
+			$app->uses('functions');
+			$app->uses('getconf');
+			$server_config_array = $app->getconf->get_global_config();
+
+			$app->uses('getconf,ispcmail');
+			$mail_config = $server_config_array['mail'];
+			if($mail_config['smtp_enabled'] == 'y') {
+				$mail_config['use_smtp'] = true;
+				$app->ispcmail->setOptions($mail_config);
+			}
+
+			$clientuser = $app->db->queryOneRecord('SELECT email FROM sys_user u LEFT JOIN client c ON (u.client_id=c.client_id) WHERE u.userid = ?', $_SESSION['s_pending']['user']['userid']);
+			if (!empty($clientuser['email'])) {
+				$email_to = $clientuser['email'];
+			}
+			else {
+				// Admin users are not related to a client, thus use the globally configured email address.
+				$email_to = $mail_config['admin_mail'];
+			}
+
+			$app->ispcmail->setSender($mail_config['admin_mail'], $mail_config['admin_name']);
+			$app->ispcmail->setSubject($wb['otp_code_email_subject_txt']);
+			$app->ispcmail->setMailText(sprintf($wb['otp_code_email_template_txt'], $new_otp_code));
+			$send_result = $app->ispcmail->send($email_to);
+			$app->ispcmail->finish();
+
+			if ($send_result) {
+
+				// Increase sent counter.
+				if(!isset($_SESSION['otp']['sent'])) {
+					$_SESSION['otp']['sent'] = 1;
+				} else {
+					$_SESSION['otp']['sent']++;
+				}
+
+				$token_sent_message = $wb['otp_code_email_sent_txt'] . ' ' . $email_to;
+			}
+			else {
+				$token_sent_message = sprintf($wb['otp_code_email_sent_failed_txt'], $email_to);
+			}
+		}
+	}
+
+	// Show form to enter email code
+	// ... below
+
+} else {
+	$app->error('Otp method unknown', 'index.php');
+}
+
+
+$logo = $app->db->queryOneRecord("SELECT * FROM sys_ini WHERE sysini_id = 1");
+if($logo['custom_logo'] != ''){
+    $base64_logo_txt = $logo['custom_logo'];
+} else {
+    $base64_logo_txt = $logo['default_logo'];
+}
+$app->tpl->setVar('base64_logo_txt', $base64_logo_txt);
+
+$app->tpl->setVar('current_theme', isset($_SESSION['s']['theme']) ? $_SESSION['s']['theme'] : 'default', true);
+if (!empty($token_sent_message)) {
+  $app->tpl->setVar('token_sent_message', $token_sent_message);
+}
+
+// Load templating system and lang file.
+$app->uses('tpl');
+$app->tpl->newTemplate('main_login.tpl.htm');
+$app->tpl->setInclude('content_tpl', 'templates/otp.htm');
+
+
+// SET csrf token.
+$csrf_token = $app->auth->csrf_token_get('otp');
+$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
+$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
+//$app->tpl->setVar('msg', print_r($_SESSION['otp'], 1)); // For DEBUG only.
+
+$app->tpl->setVar($wb);
+
+$app->tpl_defaults();
+$app->tpl->pparse();
+
+
+?>
diff --git a/interface/web/login/templates/otp.htm b/interface/web/login/templates/otp.htm
new file mode 100644
index 0000000000000000000000000000000000000000..cf49ba8108d6c7157c0458104d79c5098a40868d
--- /dev/null
+++ b/interface/web/login/templates/otp.htm
@@ -0,0 +1,25 @@
+<tmpl_if name="msg">
+<div class="alert alert-success" role="alert"><tmpl_var name="msg"></div>
+</tmpl_if>
+<tmpl_if name="error">
+<div class="alert alert-danger" role="alert"><tmpl_var name="error"></div>
+</tmpl_if>
+<h2><tmpl_var name="otp_code_txt"></h2>
+<p><tmpl_var name="otp_code_desc_txt"></p>
+<form accept-charset="UTF-8" role="form" method="post" action="otp.php">
+<fieldset>
+	<div class="form-group">
+		<input class="form-control" placeholder="{tmpl_var name='otp_code_placeholder_txt'}" name="code" id="code" type="text" autofocus>
+	</div>
+	<div class="right">
+			<input class="btn btn-default formbutton-default" type="submit" value="{tmpl_var name='login_button_txt'}">
+	</div>
+	<tmpl_if name="token_sent_message">{tmpl_var name='token_sent_message'}<br /></tmpl_if>
+	<a href="otp.php?action=resend">{tmpl_var name='otp_code_resend_txt'}</a>
+
+
+	<input type="hidden" name="_csrf_id" value="{tmpl_var name='_csrf_id'}" />
+	<input type="hidden" name="_csrf_key" value="{tmpl_var name='_csrf_key'}" />
+
+</fieldset>
+</form>
diff --git a/interface/web/mail/lib/remote.conf.php b/interface/web/mail/lib/remote.conf.php
index ae03e9992aa99374c163fe0e2876189e8b9644ec..3060a8b4cc7be87c3e15f75f015822eac8bec2a4 100644
--- a/interface/web/mail/lib/remote.conf.php
+++ b/interface/web/mail/lib/remote.conf.php
@@ -3,7 +3,7 @@
 $function_list['mail_domain_get,mail_domain_add,mail_domain_update,mail_domain_delete,mail_domain_set_status,mail_domain_get_by_domain'] = 'Mail domain functions';
 $function_list['mail_aliasdomain_get,mail_aliasdomain_add,mail_aliasdomain_update,mail_aliasdomain_delete'] = 'Mail domain alias functions';
 $function_list['mail_mailinglist_get,mail_mailinglist_add,mail_mailinglist_update,mail_mailinglist_delete'] = 'Mail mailinglist functions';
-$function_list['mail_user_get,mail_user_add,mail_user_update,mail_user_delete'] = 'Mail user functions';
+$function_list['mail_user_get,mail_user_add,mail_user_update,mail_user_delete,mail_user_get_all_by_client'] = 'Mail user functions';
 $function_list['mail_alias_get,mail_alias_add,mail_alias_update,mail_alias_delete'] = 'Mail alias functions';
 $function_list['mail_forward_get,mail_forward_add,mail_forward_update,mail_forward_delete'] = 'Mail forward functions';
 $function_list['mail_catchall_get,mail_catchall_add,mail_catchall_update,mail_catchall_delete'] = 'Mail catchall functions';
diff --git a/interface/web/mail/templates/mail_user_mailbox_edit.htm b/interface/web/mail/templates/mail_user_mailbox_edit.htm
index 170ab15db0127ef7797ec7638fa4b98784668d43..4b47b9ecc55d94674943a91cd55ca70e613bc700 100644
--- a/interface/web/mail/templates/mail_user_mailbox_edit.htm
+++ b/interface/web/mail/templates/mail_user_mailbox_edit.htm
@@ -11,6 +11,11 @@
                         <div class='input-group-field'>
 							<select name="email_domain" id="email_domain" class="form-control" style="height:50px;min-width:170px;">{tmpl_var name='email_domain'}</select>
                         </div>
+                        <div class="input-group-field">
+                          <a class="btn btn-default formbutton-narrow" href="javascript: navigator.clipboard.writeText(document.getElementById('email_local_part').value + '@' + document.getElementById('email_domain').value);" title="">i
+                            <span class="fa fa-clone"></span>
+                          </a>
+                        </div>
                     </div>
 				</div>
             </div>
diff --git a/interface/web/monitor/lib/lang/ar_dataloghistory_list.lng b/interface/web/monitor/lib/lang/ar_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/ar_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/ar_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/bg_dataloghistory_list.lng b/interface/web/monitor/lib/lang/bg_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/bg_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/bg_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/br_dataloghistory_list.lng b/interface/web/monitor/lib/lang/br_dataloghistory_list.lng
index 894670052ff6088caf9a024ba28dc4c0f3cdab99..6034c94ac6d0cb816195c24e63bad1c73e26a54e 100644
--- a/interface/web/monitor/lib/lang/br_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/br_dataloghistory_list.lng
@@ -5,3 +5,4 @@ $wb['server_id_txt'] = 'Servidor';
 $wb['dbtable_txt'] = 'Tabela do BD';
 $wb['action_txt'] = 'Ação';
 $wb['status_txt'] = 'Estado';
+$wb['user_txt'] = 'User';
diff --git a/interface/web/monitor/lib/lang/ca_dataloghistory_list.lng b/interface/web/monitor/lib/lang/ca_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/ca_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/ca_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/cz_dataloghistory_list.lng b/interface/web/monitor/lib/lang/cz_dataloghistory_list.lng
index c7600817bde1d171e60ba150ce3ddb86085b90fe..1ac39bb4eadde30033289ce6df08c5130ecb555e 100644
--- a/interface/web/monitor/lib/lang/cz_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/cz_dataloghistory_list.lng
@@ -5,3 +5,4 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Tabulka';
 $wb['action_txt'] = 'Akce';
 $wb['status_txt'] = 'Stav';
+$wb['user_txt'] = 'User';
diff --git a/interface/web/monitor/lib/lang/de_dataloghistory_list.lng b/interface/web/monitor/lib/lang/de_dataloghistory_list.lng
index 2c2b6c9fc2d41c11f5d37d11d691140229718b7a..2fc3534b6b48e0a69ce16f62c9b4812a92e3cd76 100644
--- a/interface/web/monitor/lib/lang/de_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/de_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'Datenbanktabelle';
 $wb['action_txt'] = 'Aktion';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'Benutzer';
 ?>
diff --git a/interface/web/monitor/lib/lang/dk_dataloghistory_list.lng b/interface/web/monitor/lib/lang/dk_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/dk_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/dk_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/el_dataloghistory_list.lng b/interface/web/monitor/lib/lang/el_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/el_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/el_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/en_dataloghistory_list.lng b/interface/web/monitor/lib/lang/en_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/en_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/en_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/es_dataloghistory_list.lng b/interface/web/monitor/lib/lang/es_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/es_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/es_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/fi_dataloghistory_list.lng b/interface/web/monitor/lib/lang/fi_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/fi_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/fi_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/fr_dataloghistory_list.lng b/interface/web/monitor/lib/lang/fr_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/fr_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/fr_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/hr_dataloghistory_list.lng b/interface/web/monitor/lib/lang/hr_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/hr_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/hr_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/hu_dataloghistory_list.lng b/interface/web/monitor/lib/lang/hu_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/hu_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/hu_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/id_dataloghistory_list.lng b/interface/web/monitor/lib/lang/id_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/id_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/id_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/it_dataloghistory_list.lng b/interface/web/monitor/lib/lang/it_dataloghistory_list.lng
index 26138fba2503ea9a37ee24d3a3e010b82e6e6d83..69f31abac96cc08cc1ce780043163f053bff6bde 100644
--- a/interface/web/monitor/lib/lang/it_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/it_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'Tabella DB';
 $wb['action_txt'] = 'Azione';
 $wb['status_txt'] = 'Stato';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/ja_dataloghistory_list.lng b/interface/web/monitor/lib/lang/ja_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/ja_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/ja_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/nl_dataloghistory_list.lng b/interface/web/monitor/lib/lang/nl_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/nl_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/nl_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/pl_dataloghistory_list.lng b/interface/web/monitor/lib/lang/pl_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/pl_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/pl_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/pt_dataloghistory_list.lng b/interface/web/monitor/lib/lang/pt_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/pt_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/pt_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/ro_dataloghistory_list.lng b/interface/web/monitor/lib/lang/ro_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/ro_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/ro_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/ru_dataloghistory_list.lng b/interface/web/monitor/lib/lang/ru_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/ru_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/ru_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/se_dataloghistory_list.lng b/interface/web/monitor/lib/lang/se_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/se_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/se_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/sk_dataloghistory_list.lng b/interface/web/monitor/lib/lang/sk_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/sk_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/sk_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/lib/lang/tr_dataloghistory_list.lng b/interface/web/monitor/lib/lang/tr_dataloghistory_list.lng
index f1ba8c67b8eed44c916f66d91ec4bd7a1af49872..1fd0a318cb7e132fd8ed123067725cf9f028c8b9 100644
--- a/interface/web/monitor/lib/lang/tr_dataloghistory_list.lng
+++ b/interface/web/monitor/lib/lang/tr_dataloghistory_list.lng
@@ -5,4 +5,5 @@ $wb['server_id_txt'] = 'Server';
 $wb['dbtable_txt'] = 'DB Table';
 $wb['action_txt'] = 'Action';
 $wb['status_txt'] = 'Status';
+$wb['user_txt'] = 'User';
 ?>
diff --git a/interface/web/monitor/list/dataloghistory.list.php b/interface/web/monitor/list/dataloghistory.list.php
index 1757125e8d2b33690f4bf7522513ca5c0eb3c653..7679f397dbbc871c3c53e69cf9366390622d9f48 100644
--- a/interface/web/monitor/list/dataloghistory.list.php
+++ b/interface/web/monitor/list/dataloghistory.list.php
@@ -77,7 +77,6 @@ $liste["item"][] = array( 'field'  => "action",
 	'width'  => "",
 	'value'  => array('i' => "Insert", 'u' => "Update", 'd' => "Delete"));
 
-
 $liste["item"][] = array( 'field'  => "dbtable",
 	'datatype' => "VARCHAR",
 	'formtype' => "TEXT",
@@ -87,5 +86,13 @@ $liste["item"][] = array( 'field'  => "dbtable",
 	'width'  => "",
 	'value'  => "");
 
+$liste["item"][] = array( 'field'  => "user",
+	'datatype' => "VARCHAR",
+	'formtype' => "TEXT",
+	'op'  => "like",
+	'prefix' => "%",
+	'suffix' => "%",
+	'width'  => "",
+	'value'  => "");
 
 ?>
diff --git a/interface/web/monitor/templates/dataloghistory_list.htm b/interface/web/monitor/templates/dataloghistory_list.htm
index 0cd3c4f4d27f52fa40977b3e00b80bf0c65cfbb4..61bf042993a4f0449684180b56081a2bda46da34 100644
--- a/interface/web/monitor/templates/dataloghistory_list.htm
+++ b/interface/web/monitor/templates/dataloghistory_list.htm
@@ -15,6 +15,7 @@
                         <th data-column="server_id"><tmpl_var name="server_id_txt"></th>
                         <th data-column="action"><tmpl_var name="action_txt"></th>
                         <th data-column="dbtable"><tmpl_var name="dbtable_txt"></th>
+                        <th data-column="user"><tmpl_var name="user_txt"></th>
                         <th class="small-col text-right">{tmpl_var name='search_limit'}</th>
                     </tr>
                     <tr>
@@ -22,6 +23,8 @@
                         <td><select class="form-control" name="search_server_id">{tmpl_var name='search_server_id'}</select></td>
                         <td><select class="form-control" name="search_action">{tmpl_var name='search_action'}</select></td>
                         <td><input class="form-control" type="text" name="search_dbtable" value="{tmpl_var name='search_dbtable'}" /></td>
+                        <td><input class="form-control" type="text" name="search_user" value="{tmpl_var name='search_user'}" /></td>
+                        
                         <td class="text-right">
                             <button type="button" class="btn btn-default formbutton-default formbutton-narrow" name="Filter" id="Filter" value="{tmpl_var name="filter_txt"}" data-submit-form="pageForm" data-form-action="monitor/dataloghistory_list.php"><span class="icon icon-filter"></span></button>
                         </td>
@@ -34,18 +37,19 @@
                             <td><a href="#" data-load-content="monitor/dataloghistory_view.php?id={tmpl_var name='id'}">{tmpl_var name="server_id"}</a></td>
                             <td><a href="#" data-load-content="monitor/dataloghistory_view.php?id={tmpl_var name='id'}">{tmpl_var name="action"}</a></td>
                             <td><a href="#" data-load-content="monitor/dataloghistory_view.php?id={tmpl_var name='id'}">{tmpl_var name="dbtable"}</a></td>
+                            <td><a href="#" data-load-content="monitor/dataloghistory_view.php?id={tmpl_var name='id'}">{tmpl_var name="user"}</a></td>
                             <td class="text-right"></td>
                         </tr>
                     </tmpl_loop>
                     <tmpl_unless name="records">
                         <tr class="tbl_row_noresults tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
-                            <td colspan="5">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
+                            <td colspan="6">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
                         </tr>
                     </tmpl_unless>
                 </tbody>
                 <tfoot>
                     <tr>
-                        <td colspan="5"><tmpl_var name="paging"></td>
+                        <td colspan="6"><tmpl_var name="paging"></td>
                     </tr>
                 </tfoot>
             </table>
diff --git a/interface/web/sites/templates/ftp_sites_stats_list.htm b/interface/web/sites/templates/ftp_sites_stats_list.htm
index 9474bb2fdad7317888fe2e410909df0797a52729..f6739552fcd750b5dd3742bdfbfcd112c1910e98 100644
--- a/interface/web/sites/templates/ftp_sites_stats_list.htm
+++ b/interface/web/sites/templates/ftp_sites_stats_list.htm
@@ -30,10 +30,10 @@
 		<tmpl_loop name="records">
 			<tr>
 				<td><a target="_blank" href="http://{tmpl_var name="domain"}/stats">{tmpl_var name="domain"}</a></td>
-				<td><a href="#" data-load-content="sites/web_<tmpl_if name='type' op='==' value='vhostsubdomain'>vhost_sub</tmpl_if><tmpl_if name='type' op='==' value='vhostalias'>vhost_alias</tmpl_if>domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="this_month_in"}/{tmpl_var name="this_month_out"}</a></td>
-				<td><a href="#" data-load-content="sites/web_<tmpl_if name='type' op='==' value='vhostsubdomain'>vhost_sub</tmpl_if><tmpl_if name='type' op='==' value='vhostalias'>vhost_alias</tmpl_if>domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="last_month_in"}/{tmpl_var name="last_month_out"}</a></td>
-				<td><a href="#" data-load-content="sites/web_<tmpl_if name='type' op='==' value='vhostsubdomain'>vhost_sub</tmpl_if><tmpl_if name='type' op='==' value='vhostalias'>vhost_alias</tmpl_if>domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="this_year_in"}/{tmpl_var name="this_year_out"}</a></td>
-				<td><a href="#" data-load-content="sites/web_<tmpl_if name='type' op='==' value='vhostsubdomain'>vhost_sub</tmpl_if><tmpl_if name='type' op='==' value='vhostalias'>vhost_alias</tmpl_if>domain_edit.php?id={tmpl_var name='id'}">{tmpl_var name="last_year_in"}/{tmpl_var name="last_year_out"}</a></td>
+				<td><a href="#" data-load-content="sites/web_vhost_domain_edit.php?id={tmpl_var name='id'}&type={tmpl_var name='vhostdomain_type'}">{tmpl_var name="this_month_in"}/{tmpl_var name="this_month_out"}</a></td>
+				<td><a href="#" data-load-content="sites/web_vhost_domain_edit.php?id={tmpl_var name='id'}&type={tmpl_var name='vhostdomain_type'}">{tmpl_var name="last_month_in"}/{tmpl_var name="last_month_out"}</a></td>
+				<td><a href="#" data-load-content="sites/web_vhost_domain_edit.php?id={tmpl_var name='id'}&type={tmpl_var name='vhostdomain_type'}">{tmpl_var name="this_year_in"}/{tmpl_var name="this_year_out"}</a></td>
+				<td><a href="#" data-load-content="sites/web_vhost_domain_edit.php?id={tmpl_var name='id'}&type={tmpl_var name='vhostdomain_type'}">{tmpl_var name="last_year_in"}/{tmpl_var name="last_year_out"}</a></td>
 				<td class="text-right"></td>
 			</tr>
 		</tmpl_loop>
diff --git a/interface/web/sites/templates/shell_user_edit.htm b/interface/web/sites/templates/shell_user_edit.htm
index c1c23965f14caa87033e9fc42c2a0185b7e33311..e96986a9fd3edccb7aa0d57867f9104eef9e1875 100644
--- a/interface/web/sites/templates/shell_user_edit.htm
+++ b/interface/web/sites/templates/shell_user_edit.htm
@@ -17,7 +17,11 @@
                 <div class="col-sm-9">
 					<div class="input-group">
 						<span class="input-group-addon" id="username-desc">{tmpl_var name='username_prefix'}</span>
-						<input type="text" name="username" id="username" value="{tmpl_var name='username'}" class="form-control" aria-describedby="username-desc" />
+						<input type="text" name="username" id="username" value="{tmpl_var name='username'}" class="form-control" aria-describedby="username-desc" style="width: 90%" />
+						<a class="btn btn-default formbutton-narrow" href="javascript: navigator.clipboard.writeText(document.getElementById('username-desc').innerText + document.getElementById('username').value);" title="{tmpl_var name='copy_to_clipboard_txt'}">
+							<span class="fa fa-clone"></span>
+						</a>
+
 					</div>
 				</div>
             </div>
diff --git a/interface/web/themes/default/assets/javascripts/ispconfig.js b/interface/web/themes/default/assets/javascripts/ispconfig.js
index 18940f6f3ba183a8af83e54bab0db50d5d6bf5d8..54d5cd3c640059d4bb663882d63d8d75d0cc10b5 100644
--- a/interface/web/themes/default/assets/javascripts/ispconfig.js
+++ b/interface/web/themes/default/assets/javascripts/ispconfig.js
@@ -223,7 +223,7 @@ var ISPConfig = {
 
 		var frame_id = 'ajaxUploader-iframe-' + Math.round(new Date().getTime() / 1000);
 		$('body').append('<iframe width="0" height="0" style="display:none;" name="'+frame_id+'" id="'+frame_id+'"/>');
-		$('#'+frame_id).load(function() {
+		$('#'+frame_id).on("load", function() {
 			var msg = handleResponse(this);
 			$('#errorMsg').remove();
 			$('#OKMsg').remove();
diff --git a/interface/web/themes/default/assets/stylesheets/ispconfig.css b/interface/web/themes/default/assets/stylesheets/ispconfig.css
index b614bebdf5ed1fe4e60fca4a4b1ba4e59e6fb924..03beca183659047bd4632f7db2b425b127c93549 100644
--- a/interface/web/themes/default/assets/stylesheets/ispconfig.css
+++ b/interface/web/themes/default/assets/stylesheets/ispconfig.css
@@ -115,7 +115,7 @@ body {
     padding: 0 12px;
     height: 70px;
     border-bottom-style: solid;
-    botder-bottom-width: 2px;
+    border-bottom-width: 1px;
     transition: all ease 500ms; }
   #main-navigation .icon {
     font-size: 32px; }
diff --git a/interface/web/tools/form/user_settings.tform.php b/interface/web/tools/form/user_settings.tform.php
index f063634b0ccf96ed6222acb33274c81b7dbd9ea2..85cdda08471d49d45f34e096cdb4119d3227f5ff 100644
--- a/interface/web/tools/form/user_settings.tform.php
+++ b/interface/web/tools/form/user_settings.tform.php
@@ -119,6 +119,10 @@ if($_SESSION["s"]["user"]["typ"] == 'admin') {
 	}
 }
 
+$otp_method_list = array(
+	'none' => 'none',
+	'email' => 'email',
+);
 //* Load themes
 $themes_list = array();
 $handle = @opendir(ISPC_THEMES_PATH);
@@ -163,6 +167,25 @@ $form['tabs']['users'] = array (
 			'rows'  => '',
 			'cols'  => ''
 		),
+		'otp_type' => array(
+			'datatype' => 'VARCHAR',
+			'formtype' => 'SELECT',
+			'validators' => array (  0 => array (    'type' => 'NOTEMPTY',
+			'errmsg'=> 'otp_auth_empty'),
+			1 => array (    'type' => 'REGEX',
+			'regex' => '/^[a-z0-9\_]{0,64}$/',
+			'errmsg'=> 'otp_auth_regex'),
+			),
+			'regex'  => '',
+			'errmsg' => '',
+			'default' => '',
+			'value'  => $otp_method_list,
+			'separator' => '',
+			'width'  => '30',
+			'maxlength' => '255',
+			'rows'  => '',
+			'cols'  => ''
+		),
 		'language' => array (
 			'datatype' => 'VARCHAR',
 			'formtype' => 'SELECT',
diff --git a/interface/web/tools/lib/lang/ar_usersettings.lng b/interface/web/tools/lib/lang/ar_usersettings.lng
index c05b94e76e77b6f2c2548b8f3dc9607ba91d228f..ac3339f448b0f861f7701f03aeb01af081ec6a2a 100644
--- a/interface/web/tools/lib/lang/ar_usersettings.lng
+++ b/interface/web/tools/lib/lang/ar_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/bg_usersettings.lng b/interface/web/tools/lib/lang/bg_usersettings.lng
index c30dcf37019f205569a250bd4addd21cf6961e6a..93cbf9441728149843566af79f2053dc0f7f507c 100644
--- a/interface/web/tools/lib/lang/bg_usersettings.lng
+++ b/interface/web/tools/lib/lang/bg_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/br_usersettings.lng b/interface/web/tools/lib/lang/br_usersettings.lng
index 8e6829a8c027b923b5d700d4f5144b039bbcf5af..a8bb10a34372a2a919e9cfb9e5bbf8b8ae541bd6 100644
--- a/interface/web/tools/lib/lang/br_usersettings.lng
+++ b/interface/web/tools/lib/lang/br_usersettings.lng
@@ -15,3 +15,4 @@ $wb['startmodule_empty'] = 'Módulo inicial está vazio.';
 $wb['startmodule_regex'] = 'Caracteres inválidos no módulo inicial.';
 $wb['app_theme_empty'] = 'Tema está vazio.';
 $wb['app_theme_regex'] = 'Caracteres inválidos no tema.';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
diff --git a/interface/web/tools/lib/lang/ca_usersettings.lng b/interface/web/tools/lib/lang/ca_usersettings.lng
index 4705660b9e1489cdd8fdcdaadd22561a4892d410..74dfb3281d8b0446ed32b29d3fc0da2091f8cb32 100644
--- a/interface/web/tools/lib/lang/ca_usersettings.lng
+++ b/interface/web/tools/lib/lang/ca_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Les mots de passe correspondent.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Page d\'accueil';
 $wb['app_theme_txt'] = 'Interface';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/cz_usersettings.lng b/interface/web/tools/lib/lang/cz_usersettings.lng
index 3805d25b3a6a144835d8a7d499717729bf8ab0ba..c3ded6184d09917be0a99248b45bf722652595e2 100644
--- a/interface/web/tools/lib/lang/cz_usersettings.lng
+++ b/interface/web/tools/lib/lang/cz_usersettings.lng
@@ -15,3 +15,4 @@ $wb['startmodule_empty'] = 'Startmodule empty.';
 $wb['startmodule_regex'] = 'Invalid chars in Startmodule.';
 $wb['app_theme_empty'] = 'App theme empty.';
 $wb['app_theme_regex'] = 'Invalid chars in App theme.';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
diff --git a/interface/web/tools/lib/lang/de_usersettings.lng b/interface/web/tools/lib/lang/de_usersettings.lng
index dd5fefffae16a756fc596ae7566cedefe27d495f..e66f2db650f617d2eabd537f70bc02afd8b32e65 100644
--- a/interface/web/tools/lib/lang/de_usersettings.lng
+++ b/interface/web/tools/lib/lang/de_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Die Passwörter stimmen überein.';
 $wb['language_txt'] = 'Sprache';
 $wb['startmodule_txt'] = 'Startmodul';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/dk_usersettings.lng b/interface/web/tools/lib/lang/dk_usersettings.lng
index 341d9db757b08e847b3d0aa5b7ece8781959764a..e413c61f1b360a3e2efe9757ddc0d172792edf89 100644
--- a/interface/web/tools/lib/lang/dk_usersettings.lng
+++ b/interface/web/tools/lib/lang/dk_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_txt'] = 'Password';
 $wb['language_txt'] = 'Sprog';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/el_usersettings.lng b/interface/web/tools/lib/lang/el_usersettings.lng
index 68ddcd657c44dac297d32edcc570ceb6bd06b10c..4158c9fc0ee1b6fe7f66eb8d85032265a302ffcd 100644
--- a/interface/web/tools/lib/lang/el_usersettings.lng
+++ b/interface/web/tools/lib/lang/el_usersettings.lng
@@ -11,4 +11,5 @@ $wb['password_mismatch_txt'] = 'The passwords do not match.';
 $wb['password_match_txt'] = 'The passwords do match.';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/en.lng b/interface/web/tools/lib/lang/en.lng
index 7794543497984f911d29364e2b6497c39ab5940d..eff8a133231bfd8974da242398f0470b45fc5dbf 100644
--- a/interface/web/tools/lib/lang/en.lng
+++ b/interface/web/tools/lib/lang/en.lng
@@ -10,4 +10,4 @@ $wb['Resync'] = 'Resync';
 $wb['Import'] = 'Import';
 $wb['ISPConfig 3 mail'] = 'ISPConfig 3 mail';
 $wb['PDNS Tupa'] = 'PowerDNS Tupa';
-?>
\ No newline at end of file
+?>
diff --git a/interface/web/tools/lib/lang/en_usersettings.lng b/interface/web/tools/lib/lang/en_usersettings.lng
index 421805e7896ebe54e961752415dd7cfa46244179..458eef7606042fe4019e35292cdfbb75d056a529 100644
--- a/interface/web/tools/lib/lang/en_usersettings.lng
+++ b/interface/web/tools/lib/lang/en_usersettings.lng
@@ -16,4 +16,5 @@ $wb['startmodule_empty'] = 'Startmodule empty.';
 $wb['startmodule_regex'] = 'Invalid chars in Startmodule.';
 $wb['app_theme_empty'] = 'App theme empty.';
 $wb['app_theme_regex'] = 'Invalid chars in App theme.';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/es_usersettings.lng b/interface/web/tools/lib/lang/es_usersettings.lng
index 43a181a11c7337042c0faada5357b30b53aae228..b3a6390948a432c9d6023b85f9f75854e4f31d80 100644
--- a/interface/web/tools/lib/lang/es_usersettings.lng
+++ b/interface/web/tools/lib/lang/es_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Las contraseñas coinciden.';
 $wb['language_txt'] = 'Idioma';
 $wb['startmodule_txt'] = 'Módulo de inicio';
 $wb['app_theme_txt'] = 'Diseño';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/fi_usersettings.lng b/interface/web/tools/lib/lang/fi_usersettings.lng
index 91d71739537e6d663f4a6e9fc043ab5f73af5fed..888b1c7eb64d46a4dc3e961ee38378bda61eda77 100644
--- a/interface/web/tools/lib/lang/fi_usersettings.lng
+++ b/interface/web/tools/lib/lang/fi_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/fr_usersettings.lng b/interface/web/tools/lib/lang/fr_usersettings.lng
index b398e76e352ccb6b168473b29f74bcbf6c5b932f..57f47dc9fbb82bc1c211dc4fb92cf16c1b670d19 100644
--- a/interface/web/tools/lib/lang/fr_usersettings.lng
+++ b/interface/web/tools/lib/lang/fr_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Les mots de passe correspondent.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/hr_usersettings.lng b/interface/web/tools/lib/lang/hr_usersettings.lng
index b707cce4da55bf35f0c771408c92f95fd0464457..cf206223395f8b6c4016cbc14a8e1101b0efcec2 100644
--- a/interface/web/tools/lib/lang/hr_usersettings.lng
+++ b/interface/web/tools/lib/lang/hr_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Šifre su identične.';
 $wb['language_txt'] = 'Jezik';
 $wb['startmodule_txt'] = 'Početna stranica';
 $wb['app_theme_txt'] = 'Tema';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/hu_usersettings.lng b/interface/web/tools/lib/lang/hu_usersettings.lng
index 2a89acf5b5f926929859300cc3e573566b55fc1c..35bb4a60dee5ebb226d8b75c1e02d341119e66be 100644
--- a/interface/web/tools/lib/lang/hu_usersettings.lng
+++ b/interface/web/tools/lib/lang/hu_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/id_usersettings.lng b/interface/web/tools/lib/lang/id_usersettings.lng
index 760cfe75f244d893433fc863f683093816a11c00..1a63a8b41c399aefdd28cc5c193df9a711a34278 100644
--- a/interface/web/tools/lib/lang/id_usersettings.lng
+++ b/interface/web/tools/lib/lang/id_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/it_usersettings.lng b/interface/web/tools/lib/lang/it_usersettings.lng
index 0f1cefe1bf3411eeb539324b6927dd3ac96dfe26..e291041b1c61cbaea57ccf2c7f049f7dc6fef266 100644
--- a/interface/web/tools/lib/lang/it_usersettings.lng
+++ b/interface/web/tools/lib/lang/it_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Le password coincidono.';
 $wb['language_txt'] = 'Lingua pannello';
 $wb['startmodule_txt'] = 'Modulo di avvio';
 $wb['app_theme_txt'] = 'Apparenza';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/ja_usersettings.lng b/interface/web/tools/lib/lang/ja_usersettings.lng
index 291aa94537208f694c4b6e49eabe059d7ac8f085..d5ba174fde29f7690d6e6c3a8c842822d5bc07fa 100644
--- a/interface/web/tools/lib/lang/ja_usersettings.lng
+++ b/interface/web/tools/lib/lang/ja_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/nl_usersettings.lng b/interface/web/tools/lib/lang/nl_usersettings.lng
index 909df9dbecf4bcadca6266477ec37b276581f1ee..cb31a68d209977df2ee0ab01c6ae354562738ebe 100644
--- a/interface/web/tools/lib/lang/nl_usersettings.lng
+++ b/interface/web/tools/lib/lang/nl_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Taal';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Twee-factor Authenticatie';
 ?>
diff --git a/interface/web/tools/lib/lang/pl_usersettings.lng b/interface/web/tools/lib/lang/pl_usersettings.lng
index 64396df2409dbb08ea741cd5d7ea7551ce5769c1..1bb9a69ae7525a61a7bea81e02c91331cc0551dc 100644
--- a/interface/web/tools/lib/lang/pl_usersettings.lng
+++ b/interface/web/tools/lib/lang/pl_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Hasła się zgadzają';
 $wb['language_txt'] = 'Język';
 $wb['startmodule_txt'] = 'Moduł startowy';
 $wb['app_theme_txt'] = 'Temat';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/pt_usersettings.lng b/interface/web/tools/lib/lang/pt_usersettings.lng
index 4925a3f7286da3e7a1fc9c74205d7dcd4217ccfe..b5ca31359e3cfc3e9b6443be984572b68973855e 100644
--- a/interface/web/tools/lib/lang/pt_usersettings.lng
+++ b/interface/web/tools/lib/lang/pt_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/ro_usersettings.lng b/interface/web/tools/lib/lang/ro_usersettings.lng
index 8c43550f33cc56729cd5902089e60d21b5732e25..7c826d923b62e6958ee82b9cb178561dfcff642f 100644
--- a/interface/web/tools/lib/lang/ro_usersettings.lng
+++ b/interface/web/tools/lib/lang/ro_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/ru_usersettings.lng b/interface/web/tools/lib/lang/ru_usersettings.lng
index ffa3f3bf03116cf1d8b3cd4b97c38114e4762b28..d8e091e55364e47b9e2528a231f34855f41d8bcb 100644
--- a/interface/web/tools/lib/lang/ru_usersettings.lng
+++ b/interface/web/tools/lib/lang/ru_usersettings.lng
@@ -14,4 +14,5 @@ $wb['interface_desc_txt'] = 'Измените свой интерфейс';
 $wb['language_txt'] = 'Язык';
 $wb['startmodule_txt'] = 'Стартовый модуль';
 $wb['app_theme_txt'] = 'Тема';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/se_usersettings.lng b/interface/web/tools/lib/lang/se_usersettings.lng
index f6de2dc4eebe227af1be4cfe0e5de3bd5ee7eff1..9680936d7bee1af79c3f846b9d90b66a7156e368 100644
--- a/interface/web/tools/lib/lang/se_usersettings.lng
+++ b/interface/web/tools/lib/lang/se_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Lösenorden matchar';
 $wb['language_txt'] = 'Språk';
 $wb['startmodule_txt'] = 'Startmodul';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/sk_usersettings.lng b/interface/web/tools/lib/lang/sk_usersettings.lng
index e00f5e664b1bb4bcb71a6614446dec2530c1aa21..ee1ff41888281bcecd049c124a68679526cced82 100644
--- a/interface/web/tools/lib/lang/sk_usersettings.lng
+++ b/interface/web/tools/lib/lang/sk_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'The passwords do match.';
 $wb['language_txt'] = 'Language';
 $wb['startmodule_txt'] = 'Startmodule';
 $wb['app_theme_txt'] = 'Design';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/lib/lang/tr_usersettings.lng b/interface/web/tools/lib/lang/tr_usersettings.lng
index a1fd7c56d4cddc2fd47065819f46c37917369bfb..81ea3ed5f6ed1a851a34b1449c395a3fa96a3a25 100644
--- a/interface/web/tools/lib/lang/tr_usersettings.lng
+++ b/interface/web/tools/lib/lang/tr_usersettings.lng
@@ -12,4 +12,5 @@ $wb['password_match_txt'] = 'Parola ile onayı aynı.';
 $wb['language_txt'] = 'Dil';
 $wb['startmodule_txt'] = 'Başlangıç modülü';
 $wb['app_theme_txt'] = 'Tasarım';
+$wb['otp_auth_txt'] = 'Two Factor Authentication';
 ?>
diff --git a/interface/web/tools/templates/user_settings.htm b/interface/web/tools/templates/user_settings.htm
index a620f419c54d58ed5ad4e3b044c8410b10d46160..f430b64195d29cb56cb3a52e74355101b0db64c5 100644
--- a/interface/web/tools/templates/user_settings.htm
+++ b/interface/web/tools/templates/user_settings.htm
@@ -26,6 +26,14 @@
     <div id="confirmpasswordOK" style="display:none;" class="confirmpasswordok">{tmpl_var name='password_match_txt'}</div>
   </div>
 </div>
+<div class="form-group">
+  <label for="2fa" class="col-sm-3 control-label">{tmpl_var name='otp_auth_txt'}</label>
+  <div class="col-sm-9">
+    <select name="otp_type" id="otp_type" class="form-control">
+      {tmpl_var name='otp_type'}
+    </select>
+  </div>
+</div>
 <div class="form-group">
   <label for="language" class="col-sm-3 control-label">{tmpl_var name='language_txt'}</label>
   <div class="col-sm-9"><select name="language" id="language" class="form-control flags">
diff --git a/remoting_client/API-docs/mail_user_get_all_by_client.html b/remoting_client/API-docs/mail_user_get_all_by_client.html
new file mode 100644
index 0000000000000000000000000000000000000000..2ddbc1655637b3f42313ab69bb6eda2acb085c03
--- /dev/null
+++ b/remoting_client/API-docs/mail_user_get_all_by_client.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head><title>ISPCOnfig 3 remote API documentation</title>
+
+  
+
+  
+  
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="definitionen.css">
+  <style type="text/css">
+
+  </style></head>
+
+<body>
+<div style="padding:40px">
+<h1>mail_user_get_all_by_client(<span class="var">$session_id</span>, <span class="var">$client_id</span>);</h1>
+<br>
+<p class="headgrp">Description: </p>
+<p class="margin"> Retrieves information about the mail users belonging to a client.</p><br>
+<p class="headgrp">Input Variables: </p> 
+<p class="margin"> <span class="var">$session_id</span>, <span class="var">$primary_id</span></p>
+<p class="headgrp">Parameters (in <span class="var">$params</span>): </p>
+<p class="margin"> None</p>
+<p class="headgrp">Output: </p> 
+<p class="margin"> Returns all fields and values of the chosen mail users.</p>
+<!--<b>Output:</b> 
+<p style="margin-left:100px">Gives a record of </p> -->
+</div>
+
+</body></html>
diff --git a/remoting_client/examples/mail_user_get.php b/remoting_client/examples/mail_user_get.php
index cdec8b7c1eca5a1f52bcf5db13fb325ff84fe705..247d98c15b751a9cf3dd52e5281db725784052af 100644
--- a/remoting_client/examples/mail_user_get.php
+++ b/remoting_client/examples/mail_user_get.php
@@ -17,9 +17,13 @@ try {
 	//* Set the function parameters.
 	$mailuser_id = 1;
 
-	$app = $client->mail_user_get($session_id, $mailuser_id);
+	// Lookup by primary key, gets back a single record.
+	$mail_user = $client->mail_user_get($session_id, $mailuser_id);
+	print_r($mail_user);
 
-	print_r($app);
+	// Lookup by pattern gives an array of records.
+	$mail_users_array = $client->mail_user_get($session_id, array('email' => '%@example.com'));
+	print_r($mail_user_array);
 
 	if($client->logout($session_id)) {
 		echo 'Logged out.<br />';
diff --git a/remoting_client/examples/mail_user_get_all_by_client.php b/remoting_client/examples/mail_user_get_all_by_client.php
new file mode 100644
index 0000000000000000000000000000000000000000..e90a31f127b8b0566b905ea1866aa6b323f583c5
--- /dev/null
+++ b/remoting_client/examples/mail_user_get_all_by_client.php
@@ -0,0 +1,34 @@
+<?php
+
+require 'soap_config.php';
+
+
+$client = new SoapClient(null, array('location' => $soap_location,
+		'uri'      => $soap_uri,
+		'trace' => 1,
+		'exceptions' => 1));
+
+
+try {
+	if($session_id = $client->login($username, $password)) {
+		echo 'Logged successfull. Session ID:'.$session_id.'<br />';
+	}
+
+	//* Set the function parameters.
+	$client_id = 1;
+
+	$app = $client->mail_user_get_all_by_client($session_id, $client_id);
+
+	print_r($app);
+
+	if($client->logout($session_id)) {
+		echo 'Logged out.<br />';
+	}
+
+
+} catch (SoapFault $e) {
+	echo $client->__getLastResponse();
+	die('SOAP Error: '.$e->getMessage());
+}
+
+?>
diff --git a/server/conf/nginx_vhost.conf.master b/server/conf/nginx_vhost.conf.master
index 1c219f0cd4654ef88356afd1f67a95d3577baab9..400d9b9af2a00f57463a2b762c7a29d79c80968c 100644
--- a/server/conf/nginx_vhost.conf.master
+++ b/server/conf/nginx_vhost.conf.master
@@ -69,6 +69,16 @@ server {
         <tmpl_if name='exclude_own_hostname'>if ($http_host != "<tmpl_var name='exclude_own_hostname'>") { </tmpl_if>rewrite ^<tmpl_var name='rewrite_exclude'>(.*)$ <tmpl_var name='rewrite_target'>$2 <tmpl_var name='rewrite_type'>;<tmpl_if name='exclude_own_hostname'> }</tmpl_if>
 </tmpl_if>
 <tmpl_if name='use_proxy'>
+        ## no proxy for acme-challenge
+        location ^~ /.well-known/acme-challenge/ {
+            access_log off;
+            log_not_found off;
+            root /usr/local/ispconfig/interface/acme/;
+            autoindex off;
+            index index.html;
+            try_files $uri $uri/ =404;
+        }
+
         location / {
             proxy_pass <tmpl_var name='rewrite_target'>;
             <tmpl_if name='rewrite_subdir'>rewrite ^/<tmpl_var name='rewrite_subdir'>(.*) /$1;</tmpl_if>
diff --git a/server/lib/classes/cron.d/200-ftplogfiles.inc.php b/server/lib/classes/cron.d/200-ftplogfiles.inc.php
index 36b43352404153dcde58ee8e857de9bd6830011d..a88a360ae2cb32ff99face8352686f43bf7a2a07 100644
--- a/server/lib/classes/cron.d/200-ftplogfiles.inc.php
+++ b/server/lib/classes/cron.d/200-ftplogfiles.inc.php
@@ -32,7 +32,17 @@ class cronjob_ftplogfiles extends cronjob {
 		// Make the ftp logfiles directories world readable to enable ftp access
 		//######################################################################################################
 
-		if(is_dir('/var/log/pure-ftpd/')) exec('chmod +r /var/log/pure-ftpd/*');
+		$logfile = null;
+
+		if(is_dir('/var/log/pure-ftpd/')) {
+			exec('chmod +r /var/log/pure-ftpd/*');
+			$logfile="/var/log/pure-ftpd/transfer.log.1";
+		} elseif(is_file('/var/log/pureftpd.log')) {
+			$logfile="/var/log/pureftpd.log";
+		} else {
+			$app->log("The pure-ftpd log file could not be found.", LOGLEVEL_DEBUG);
+			return false;
+		}
 
 		//######################################################################################################
 		// Manage and compress ftp logfiles and create traffic statistics
@@ -71,7 +81,7 @@ class cronjob_ftplogfiles extends cronjob {
 			}
 		}
 		
-		$fp = @fopen('/var/log/pure-ftpd/transfer.log.1', 'r');
+		$fp = @fopen($logfile, 'r');
 		$ftp_traffic = array();
 
 		if ($fp) {
diff --git a/server/lib/classes/cron.d/300-quota_notify.inc.php b/server/lib/classes/cron.d/300-quota_notify.inc.php
index ac7ae0aa5c70fab9c8e539145f558c950d174563..08cd283ef78834d67ed011fc2e3b124b1a380121 100644
--- a/server/lib/classes/cron.d/300-quota_notify.inc.php
+++ b/server/lib/classes/cron.d/300-quota_notify.inc.php
@@ -57,6 +57,13 @@ class cronjob_quota_notify extends cronjob {
 
 		$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
 
+		// Get client email and eventual reseller email
+		$client_group_id = $rec["sys_groupid"];
+		$client = $app->db->queryOneRecord("SELECT client.email, client.parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
+		if($client['parent_client_id'] > 0) {
+			$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
+		}
+
 		//######################################################################################################
 		// enforce traffic quota (run only on the "master-server")
 		//######################################################################################################
@@ -90,7 +97,7 @@ class cronjob_quota_notify extends cronjob {
 							$app->log('Traffic quota for '.$rec['domain'].' exceeded.', LOGLEVEL_DEBUG);
 						}
 						//* Send traffic notifications
-						if($rec['traffic_quota_lock'] != 'y' && ($web_config['overtraffic_notify_admin'] == 'y' || $web_config['overtraffic_notify_client'] == 'y')) {
+						if($rec['traffic_quota_lock'] != 'y' && ($web_config['overtraffic_notify_admin'] == 'y' || $web_config['overtraffic_notify_reseller'] == 'y' || $web_config['overtraffic_notify_client'] == 'y')) {
 
 							$placeholders = array('{domain}' => $rec['domain'],
 								'{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
@@ -105,10 +112,15 @@ class cronjob_quota_notify extends cronjob {
 								$recipients[] = $global_config['admin_mail'];
 							}
 
+							//* Send email to reseller
+							if($web_config['overtraffic_notify_reseller'] == 'y') {
+								if($reseller['email'] != '') {
+									$recipients[] = $reseller['email'];
+								}
+							}
+
 							//* Send email to client
 							if($web_config['overtraffic_notify_client'] == 'y') {
-								$client_group_id = $rec["sys_groupid"];
-								$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
 								if($client['email'] != '') {
 									$recipients[] = $client['email'];
 								}
@@ -216,7 +228,7 @@ class cronjob_quota_notify extends cronjob {
 						if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('web_domain', array("last_quota_notification" => null), 'domain_id', $rec['domain_id']);
 
 						// send notification - everything ok again
-						if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y')) {
+						if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_reseller'] == 'y' || $web_config['overquota_notify_client'] == 'y')) {
 							$placeholders = array('{domain}' => $rec['domain'],
 								'{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
 								'{used}' => $rec['used'],
@@ -231,10 +243,15 @@ class cronjob_quota_notify extends cronjob {
 								$recipients[] = $global_config['admin_mail'];
 							}
 
+							//* Send email to reseller
+							if($web_config['overquota_notify_reseller'] == 'y') {
+								if($reseller['email'] != '') {
+									$recipients[] = $reseller['email'];
+								}
+							}
+
 							//* Send email to client
 							if($web_config['overquota_notify_client'] == 'y') {
-								$client_group_id = $rec["sys_groupid"];
-								$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
 								if($client['email'] != '') {
 									$recipients[] = $client['email'];
 								}
@@ -249,7 +266,7 @@ class cronjob_quota_notify extends cronjob {
 						elseif($web_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $web_config['overquota_notify_freq']) $send_notification = true;
 
 						//* Send quota notifications
-						if(($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y') && $send_notification == true) {
+						if(($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_reseller'] == 'y' || $web_config['overquota_notify_client'] == 'y') && $send_notification == true) {
 							$app->dbmaster->datalogUpdate('web_domain', array("last_quota_notification" => date('Y-m-d')), 'domain_id', $rec['domain_id']);
 
 							$placeholders = array('{domain}' => $rec['domain'],
@@ -266,10 +283,15 @@ class cronjob_quota_notify extends cronjob {
 								$recipients[] = $global_config['admin_mail'];
 							}
 
+							//* Send email to reseller
+							if($web_config['overquota_notify_reseller'] == 'y') {
+								if($reseller['email'] != '') {
+									$recipients[] = $reseller['email'];
+								}
+							}
+
 							//* Send email to client
 							if($web_config['overquota_notify_client'] == 'y') {
-								$client_group_id = $rec["sys_groupid"];
-								$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
 								if($client['email'] != '') {
 									$recipients[] = $client['email'];
 								}
@@ -345,7 +367,7 @@ class cronjob_quota_notify extends cronjob {
 						if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('mail_user', array("last_quota_notification" => null), 'mailuser_id', $rec['mailuser_id']);
 
 						// send notification - everything ok again
-						if($rec['last_quota_notification'] && $mail_config['overquota_notify_onok'] == 'y' && ($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y')) {
+						if($rec['last_quota_notification'] && $mail_config['overquota_notify_onok'] == 'y' && ($mail_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_reseller'] == 'y' || $mail_config['overquota_notify_client'] == 'y')) {
 							$placeholders = array('{email}' => $rec['email'],
 								'{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
 								'{used}' => $rec['used'],
@@ -359,10 +381,15 @@ class cronjob_quota_notify extends cronjob {
 								$recipients[] = $global_config['admin_mail'];
 							}
 
+							//* Send email to reseller
+							if($web_config['overquota_notify_reseller'] == 'y') {
+								if($reseller['email'] != '') {
+									$recipients[] = $reseller['email'];
+								}
+							}
+
 							//* Send email to client
 							if($mail_config['overquota_notify_client'] == 'y') {
-								$client_group_id = $rec["sys_groupid"];
-								$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
 								if($client['email'] != '') {
 									$recipients[] = $client['email'];
 								}
@@ -378,7 +405,7 @@ class cronjob_quota_notify extends cronjob {
 						if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
 						elseif($mail_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $mail_config['overquota_notify_freq']) $send_notification = true;
 
-						if(($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y') && $send_notification == true) {
+						if(($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_reseller'] == 'y' || $mail_config['overquota_notify_client'] == 'y') && $send_notification == true) {
 							$app->dbmaster->datalogUpdate('mail_user', array("last_quota_notification" => date('Y-m-d')), 'mailuser_id', $rec['mailuser_id']);
 
 							$placeholders = array('{email}' => $rec['email'],
@@ -394,10 +421,15 @@ class cronjob_quota_notify extends cronjob {
 								$recipients[] = $global_config['admin_mail'];
 							}
 
+							//* Send email to reseller
+							if($web_config['overquota_notify_reseller'] == 'y') {
+								if($reseller['email'] != '') {
+									$recipients[] = $reseller['email'];
+								}
+							}
+
 							//* Send email to client
 							if($mail_config['overquota_notify_client'] == 'y') {
-								$client_group_id = $rec["sys_groupid"];
-								$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
 								if($client['email'] != '') {
 									$recipients[] = $client['email'];
 								}
@@ -448,9 +480,6 @@ class cronjob_quota_notify extends cronjob {
 						foreach($cid as $monitor) {
 
 							if ($monitor['database_name'] == $database) {
-								//* get the client
-								$client = $app->db->queryOneRecord("SELECT client.username, client.email FROM web_database, sys_group, client WHERE web_database.sys_groupid = sys_group.groupid AND sys_group.client_id = client.client_id AND web_database.database_name=?", $database);
-
 								//* check quota
 								if ($quota > 0) $used_ratio = $monitor['size'] / $quota;
 								else $used_ratio = 0;
@@ -465,7 +494,7 @@ class cronjob_quota_notify extends cronjob {
 
 
 									//* Send quota notifications
-									if(($web_config['overquota_db_notify_admin'] == 'y' || $web_config['overquota_db_notify_client'] == 'y') && $send_notification == true) {
+									if(($web_config['overquota_db_notify_admin'] == 'y' || $web_config['overquota_db_notify_reseller'] == 'y' || $web_config['overquota_db_notify_client'] == 'y') && $send_notification == true) {
 										$app->dbmaster->datalogUpdate('web_database', array("last_quota_notification" => date('Y-m-d')), 'database_id', $rec['database_id']);
 										$placeholders = array(
 											'{database_name}' => $rec['database_name'],
@@ -481,10 +510,19 @@ class cronjob_quota_notify extends cronjob {
 										if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y')
 											$recipients[] = $global_config['admin_mail'];
 
+										//* Send email to reseller
+										if($web_config['overquota_db_notify_reseller'] == 'y') {
+											if($reseller['email'] != '') {
+												$recipients[] = $reseller['email'];
+											}
+										}
+										
 										//* Send email to client
-										if($web_config['overquota_db_notify_client'] == 'y' && $client['email'] != '')
-											$recipients[] = $client['email'];
-
+										if($web_config['overquota_db_notify_client'] == 'y') {
+											if($client['email'] != '') {
+												$recipients[] = $client['email'];
+											}
+										}
 										$this->_tools->send_notification_email('db_quota_notification', $placeholders, $recipients);
 
 									}
@@ -494,7 +532,7 @@ class cronjob_quota_notify extends cronjob {
 									if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('web_database', array("last_quota_notification" => null), 'database_id', $rec['database_id']);
 
 									// send notification - everything ok again
-									if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_db_notify_admin'] == 'y' || $web_config['overquota_db_notify_client'] == 'y')) {
+									if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_db_notify_admin'] == 'y' || $web_config['overquota_db_notify_reseller'] == 'y' || $web_config['overquota_db_notify_client'] == 'y')) {
 										$placeholders = array(
 											'{database_name}' => $rec['database_name'],
 											'{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
@@ -506,12 +544,24 @@ class cronjob_quota_notify extends cronjob {
 										$recipients = array();
 
 										//* send email to admin
-										if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y')
+										if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y') {
 											$recipients[] = $global_config['admin_mail'];
+										}
+
+										//* Send email to reseller
+										if($web_config['overquota_db_notify_reseller'] == 'y') {
+											if($reseller['email'] != '') {
+												$recipients[] = $reseller['email'];
+											}
+										}
 
 										//* Send email to client
-										if($web_config['overquota_db_notify_client'] == 'y' && $client['email'] != '')
-											$recipients[] = $client['email'];
+										if($mail_config['overquota_notify_client'] == 'y') {
+											if($client['email'] != '') {
+												$recipients[] = $client['email'];
+											}
+										}
+											
 
 										$this->_tools->send_notification_email('db_quota_ok_notification', $placeholders, $recipients);
 
diff --git a/server/plugins-available/bind_plugin.inc.php b/server/plugins-available/bind_plugin.inc.php
index 49fd043aff42a89753e81e28196d618468b18fbe..2deabc7e23a71f29f7747b313f72a70f529d1d7c 100644
--- a/server/plugins-available/bind_plugin.inc.php
+++ b/server/plugins-available/bind_plugin.inc.php
@@ -90,7 +90,7 @@ class bind_plugin {
 		if (!file_exists($dns_config['bind_zonefiles_dir'].'/'.$this->zone_file_prefix().$domain)) return false;
 
 		//* Check Entropy
-		if (file_get_contents('/proc/sys/kernel/random/entropy_avail') < 400) {
+		if (file_get_contents('/proc/sys/kernel/random/entropy_avail') < 200) {
 			$app->log('DNSSEC ERROR: We are low on entropy. Not generating new Keys for '.$domain.'. Please consider installing package haveged.', LOGLEVEL_WARN);
 			echo "DNSSEC ERROR: We are low on entropy. Not generating new Keys for $domain. Please consider installing package haveged.\n";
 			return false;
diff --git a/server/plugins-available/mail_plugin.inc.php b/server/plugins-available/mail_plugin.inc.php
index 2baf07ec7dd07ad69f7203b77924bb166cf1f8f9..53836a1392f50d4dda9268f83f464fa6ec78d149 100644
--- a/server/plugins-available/mail_plugin.inc.php
+++ b/server/plugins-available/mail_plugin.inc.php
@@ -429,8 +429,19 @@ class mail_plugin {
 		$maildir_path_deleted = false;
 		$old_maildir_path = $data['old']['maildir'];
 		if($old_maildir_path != $mail_config['homedir_path'] && strlen($old_maildir_path) > strlen($mail_config['homedir_path']) && !stristr($old_maildir_path, '//') && !stristr($old_maildir_path, '..') && !stristr($old_maildir_path, '*') && strlen($old_maildir_path) >= 10) {
-			$app->system->exec_safe('rm -rf ?', $old_maildir_path);
-			$app->log('Deleted the Maildir: '.$data['old']['maildir'], LOGLEVEL_DEBUG);
+			if ($mail_config['mailbox_soft_delete'] == 'y') {
+				// Move it, adding a date based suffix. A cronjob should purge or archive.
+				$thrash_maildir_path = $old_maildir_path . '-deleted-' . date("YmdHis");
+				$app->system->exec_safe('mv ? ?', $old_maildir_path, $thrash_maildir_path);
+
+				// Update the dir's timestamp to make filtering on age easier in any cleanup cronjob.
+				$app->system->exec_safe('touch ?', $thrash_maildir_path);
+
+				$app->log('Renamed the Maildir: ' . $data['old']['maildir'] . ' to ' . $thrash_maildir_path, LOGLEVEL_DEBUG);
+			} else  {
+				$app->system->exec_safe('rm -rf ?', $old_maildir_path);
+				$app->log('Deleted the Maildir: '.$data['old']['maildir'], LOGLEVEL_DEBUG);
+			}
 			$maildir_path_deleted = true;
 		} else {
 			$app->log('Possible security violation when deleting the maildir: '.$data['old']['maildir'], LOGLEVEL_ERROR);
@@ -473,8 +484,19 @@ class mail_plugin {
 		//* Delete maildomain path
 		$old_maildomain_path = $mail_config['homedir_path'].'/'.$data['old']['domain'];
 		if($old_maildomain_path != $mail_config['homedir_path'] && !stristr($old_maildomain_path, '//') && !stristr($old_maildomain_path, '..') && !stristr($old_maildomain_path, '*') && !stristr($old_maildomain_path, '&') && strlen($old_maildomain_path) >= 10  && !empty($data['old']['domain'])) {
-			$app->system->exec_safe('rm -rf ?', $old_maildomain_path);
-			$app->log('Deleted the mail domain directory: '.$old_maildomain_path, LOGLEVEL_DEBUG);
+			if ($mail_config['mailbox_soft_delete'] == 'y') {
+				// Move it, adding a date based suffix. A cronjob should purge or archive.
+				$thrash_maildomain_path = $old_maildomain_path . '-deleted-' . date("YmdHis");
+				$app->system->exec_safe('mv ? ?', $old_maildomain_path, $thrash_maildomain_path);
+
+				// Update the dir's timestamp to make filtering on age easier in any cleanup cronjob.
+				$app->system->exec_safe('touch ?', $thrash_maildomain_path);
+
+				$app->log('Renamed the mail domain directory: ' . $old_maildomain_path . ' to ' . $thrash_maildomain_path, LOGLEVEL_DEBUG);
+			} else  {
+				$app->system->exec_safe('rm -rf ?', $old_maildomain_path);
+				$app->log('Deleted the mail domain directory: '.$old_maildomain_path, LOGLEVEL_DEBUG);
+			}
 			$maildomain_path_deleted = true;
 		} else {
 			$app->log('Possible security violation when deleting the mail domain directory: '.$old_maildomain_path, LOGLEVEL_ERROR);
diff --git a/server/scripts/handle_mailbox_soft_deleted.sh b/server/scripts/handle_mailbox_soft_deleted.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7c7f280839d31233adabfd39832ed089e5fc66d3
--- /dev/null
+++ b/server/scripts/handle_mailbox_soft_deleted.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Archive directories for deleted mailboxes.
+delay_days=7
+
+# Test if there is something to do... to avoid 'No such file or directory' from find later.
+ls /var/vmail/*/[a-z0-9.-]*-deleted-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] >/dev/null 2>&1
+if [ $? != 0 ]; then
+        exit 0;
+fi
+
+function remove_soft_deleted_mailbox {
+        dir=$1
+
+        echo "Purging $dir"
+        rm -r "$dir"
+}
+
+function compress_soft_deleted_mailbox {
+        dir=$1
+
+        backupfile="${dir}.tar.bz2"
+
+        # Test if backup file already exists
+        if [ -f $backupfile ]; then
+                # Skip
+                echo "ERROR: Backupfile($backupfile) exists!" >&2
+                continue
+        fi
+
+        echo "Compressing for $dir"
+        tar cvfj "$backupfile" --remove-files "$dir" 2> >( grep -v "tar: Removing leading" >&2)
+}
+
+# List deleted mailboxs to archive
+# -mtime +7 ===> Only mailboxes deleted more then 7 days ago
+# Test that the last dir component matches e.g. xxx-deleted-20220101094242 (14 digits)
+# command: xxx-`date "+%Y%m%d%H%M%S"`
+find /var/vmail/*/[a-z0-9.-]*-deleted-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]  -maxdepth 0 -type d -mtime +$delay_days | while read line; do
+        # example $line: "/var/vmail/example.com/info-20220101094242"
+
+        dir=$line
+
+        # Uncomment the desired cleanup method below, or be creative and create your own.
+
+        remove_soft_deleted_mailbox $dir
+        #compress_soft_deleted_mailbox $dir
+
+done