diff --git a/data/web/edit.php b/data/web/edit.php index 185e7934b..09db796d3 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -39,17 +39,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { $template_data = ['admin' => $admin]; } elseif (isset($_GET['domain'])) { - if ($_GET['domain'] == "defaults") { - // edit domain default settings - //$result = mailbox('get', 'domain_defaults'); - //$rl = ratelimit('get', 'domain_defaults'); - $result = true; - $template = 'edit/domain-defaults.twig'; - $template_data = [ - // 'rl' => $rl, - ]; - } - elseif (is_valid_domain_name($_GET["domain"]) && + if (is_valid_domain_name($_GET["domain"]) && !empty($_GET["domain"])) { // edit domain $domain = $_GET["domain"]; @@ -69,6 +59,26 @@ if (isset($_SESSION['mailcow_cc_role'])) { ]; } } + elseif (isset($_GET["template"])){ + $domain_template = mailbox('get', 'domain_templates', $_GET["template"]); + if ($domain_template){ + $template_data = [ + 'template' => $domain_template + ]; + $template = 'edit/domain-templates.twig'; + $result = true; + } + else { + $mailbox_template = mailbox('get', 'mailbox_templates', $_GET["template"]); + if ($mailbox_template){ + $template_data = [ + 'template' => $mailbox_template + ]; + $template = 'edit/mailbox-templates.twig'; + $result = true; + } + } + } elseif (isset($_GET['oauth2client']) && is_numeric($_GET["oauth2client"]) && !empty($_GET["oauth2client"])) { @@ -92,17 +102,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { ]; } elseif (isset($_GET['mailbox'])){ - if ($_GET['mailbox'] == "defaults"){ - // edit mailbox default settings - // $result = mailbox('get', 'mailbox_defaults'); - // $rl = ratelimit('get', 'mailbox_defaults'); - $result = true; - $template = 'edit/mailbox-defaults.twig'; - $template_data = [ - // 'rl' => $rl, - ]; - } - elseif(filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) { + if(filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) { // edit mailbox $mailbox = html_entity_decode(rawurldecode($_GET["mailbox"])); $result = mailbox('get', 'mailbox_details', $mailbox); diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 2cf9f6c65..b30a4a974 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1020,6 +1020,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (empty($name)) { $name = $local_part; } + if (isset($_data['protocol_access'])) { + $_data['protocol_access'] = (array)$_data['protocol_access']; + $_data['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0; + $_data['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0; + $_data['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0; + $_data['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0; + } $active = intval($_data['active']); $force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']); $tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']); @@ -1200,10 +1207,63 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ':domain' => $domain, ':active' => $active )); - $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)"); - $stmt->execute(array( - ':username' => $username - )); + + + if (isset($_data['acl'])) { + $_data['acl'] = (array)$_data['acl']; + $_data['spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0; + $_data['tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0; + $_data['spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0; + $_data['spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0; + $_data['delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0; + $_data['syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0; + $_data['eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0; + $_data['sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0; + $_data['pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0; + $_data['quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0; + $_data['quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0; + $_data['quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0; + $_data['quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0; + $_data['app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0; + + $stmt = $pdo->prepare("INSERT INTO `user_acl` + (`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`, + `pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`) + VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset, + :pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds) "); + $stmt->execute(array( + ':username' => $username, + ':spam_alias' => $_data['spam_alias'], + ':tls_policy' => $_data['tls_policy'], + ':spam_score' => $_data['spam_score'], + ':spam_policy' => $_data['spam_policy'], + ':delimiter_action' => $_data['delimiter_action'], + ':syncjobs' => $_data['syncjobs'], + ':eas_reset' => $_data['eas_reset'], + ':sogo_profile_reset' => $_data['sogo_profile_reset'], + ':pushover' => $_data['pushover'], + ':quarantine' => $_data['quarantine'], + ':quarantine_attachments' => $_data['quarantine_attachments'], + ':quarantine_notification' => $_data['quarantine_notification'], + ':quarantine_category' => $_data['quarantine_category'], + ':app_passwds' => $_data['app_passwds'] + )); + } + else { + $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)"); + $stmt->execute(array( + ':username' => $username + )); + } + + if (isset($_data['rl_frame']) && isset($_data['rl_value'])){ + ratelimit('edit', 'mailbox', array( + 'object' => $username, + 'rl_frame' => $_data['rl_frame'], + 'rl_value' => $_data['rl_value'] + )); + } + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), @@ -1322,6 +1382,191 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { 'msg' => array('resource_added', htmlspecialchars($name)) ); break; + case 'domain_templates': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'access_denied' + ); + return false; + } + if (empty($_data["template"])){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'template_name_invalid' + ); + return false; + } + + // check if template name exists, return false + $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template"); + $stmt->execute(array( + ":type" => "domain", + ":template" => $_data["template"] + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!empty($row)){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => array('template_exists', $_data["template"]) + ); + return false; + } + + // check attributes + $attr = array(); + $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array(); + $attr['max_num_aliases_for_domain'] = (isset($_data['max_num_aliases_for_domain'])) ? intval($_data['max_num_aliases_for_domain']) : 0; + $attr['max_num_mboxes_for_domain'] = (isset($_data['max_num_mboxes_for_domain'])) ? intval($_data['max_num_mboxes_for_domain']) : 0; + $attr['def_quota_for_mbox'] = (isset($_data['def_quota_for_mbox'])) ? intval($_data['def_quota_for_mbox']) * 1048576 : 0; + $attr['max_quota_for_mbox'] = (isset($_data['max_quota_for_mbox'])) ? intval($_data['max_quota_for_mbox']) * 1048576 : 0; + $attr['max_quota_for_domain'] = (isset($_data['max_quota_for_domain'])) ? intval($_data['max_quota_for_domain']) * 1048576 : 0; + $attr['rl_frame'] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s"; + $attr['rl_value'] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : ""; + $attr['active'] = isset($_data['active']) ? intval($_data['active']) : 1; + $attr['gal'] = (isset($_data['gal'])) ? intval($_data['gal']) : 1; + $attr['backupmx'] = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : 0; + $attr['relay_all_recipients'] = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : 0; + $attr['relay_unknown_only'] = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : 0; + $attr['dkim_selector'] = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : "dkim"; + $attr['key_size'] = isset($_data['key_size']) ? intval($_data['key_size']) : 2048; + + + // save template + $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) + VALUES (:type, :template, :attributes)"); + $stmt->execute(array( + ":type" => "domain", + ":template" => $_data["template"], + ":attributes" => json_encode($attr) + )); + + // success + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('template_added', $_data["template"]) + ); + return true; + break; + case 'mailbox_templates': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'access_denied' + ); + return false; + } + if (empty($_data["template"])){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'template_name_invalid' + ); + return false; + } + + // check if template name exists, return false + $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template"); + $stmt->execute(array( + ":type" => "mailbox", + ":template" => $_data["template"] + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!empty($row)){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => array('template_exists', $_data["template"]) + ); + return false; + } + + + // check attributes + $attr = array(); + $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0; + $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array(); + $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']); + $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']); + $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s"; + $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : ""; + $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']); + $attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_access']); + $attr["active"] = isset($_data['active']) ? intval($_data['active']) : 1; + $attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']); + $attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']); + if (isset($_data['protocol_access'])) { + $_data['protocol_access'] = (array)$_data['protocol_access']; + $attr['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']); + $attr['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']); + $attr['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']); + $attr['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['sieve_access']); + } + else { + $attr['imap_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']); + $attr['pop3_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']); + $attr['smtp_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']); + $attr['sieve_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['sieve_access']); + } + if (isset($_data['acl'])) { + $_data['acl'] = (array)$_data['acl']; + $attr['acl_spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0; + $attr['acl_tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0; + $attr['acl_spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0; + $attr['acl_spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0; + $attr['acl_delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0; + $attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0; + $attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0; + $attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0; + $attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0; + $attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0; + } else { + $_data['acl'] = (array)$_data['acl']; + $attr['acl_spam_alias'] = 1; + $attr['acl_tls_policy'] = 1; + $attr['acl_spam_score'] = 1; + $attr['acl_spam_policy'] = 1; + $attr['acl_delimiter_action'] = 1; + $attr['acl_syncjobs'] = 0; + $attr['acl_eas_reset'] = 1; + $attr['acl_sogo_profile_reset'] = 0; + $attr['acl_pushover'] = 1; + $attr['acl_quarantine'] = 1; + $attr['acl_quarantine_attachments'] = 1; + $attr['acl_quarantine_notification'] = 1; + $attr['acl_quarantine_category'] = 1; + $attr['acl_app_passwds'] = 1; + } + + + + // save template + $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) + VALUES (:type, :template, :attributes)"); + $stmt->execute(array( + ":type" => "mailbox", + ":template" => $_data["template"], + ":attributes" => json_encode($attr) + )); + + // success + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('template_added', $_data["template"]) + ); + return true; + break; } break; case 'edit': @@ -2472,6 +2717,79 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } } break; + case 'domain_templates': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'access_denied' + ); + return false; + } + if (!is_array($_data['ids'])) { + $ids = array(); + $ids[] = $_data['ids']; + } + else { + $ids = $_data['ids']; + } + foreach ($ids as $id) { + $is_now = mailbox("get", "domain_templates", $id); + if (empty($is_now) || + $is_now["type"] != "domain"){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'template_id_invalid' + ); + continue; + } + + // check name + if ($is_now["template"] == "Default" && $is_now["template"] != $_data["template"]){ + // keep template name of Default template + $_data["template"] = $is_now["template"]; + } + else { + $_data["template"] = (isset($_data["template"])) ? $_data["template"] : $is_now["template"]; + } + // check attributes + $attr = array(); + $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array(); + $attr['max_num_aliases_for_domain'] = (isset($_data['max_num_aliases_for_domain'])) ? intval($_data['max_num_aliases_for_domain']) : 0; + $attr['max_num_mboxes_for_domain'] = (isset($_data['max_num_mboxes_for_domain'])) ? intval($_data['max_num_mboxes_for_domain']) : 0; + $attr['def_quota_for_mbox'] = (isset($_data['def_quota_for_mbox'])) ? intval($_data['def_quota_for_mbox']) * 1048576 : 0; + $attr['max_quota_for_mbox'] = (isset($_data['max_quota_for_mbox'])) ? intval($_data['max_quota_for_mbox']) * 1048576 : 0; + $attr['max_quota_for_domain'] = (isset($_data['max_quota_for_domain'])) ? intval($_data['max_quota_for_domain']) * 1048576 : 0; + $attr['rl_frame'] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s"; + $attr['rl_value'] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : ""; + $attr['active'] = isset($_data['active']) ? intval($_data['active']) : 1; + $attr['gal'] = (isset($_data['gal'])) ? intval($_data['gal']) : 1; + $attr['backupmx'] = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : 0; + $attr['relay_all_recipients'] = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : 0; + $attr['relay_unknown_only'] = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : 0; + $attr['dkim_selector'] = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : "dkim"; + $attr['key_size'] = isset($_data['key_size']) ? intval($_data['key_size']) : 2048; + + // update template + $stmt = $pdo->prepare("UPDATE `templates` + SET `template` = :template, `attributes` = :attributes + WHERE id = :id"); + $stmt->execute(array( + ":id" => $id , + ":template" => $_data["template"] , + ":attributes" => json_encode($attr) + )); + } + + + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('template_modified', $_data["template"]) + ); + return true; + break; case 'mailbox': if (!is_array($_data['username'])) { $usernames = array(); @@ -2814,6 +3132,110 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); } break; + case 'mailbox_templates': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'access_denied' + ); + return false; + } + if (!is_array($_data['ids'])) { + $ids = array(); + $ids[] = $_data['ids']; + } + else { + $ids = $_data['ids']; + } + foreach ($ids as $id) { + $is_now = mailbox("get", "mailbox_templates", $id); + if (empty($is_now) || + $is_now["type"] != "mailbox"){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra), + 'msg' => 'template_id_invalid' + ); + continue; + } + + + // check name + if ($is_now["template"] == "Default" && $is_now["template"] != $_data["template"]){ + // keep template name of Default template + $_data["template"] = $is_now["template"]; + } + else { + $_data["template"] = (isset($_data["template"])) ? $_data["template"] : $is_now["template"]; + } + // check attributes + $attr = array(); + $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0; + $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags']; + $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification']; + $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category']; + $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame']; + $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value']; + $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update']; + $attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : $is_now['sogo_access']; + $attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active']; + $attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in']; + $attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out']; + if (isset($_data['protocol_access'])) { + $_data['protocol_access'] = (array)$_data['protocol_access']; + $attr['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0; + $attr['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0; + $attr['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0; + $attr['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0; + } + else { + foreach ($is_now as $key => $value){ + $attr[$key] = $is_now[$key]; + } + } + if (isset($_data['acl'])) { + $_data['acl'] = (array)$_data['acl']; + $attr['acl_spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0; + $attr['acl_tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0; + $attr['acl_spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0; + $attr['acl_spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0; + $attr['acl_delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0; + $attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0; + $attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0; + $attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0; + $attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0; + $attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0; + $attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0; + } else { + foreach ($is_now as $key => $value){ + $attr[$key] = $is_now[$key]; + } + } + + + // update template + $stmt = $pdo->prepare("UPDATE `templates` + SET `template` = :template, `attributes` = :attributes + WHERE id = :id"); + $stmt->execute(array( + ":id" => $id , + ":template" => $_data["template"] , + ":attributes" => json_encode($attr) + )); + } + + + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('template_modified', $_data["template"]) + ); + return true; + break; case 'resource': if (!is_array($_data['name'])) { $names = array(); @@ -3711,6 +4133,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return $domaindata; break; + case 'domain_templates': + if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") { + return false; + } + $_data = (isset($_data)) ? intval($_data) : null; + + if (isset($_data)){ + $stmt = $pdo->prepare("SELECT * FROM `templates` + WHERE `id` = :id AND type = :type"); + $stmt->execute(array( + ":id" => $_data, + ":type" => "domain" + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + + if (empty($row)){ + return false; + } + + $row["attributes"] = json_decode($row["attributes"], true); + return $row; + } + else { + $stmt = $pdo->prepare("SELECT * FROM `templates` WHERE `type` = 'domain'"); + $stmt->execute(); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($rows)){ + return false; + } + + foreach($rows as $key => $row){ + $rows[$key]["attributes"] = json_decode($row["attributes"], true); + } + return $rows; + } + break; case 'mailbox_details': if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { return false; @@ -3856,6 +4315,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return $mailboxdata; break; + case 'mailbox_templates': + if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") { + return false; + } + $_data = (isset($_data)) ? intval($_data) : null; + + if (isset($_data)){ + $stmt = $pdo->prepare("SELECT * FROM `templates` + WHERE `id` = :id AND type = :type"); + $stmt->execute(array( + ":id" => $_data, + ":type" => "mailbox" + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + + if (empty($row)){ + return false; + } + + $row["attributes"] = json_decode($row["attributes"], true); + return $row; + } + else { + $stmt = $pdo->prepare("SELECT * FROM `templates` WHERE `type` = 'mailbox'"); + $stmt->execute(); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($rows)){ + return false; + } + + foreach($rows as $key => $row){ + $rows[$key]["attributes"] = json_decode($row["attributes"], true); + } + return $rows; + } + break; case 'resource_details': $resourcedata = array(); if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { @@ -4224,6 +4720,42 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); } break; + case 'domain_templates': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + return false; + } + if (!is_array($_data['ids'])) { + $ids = array(); + $ids[] = $_data['ids']; + } + else { + $ids = $_data['ids']; + } + + + foreach ($ids as $id) { + // delete template + $stmt = $pdo->prepare("DELETE FROM `templates` + WHERE id = :id AND type = :type AND NOT template = :template"); + $stmt->execute(array( + ":id" => $id, + ":type" => "domain", + ":template" => "Default" + )); + } + + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'template_removed' + ); + return true; + break; case 'alias': if (!is_array($_data['id'])) { $ids = array(); @@ -4518,6 +5050,42 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); } break; + case 'mailbox_templates': + if ($_SESSION['mailcow_cc_role'] != "admin") { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + return false; + } + if (!is_array($_data['ids'])) { + $ids = array(); + $ids[] = $_data['ids']; + } + else { + $ids = $_data['ids']; + } + + + foreach ($ids as $id) { + // delete template + $stmt = $pdo->prepare("DELETE FROM `templates` + WHERE id = :id AND type = :type AND NOT template = :template"); + $stmt->execute(array( + ":id" => $id, + ":type" => "mailbox", + ":template" => "Default" + )); + } + + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'template_removed' + ); + return true; + break; case 'resource': if (!is_array($_data['name'])) { $names = array(); diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index b47bd5c23..1dc39b541 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "25072022_2300"; + $db_version = "10112022_1146"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -225,6 +225,22 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "templates" => array( + "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", + "template" => "VARCHAR(255) NOT NULL", + "type" => "VARCHAR(255) NOT NULL", + "attributes" => "JSON", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP" + ), + "keys" => array( + "primary" => array( + "" => array("id") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "domain" => array( // Todo: Move some attributes to json "cols" => array( @@ -1292,6 +1308,89 @@ function init_db_schema() { // Fix domain_admins $pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';"); + // add default templates + $default_domain_template = array( + "template" => "Default", + "type" => "domain", + "attributes" => array( + "tags" => array(), + "max_num_aliases_for_domain" => 400, + "max_num_mboxes_for_domain" => 10, + "def_quota_for_mbox" => 3072 * 1048576, + "max_quota_for_mbox" => 10240 * 1048576, + "max_quota_for_domain" => 10240 * 1048576, + "rl_frame" => "s", + "rl_value" => "", + "active" => 1, + "gal" => 1, + "backupmx" => 0, + "relay_all_recipients" => 0, + "relay_unknown_only" => 0, + "dkim_selector" => "dkim", + "key_size" => 2048, + "max_quota_for_domain" => 10240 * 1048576, + ) + ); + $default_mailbox_template = array( + "template" => "Default", + "type" => "mailbox", + "attributes" => array( + "tags" => array(), + "quota" => 0, + "quarantine_notification" => strval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['quarantine_notification']), + "quarantine_category" => strval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['quarantine_category']), + "rl_frame" => "s", + "rl_value" => "", + "force_pw_update" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_pw_update']), + "sogo_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sogo_access']), + "active" => 1, + "tls_enforce_in" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_in']), + "tls_enforce_out" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_out']), + "imap_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['imap_access']), + "pop3_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['pop3_access']), + "smtp_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['smtp_access']), + "sieve_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sieve_access']), + "acl_spam_alias" => 1, + "acl_tls_policy" => 1, + "acl_spam_score" => 1, + "acl_spam_policy" => 1, + "acl_delimiter_action" => 1, + "acl_syncjobs" => 0, + "acl_eas_reset" => 1, + "acl_sogo_profile_reset" => 0, + "acl_pushover" => 1, + "acl_quarantine" => 1, + "acl_quarantine_attachments" => 1, + "acl_quarantine_notification" => 1, + "acl_quarantine_category" => 1, + "acl_app_passwds" => 1, + ) + ); + $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) + SELECT :type, :template, :attributes FROM `templates` + WHERE NOT EXISTS ( + SELECT `template` FROM `templates` WHERE `template` = :template2 AND `type` = :type2 + ) LIMIT 1;"); + $stmt->execute(array( + ":type" => "domain", + ":type2" => "domain", + ":template" => $default_domain_template["template"], + ":template2" => $default_mailbox_template["template"], + ":attributes" => json_encode($default_domain_template["attributes"]) + )); + $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) + SELECT :type, :template, :attributes FROM `templates` + WHERE NOT EXISTS ( + SELECT `template` FROM `templates` WHERE `template` = :template2 AND `type` = :type2 + ) LIMIT 1;"); + $stmt->execute(array( + ":type" => "mailbox", + ":type2" => "mailbox", + ":template" => $default_mailbox_template["template"], + ":template2" => $default_mailbox_template["template"], + ":attributes" => json_encode($default_mailbox_template["attributes"]) + )); + if (php_sapi_name() == "cli") { echo "DB initialization completed" . PHP_EOL; } else { diff --git a/data/web/js/build/014-mailcow.js b/data/web/js/build/014-mailcow.js index a2e255476..a211643a1 100644 --- a/data/web/js/build/014-mailcow.js +++ b/data/web/js/build/014-mailcow.js @@ -289,37 +289,6 @@ $(document).ready(function() { addTag(this); } }); - function addTag(tagAddElem){ - var tagboxElem = $(tagAddElem).parent(); - var tagInputElem = $(tagboxElem).find(".tag-input")[0]; - var tagValuesElem = $(tagboxElem).find(".tag-values")[0]; - - var tag = escapeHtml($(tagInputElem).val()); - if (!tag) return; - var value_tags = []; - try { - value_tags = JSON.parse($(tagValuesElem).val()); - } catch {} - if (!Array.isArray(value_tags)) value_tags = []; - if (value_tags.includes(tag)) return; - - $(' ' + tag + '').insertBefore('.tag-input').click(function(){ - var del_tag = unescapeHtml($(this).text()); - var del_tags = []; - try { - del_tags = JSON.parse($(tagValuesElem).val()); - } catch {} - if (Array.isArray(del_tags)){ - del_tags.splice(del_tags.indexOf(del_tag), 1); - $(tagValuesElem).val(JSON.stringify(del_tags)); - } - $(this).remove(); - }); - - value_tags.push($(tagInputElem).val()); - $(tagValuesElem).val(JSON.stringify(value_tags)); - $(tagInputElem).val(''); - } // Dark Mode Loader $('#dark-mode-toggle').click(toggleDarkMode); @@ -367,13 +336,14 @@ $(document).ready(function() { `); localStorage.setItem("seenChangelog", Math.floor(Date.now() / 1000).toString()); + + new bootstrap.Modal(document.getElementById("showWhatsNewModal"), { + backdrop: 'static', + keyboard: false + }).show(); } }); - new bootstrap.Modal(document.getElementById("showWhatsNewModal"), { - backdrop: 'static', - keyboard: false - }).show(); } } @@ -408,3 +378,36 @@ $(document).ready(function() { // https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery function escapeHtml(n){var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} function unescapeHtml(t){var n={"&":"&","<":"<",">":">",""":'"',"'":"'","/":"/","`":"`","=":"="};return String(t).replace(/&|<|>|"|'|/|`|=/g,function(t){return n[t]})} + +function addTag(tagAddElem, tag = null){ + var tagboxElem = $(tagAddElem).parent(); + var tagInputElem = $(tagboxElem).find(".tag-input")[0]; + var tagValuesElem = $(tagboxElem).find(".tag-values")[0]; + + if (!tag) + tag = $(tagInputElem).val(); + if (!tag) return; + var value_tags = []; + try { + value_tags = JSON.parse($(tagValuesElem).val()); + } catch {} + if (!Array.isArray(value_tags)) value_tags = []; + if (value_tags.includes(tag)) return; + + $(' ' + escapeHtml(tag) + '').insertBefore('.tag-input').click(function(){ + var del_tag = unescapeHtml($(this).text()); + var del_tags = []; + try { + del_tags = JSON.parse($(tagValuesElem).val()); + } catch {} + if (Array.isArray(del_tags)){ + del_tags.splice(del_tags.indexOf(del_tag), 1); + $(tagValuesElem).val(JSON.stringify(del_tags)); + } + $(this).remove(); + }); + + value_tags.push(tag); + $(tagValuesElem).val(JSON.stringify(value_tags)); + $(tagInputElem).val(''); +} \ No newline at end of file diff --git a/data/web/js/site/edit.js b/data/web/js/site/edit.js index 31b9d08ba..55a8e6b40 100644 --- a/data/web/js/site/edit.js +++ b/data/web/js/site/edit.js @@ -57,6 +57,17 @@ $(document).ready(function() { $("#multiple_bookings_custom").bind("change keypress keyup blur", function() { $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val()); }); + + // load tags + if ($('#tags').length){ + var tagsEl = $('#tags').parent().find('.tag-values')[0]; + console.log($(tagsEl).val()) + var tags = JSON.parse($(tagsEl).val()); + $(tagsEl).val(""); + + for (var i = 0; i < tags.length; i++) + addTag($('#tags'), tags[i]); + } }); jQuery(function($){ diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 77da5029d..275b977ff 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -77,6 +77,90 @@ $(document).ready(function() { $('.dns-modal-body').html(xhr.responseText); } }); + }); + // @Open Domain add modal + $('#addDomainModal').on('show.bs.modal', function(e) { + $.ajax({ + url: '/api/v1/get/domain/template/all', + data: {}, + dataType: 'json', + success: async function(data){ + $('#domain_templates').find('option').remove(); + $('#domain_templates').selectpicker('destroy'); + $('#domain_templates').selectpicker(); + for (var i = 0; i < data.length; i++){ + if (data[i].template === "Default"){ + $('#domain_templates').prepend($('', { + 'value': data[i].id, + 'text': data[i].template, + 'data-attributes': JSON.stringify(data[i].attributes), + 'selected': true + })); + setDomainTemplateData(data[i].attributes); + } else { + $('#domain_templates').append($('', { + 'value': data[i].id, + 'text': data[i].template, + 'data-attributes': JSON.stringify(data[i].attributes), + 'selected': false + })); + } + }; + $('#domain_templates').selectpicker("refresh"); + + // @selecting template + $('#domain_templates').on('change', function(){ + var selected = $('#domain_templates option:selected'); + var attr = selected.data('attributes'); + setDomainTemplateData(attr); + }); + }, + error: function(xhr, status, error) { + console.log(error); + } + }); + }); + // @Open Mailbox add modal + $('#addMailboxModal').on('show.bs.modal', function(e) { + $.ajax({ + url: '/api/v1/get/mailbox/template/all', + data: {}, + dataType: 'json', + success: async function(data){ + $('#mailbox_templates').find('option').remove(); + $('#mailbox_templates').selectpicker('destroy'); + $('#mailbox_templates').selectpicker(); + for (var i = 0; i < data.length; i++){ + if (data[i].template === "Default"){ + $('#mailbox_templates').prepend($('', { + 'value': data[i].id, + 'text': data[i].template, + 'data-attributes': JSON.stringify(data[i].attributes), + 'selected': true + })); + setMailboxTemplateData(data[i].attributes); + } else { + $('#mailbox_templates').append($('', { + value: data[i].id, + text : data[i].template, + 'data-attributes': JSON.stringify(data[i].attributes), + 'selected': false + })); + } + }; + $('#mailbox_templates').selectpicker("refresh"); + + // @selecting template + $('#mailbox_templates').on('change', function(){ + var selected = $('#mailbox_templates option:selected'); + var attr = selected.data('attributes'); + setMailboxTemplateData(attr); + }); + }, + error: function(xhr, status, error) { + console.log(error); + } + }); }); // Sieve data modal $('#sieveDataModal').on('show.bs.modal', function(e) { @@ -133,6 +217,201 @@ $(document).ready(function() { $("#multiple_bookings").val($("#multiple_bookings_custom").val()); }); + function setDomainTemplateData(template){ + $("#addDomain_max_aliases").val(template.max_num_aliases_for_domain); + $("#addDomain_max_mailboxes").val(template.max_num_mboxes_for_domain); + $("#addDomain_mailbox_quota_def").val(template.def_quota_for_mbox / 1048576); + $("#addDomain_mailbox_quota_m").val(template.max_quota_for_mbox / 1048576); + $("#addDomain_domain_quota_m").val(template.max_quota_for_domain / 1048576); + + if (template.gal == 1){ + $('#addDomain_gal').prop('checked', true); + } else { + $('#addDomain_gal').prop('checked', false); + } + + if (template.active == 1){ + $('#addDomain_active').prop('checked', true); + } else { + $('#addDomain_active').prop('checked', false); + } + + $("#addDomain_rl_value").val(template.rl_value); + $('#addDomain_rl_frame').selectpicker('val', template.rl_frame); + $("#dkim_selector").val(template.dkim_selector); + if (!template.key_size) + template.key_size = 2048; + $('#key_size').selectpicker('val', template.key_size.toString()); + + if (template.backupmx == 1){ + $('#addDomain_relay_domain').prop('checked', true); + } else { + $('#addDomain_relay_domain').prop('checked', false); + } + if (template.relay_all_recipients == 1){ + $('#addDomain_relay_all').prop('checked', true); + } else { + $('#addDomain_relay_all').prop('checked', false); + } + if (template.relay_unknown_only == 1){ + $('#addDomain_relay_unknown_only').prop('checked', true); + } else { + $('#addDomain_relay_unknown_only').prop('checked', false); + } + + + // load tags + $('#addDomain_tags').val(""); + $($('#addDomain_tags').parent().find(".tag-values")[0]).val(""); + $('#addDomain_tags').parent().find(".tag-badge").remove(); + for (var i = 0; i < template.tags.length; i++) + addTag($('#addDomain_tags'), template.tags[i]); + } + function setMailboxTemplateData(template){ + $("#addInputQuota").val(template.quota / 1048576); + + if (template.quarantine_notification === "never"){ + $('#quarantine_notification_never').prop('checked', true); + $('#quarantine_notification_hourly').prop('checked', false); + $('#quarantine_notification_daily').prop('checked', false); + $('#quarantine_notification_weekly').prop('checked', false); + } else if(template.quarantine_notification === "hourly"){ + $('#quarantine_notification_never').prop('checked', false); + $('#quarantine_notification_hourly').prop('checked', true); + $('#quarantine_notification_daily').prop('checked', false); + $('#quarantine_notification_weekly').prop('checked', false); + } else if(template.quarantine_notification === "daily"){ + $('#quarantine_notification_never').prop('checked', false); + $('#quarantine_notification_hourly').prop('checked', false); + $('#quarantine_notification_daily').prop('checked', true); + $('#quarantine_notification_weekly').prop('checked', false); + } else if(template.quarantine_notification === "weekly"){ + $('#quarantine_notification_never').prop('checked', false); + $('#quarantine_notification_hourly').prop('checked', false); + $('#quarantine_notification_daily').prop('checked', false); + $('#quarantine_notification_weekly').prop('checked', true); + } else { + $('#quarantine_notification_never').prop('checked', false); + $('#quarantine_notification_hourly').prop('checked', false); + $('#quarantine_notification_daily').prop('checked', false); + $('#quarantine_notification_weekly').prop('checked', false); + } + + if (template.quarantine_category === "reject"){ + $('#quarantine_category_reject').prop('checked', true); + $('#quarantine_category_add_header').prop('checked', false); + $('#quarantine_category_all').prop('checked', false); + } else if(template.quarantine_category === "add_header"){ + $('#quarantine_category_reject').prop('checked', false); + $('#quarantine_category_add_header').prop('checked', true); + $('#quarantine_category_all').prop('checked', false); + } else if(template.quarantine_category === "all"){ + $('#quarantine_category_reject').prop('checked', false); + $('#quarantine_category_add_header').prop('checked', false); + $('#quarantine_category_all').prop('checked', true); + } + + if (template.tls_enforce_in == 1){ + $('#tls_enforce_in').prop('checked', true); + } else { + $('#tls_enforce_in').prop('checked', false); + } + if (template.tls_enforce_out == 1){ + $('#tls_enforce_out').prop('checked', true); + } else { + $('#tls_enforce_out').prop('checked', false); + } + + var protocol_access = []; + if (template.imap_access == 1){ + protocol_access.push("imap"); + } + if (template.pop3_access == 1){ + protocol_access.push("pop3"); + } + if (template.smtp_access == 1){ + protocol_access.push("smtp"); + } + if (template.sieve_access == 1){ + protocol_access.push("sieve"); + } + $('#protocol_access').selectpicker('val', protocol_access); + + var acl = []; + if (template.acl_spam_alias == 1){ + acl.push("spam_alias"); + } + if (template.acl_tls_policy == 1){ + acl.push("tls_policy"); + } + if (template.acl_spam_score == 1){ + acl.push("spam_score"); + } + if (template.acl_spam_policy == 1){ + acl.push("spam_policy"); + } + if (template.acl_delimiter_action == 1){ + acl.push("delimiter_action"); + } + if (template.acl_syncjobs == 1){ + acl.push("syncjobs"); + } + if (template.acl_eas_reset == 1){ + acl.push("eas_reset"); + } + if (template.acl_sogo_profile_reset == 1){ + acl.push("sogo_profile_reset"); + } + if (template.acl_pushover == 1){ + acl.push("pushover"); + } + if (template.acl_quarantine == 1){ + acl.push("quarantine"); + } + if (template.acl_quarantine_attachments == 1){ + acl.push("quarantine_attachments"); + } + if (template.acl_quarantine_notification == 1){ + acl.push("quarantine_notification"); + } + if (template.acl_quarantine_category == 1){ + acl.push("quarantine_category"); + } + if (template.acl_app_passwds == 1){ + acl.push("app_passwds"); + } + $('#user_acl').selectpicker('val', acl); + + $('#rl_value').val(template.rl_value); + if (template.rl_frame){ + $('#rl_frame').selectpicker('val', template.rl_frame); + } + + console.log(template.active) + if (template.active){ + $('#mbox_active').selectpicker('val', template.active.toString()); + } else { + $('#mbox_active').selectpicker('val', ''); + } + + if (template.force_pw_update == 1){ + $('#force_pw_update').prop('checked', true); + } else { + $('#force_pw_update').prop('checked', false); + } + if (template.sogo_access == 1){ + $('#sogo_access').prop('checked', true); + } else { + $('#sogo_access').prop('checked', false); + } + + // load tags + $('#addMailbox_tags').val(""); + $($('#addMailbox_tags').parent().find(".tag-values")[0]).val(""); + $('#addMailbox_tags').parent().find(".tag-badge").remove(); + for (var i = 0; i < template.tags.length; i++) + addTag($('#addMailbox_tags'), template.tags[i]); + } }); jQuery(function($){ // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript @@ -318,6 +597,196 @@ jQuery(function($){ ] }); } + function draw_templates_domain_table() { + // just recalc width if instance already exists + if ($.fn.DataTable.isDataTable('#templates_domain_table') ) { + $('#templates_domain_table').DataTable().columns.adjust().responsive.recalc(); + return; + } + + $('#templates_domain_table').DataTable({ + responsive : true, + processing: true, + serverSide: false, + language: lang_datatables, + ajax: { + type: "GET", + url: "/api/v1/get/domain/template/all", + dataSrc: function(json){ + console.log(json); + $.each(json, function (i, item) { + item.chkbox = ''; + + item.attributes.def_quota_for_mbox = humanFileSize(item.attributes.def_quota_for_mbox); + item.attributes.max_quota_for_mbox = humanFileSize(item.attributes.max_quota_for_mbox); + item.attributes.max_quota_for_domain = humanFileSize(item.attributes.max_quota_for_domain); + + item.template = escapeHtml(item.template); + if (item.attributes.rl_frame === "s"){ + item.attributes.rl_frame = lang_rl.second; + } else if (item.attributes.rl_frame === "m"){ + item.attributes.rl_frame = lang_rl.minute; + } else if (item.attributes.rl_frame === "h"){ + item.attributes.rl_frame = lang_rl.hour; + } else if (item.attributes.rl_frame === "d"){ + item.attributes.rl_frame = lang_rl.day; + } + item.attributes.rl_value = escapeHtml(item.attributes.rl_value); + + item.action = '' + + ' ' + lang.edit + '' + + ' ' + lang.remove + '' + + ''; + + if (Array.isArray(item.attributes.tags)){ + var tags = ''; + for (var i = 0; i < item.attributes.tags.length; i++) + tags += ' ' + escapeHtml(item.attributes.tags[i]) + ''; + item.attributes.tags = tags; + } else { + item.attributes.tags = ''; + } + }); + + return json; + } + }, + columns: [ + { + // placeholder, so checkbox will not block child row toggle + title: '', + data: null, + searchable: false, + orderable: false, + defaultContent: '', + responsivePriority: 1 + }, + { + title: '', + data: 'chkbox', + searchable: false, + orderable: false, + defaultContent: '', + responsivePriority: 1 + }, + { + title: "ID", + data: 'id', + responsivePriority: 2, + defaultContent: '' + }, + { + title: "Template", + data: 'template', + responsivePriority: 3, + defaultContent: '' + }, + { + title: lang.max_aliases, + data: 'attributes.max_num_aliases_for_domain', + defaultContent: '', + }, + { + title: lang.max_mailboxes, + data: 'attributes.max_num_mboxes_for_domain', + defaultContent: '', + }, + { + title: lang.mailbox_defquota, + data: 'attributes.def_quota_for_mbox', + defaultContent: '', + }, + { + title: lang.max_quota, + data: 'attributes.max_quota_for_mbox', + defaultContent: '', + }, + { + title: lang.domain_quota_total, + data: 'attributes.max_quota_for_domain', + defaultContent: '', + }, + { + title: lang.gal, + data: 'attributes.gal', + defaultContent: '', + render: function (data, type) { + return 1==data?'':''; + } + }, + { + title: lang.backup_mx, + data: 'attributes.backupmx', + defaultContent: '', + render: function (data, type) { + return 1==data?'':''; + } + }, + { + title: lang.relay_all, + data: 'attributes.relay_all_recipients', + defaultContent: '', + render: function (data, type) { + return 1==data?'':''; + } + }, + { + title: lang.relay_unknown, + data: 'attributes.relay_unknown_only', + defaultContent: '', + render: function (data, type) { + return 1==data?'':''; + } + }, + { + title: lang.active, + data: 'attributes.active', + defaultContent: '', + responsivePriority: 4, + render: function (data, type) { + return 1==data?'':''; + } + }, + { + title: 'rl_frame', + data: 'attributes.rl_frame', + defaultContent: '', + class: 'none', + }, + { + title: 'rl_value', + data: 'attributes.rl_value', + defaultContent: '', + class: 'none', + }, + { + title: lang.dkim_domains_selector, + data: 'attributes.dkim_selector', + defaultContent: '', + class: 'none', + }, + { + title: lang.dkim_key_length, + data: 'attributes.key_size', + defaultContent: '', + class: 'none', + }, + { + title: 'Tags', + data: 'attributes.tags', + defaultContent: '', + className: 'none' + }, + { + title: lang.action, + data: 'action', + className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md', + responsivePriority: 6, + defaultContent: '' + }, + ] + }); + } function draw_mailbox_table() { // just recalc width if instance already exists if ($.fn.DataTable.isDataTable('#mailbox_table') ) { @@ -564,6 +1033,211 @@ jQuery(function($){ ] }); } + function draw_templates_mbox_table() { + // just recalc width if instance already exists + if ($.fn.DataTable.isDataTable('#templates_mbox_table') ) { + $('#templates_mbox_table').DataTable().columns.adjust().responsive.recalc(); + return; + } + + $('#templates_mbox_table').DataTable({ + responsive : true, + processing: true, + serverSide: false, + language: lang_datatables, + ajax: { + type: "GET", + url: "/api/v1/get/mailbox/template/all", + dataSrc: function(json){ + $.each(json, function (i, item) { + item.chkbox = ''; + + item.template = escapeHtml(item.template); + if (item.attributes.rl_frame === "s"){ + item.attributes.rl_frame = lang_rl.second; + } else if (item.attributes.rl_frame === "m"){ + item.attributes.rl_frame = lang_rl.minute; + } else if (item.attributes.rl_frame === "h"){ + item.attributes.rl_frame = lang_rl.hour; + } else if (item.attributes.rl_frame === "d"){ + item.attributes.rl_frame = lang_rl.day; + } + item.attributes.rl_value = escapeHtml(item.attributes.rl_value); + + item.attributes.quota = humanFileSize(item.attributes.quota); + + item.attributes.tls_enforce_in = ''; + item.attributes.tls_enforce_out = ''; + item.attributes.pop3_access = ''; + item.attributes.imap_access = ''; + item.attributes.smtp_access = ''; + item.attributes.sieve_access = ''; + item.attributes.sogo_access = ''; + if (item.attributes.quarantine_notification === 'never') { + item.attributes.quarantine_notification = lang.never; + } else if (item.attributes.quarantine_notification === 'hourly') { + item.attributes.quarantine_notification = lang.hourly; + } else if (item.attributes.quarantine_notification === 'daily') { + item.attributes.quarantine_notification = lang.daily; + } else if (item.attributes.quarantine_notification === 'weekly') { + item.attributes.quarantine_notification = lang.weekly; + } + if (item.attributes.quarantine_category === 'reject') { + item.attributes.quarantine_category = '' + lang.q_reject + ''; + } else if (item.attributes.quarantine_category === 'add_header') { + item.attributes.quarantine_category = '' + lang.q_add_header + ''; + } else if (item.attributes.quarantine_category === 'all') { + item.attributes.quarantine_category = lang.q_all; + } + + + + item.action = '' + + ' ' + lang.edit + '' + + ' ' + lang.remove + '' + + ''; + + if (Array.isArray(item.attributes.tags)){ + var tags = ''; + for (var i = 0; i < item.attributes.tags.length; i++) + tags += ' ' + escapeHtml(item.attributes.tags[i]) + ''; + item.attributes.tags = tags; + } else { + item.attributes.tags = ''; + } + }); + + return json; + } + }, + columns: [ + { + // placeholder, so checkbox will not block child row toggle + title: '', + data: null, + searchable: false, + orderable: false, + defaultContent: '', + responsivePriority: 1 + }, + { + title: '', + data: 'chkbox', + searchable: false, + orderable: false, + defaultContent: '', + responsivePriority: 1 + }, + { + title: "ID", + data: 'id', + responsivePriority: 2, + defaultContent: '' + }, + { + title: "Template", + data: 'template', + responsivePriority: 3, + defaultContent: '' + }, + { + title: lang.domain_quota, + data: 'attributes.quota', + defaultContent: '', + }, + { + title: lang.tls_enforce_in, + data: 'attributes.tls_enforce_in', + defaultContent: '' + }, + { + title: lang.tls_enforce_out, + data: 'attributes.tls_enforce_out', + defaultContent: '' + }, + { + title: 'SMTP', + data: 'attributes.smtp_access', + defaultContent: '', + }, + { + title: 'IMAP', + data: 'attributes.imap_access', + defaultContent: '', + }, + { + title: 'POP3', + data: 'attributes.pop3_access', + defaultContent: '', + }, + { + title: 'SIEVE', + data: 'attributes.sieve_access', + defaultContent: '', + }, + { + title: 'SOGO', + data: 'attributes.sogo_access', + defaultContent: '', + }, + { + title: lang.quarantine_notification, + data: 'attributes.quarantine_notification', + defaultContent: '', + className: 'none' + }, + { + title: lang.quarantine_category, + data: 'attributes.quarantine_category', + defaultContent: '', + className: 'none' + }, + { + title: lang.force_pw_update, + data: 'attributes.force_pw_update', + defaultContent: '', + class: 'none', + render: function (data, type) { + return 1==data?'':''; + } + }, + { + title: "rl_frame", + data: 'attributes.rl_frame', + defaultContent: '', + class: 'none', + }, + { + title: 'rl_value', + data: 'attributes.rl_value', + defaultContent: '', + class: 'none', + }, + { + title: 'Tags', + data: 'attributes.tags', + defaultContent: '', + className: 'none' + }, + { + title: lang.active, + data: 'attributes.active', + defaultContent: '', + responsivePriority: 4, + render: function (data, type) { + return 1==data?'':(0==data?'':2==data&&'—'); + } + }, + { + title: lang.action, + data: 'action', + className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md', + responsivePriority: 6, + defaultContent: '' + }, + ] + }); + } function draw_resource_table() { // just recalc width if instance already exists if ($.fn.DataTable.isDataTable('#resource_table') ) { @@ -1437,7 +2111,9 @@ jQuery(function($){ // Load only if the tab is visible onVisible("[id^=domain_table]", () => draw_domain_table()); + onVisible("[id^=templates_domain_table]", () => draw_templates_domain_table()); onVisible("[id^=mailbox_table]", () => draw_mailbox_table()); + onVisible("[id^=templates_mbox_table]", () => draw_templates_mbox_table()); onVisible("[id^=resource_table]", () => draw_resource_table()); onVisible("[id^=alias_table]", () => draw_alias_table()); onVisible("[id^=aliasdomain_table]", () => draw_aliasdomain_table()); diff --git a/data/web/json_api.php b/data/web/json_api.php index 1953d17ce..79b6bfd53 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -230,13 +230,27 @@ if (isset($_GET['query'])) { process_add_return(rsettings('add', $attr)); break; case "mailbox": - process_add_return(mailbox('add', 'mailbox', $attr)); + switch ($object) { + case "template": + process_add_return(mailbox('add', 'mailbox_templates', $attr)); + break; + default: + process_add_return(mailbox('add', 'mailbox', $attr)); + break; + } break; case "oauth2-client": process_add_return(oauth2('add', 'client', $attr)); break; case "domain": - process_add_return(mailbox('add', 'domain', $attr)); + switch ($object) { + case "template": + process_add_return(mailbox('add', 'domain_templates', $attr)); + break; + default: + process_add_return(mailbox('add', 'domain', $attr)); + break; + } break; case "resource": process_add_return(mailbox('add', 'resource', $attr)); @@ -519,7 +533,16 @@ if (isset($_GET['query'])) { echo '{}'; } break; - + case "template": + switch ($extra){ + case "all": + process_get_return(mailbox('get', 'domain_templates')); + break; + default: + process_get_return(mailbox('get', 'domain_templates', $extra)); + break; + } + break; default: $data = mailbox('get', 'domain_details', $object); process_get_return($data); @@ -992,7 +1015,16 @@ if (isset($_GET['query'])) { echo '{}'; } break; - + case "template": + switch ($extra){ + case "all": + process_get_return(mailbox('get', 'mailbox_templates')); + break; + default: + process_get_return(mailbox('get', 'mailbox_templates', $extra)); + break; + } + break; default: $tags = null; if (isset($_GET['tags']) && $_GET['tags'] != '') @@ -1641,6 +1673,9 @@ if (isset($_GET['query'])) { case "tag": process_delete_return(mailbox('delete', 'tags_domain', array('tags' => $items, 'domain' => $extra))); break; + case "template": + process_delete_return(mailbox('delete', 'domain_templates', array('ids' => $items))); + break; default: process_delete_return(mailbox('delete', 'domain', array('domain' => $items))); } @@ -1653,6 +1688,9 @@ if (isset($_GET['query'])) { case "tag": process_delete_return(mailbox('delete', 'tags_mailbox', array('tags' => $items, 'username' => $extra))); break; + case "template": + process_delete_return(mailbox('delete', 'mailbox_templates', array('ids' => $items))); + break; default: process_delete_return(mailbox('delete', 'mailbox', array('username' => $items))); } @@ -1814,7 +1852,14 @@ if (isset($_GET['query'])) { process_edit_return(mailbox('edit', 'time_limited_alias', array_merge(array('address' => $items), $attr))); break; case "mailbox": - process_edit_return(mailbox('edit', 'mailbox', array_merge(array('username' => $items), $attr))); + switch ($object) { + case "template": + process_edit_return(mailbox('edit', 'mailbox_templates', array_merge(array('ids' => $items), $attr))); + break; + default: + process_edit_return(mailbox('edit', 'mailbox', array_merge(array('username' => $items), $attr))); + break; + } break; case "syncjob": process_edit_return(mailbox('edit', 'syncjob', array_merge(array('id' => $items), $attr))); @@ -1826,7 +1871,14 @@ if (isset($_GET['query'])) { process_edit_return(mailbox('edit', 'resource', array_merge(array('name' => $items), $attr))); break; case "domain": - process_edit_return(mailbox('edit', 'domain', array_merge(array('domain' => $items), $attr))); + switch ($object) { + case "template": + process_edit_return(mailbox('edit', 'domain_templates', array_merge(array('ids' => $items), $attr))); + break; + default: + process_edit_return(mailbox('edit', 'domain', array_merge(array('domain' => $items), $attr))); + break; + } break; case "rl-domain": process_edit_return(ratelimit('edit', 'domain', array_merge(array('object' => $items), $attr))); diff --git a/data/web/lang/lang.ca-es.json b/data/web/lang/lang.ca-es.json index 3bb0f3e36..c2032da60 100644 --- a/data/web/lang/lang.ca-es.json +++ b/data/web/lang/lang.ca-es.json @@ -316,6 +316,7 @@ "bcc_type": "BCC type", "deactivate": "Desactivar", "description": "Descripció", + "dkim_key_length": "Mida de la clau DKIM (bits)", "domain": "Domini", "domain_admins": "Administradores de dominio", "domain_aliases": "Àlies de domini", @@ -327,6 +328,7 @@ "filter_table": "Filtrar taula", "filters": "Filtres", "fname": "Nom complert", + "force_pw_update": "Forçar l'actualització de la contrassenya al proper login", "in_use": "En ús (%)", "inactive": "Inactiu", "kind": "Tipus", @@ -334,6 +336,9 @@ "last_run_reset": "Executar a continuació", "mailbox_quota": "Mida màx. de quota", "mailboxes": "Bústies", + "max_aliases": "Màx. àlies possibles", + "max_mailboxes": "Màx. bústies possibles", + "max_quota": "Màx. quota per bústia", "mins_interval": "Intèrval (min)", "msg_num": "Missatge #", "multiple_bookings": "Múltiples reserves", @@ -346,6 +351,7 @@ "recipient_map_new": "Nou destinatari", "recipient_map_old": "Destinatari original", "recipient_maps": "Recipient maps", + "relay_all": "Retransmetre tods els recipients", "remove": "Esborrar", "resources": "Recursos", "running": "Executant-se", diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 159ca8867..9983f941e 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -706,10 +706,13 @@ "description": "Popis", "disable_login": "Zakázat přihlášení (ale stále přijímat poštu)", "disable_x": "Vypnout", + "dkim_domains_selector": "Selektor", + "dkim_key_length": "Délka DKIM klíče (v bitech)", "domain": "Doména", "domain_admins": "Správci domén", "domain_aliases": "Doménové aliasy", "domain_quota": "Kvóta", + "domain_quota_total": "Celková kvóta domény", "domains": "Domény", "edit": "Upravit", "empty": "Žádné výsledky", @@ -718,6 +721,8 @@ "filter_table": "Filtrovat tabulku", "filters": "Filtry", "fname": "Celé jméno", + "force_pw_update": "Vynutit změnu hesla při příštím přihlášení", + "gal": "Globální seznam adres", "goto_ham": "Učit se jako ham", "goto_spam": "Učit se jako spam", "hourly": "Každou hodinu", @@ -735,6 +740,9 @@ "mailbox_defquota": "Výchozí velikost schránky", "mailbox_quota": "Max. velikost schránky", "mailboxes": "Mailové schránky", + "max_aliases": "Max. počet aliasů", + "max_mailboxes": "Max. počet mailových schránek", + "max_quota": "Max. kvóta mailové schránky", "mins_interval": "Interval (min)", "msg_num": "Počet zpráv", "multiple_bookings": "Vícenásobné rezervace", @@ -760,6 +768,7 @@ "recipient_map_old": "Původní příjemce", "recipient_map_old_info": "Původní příjemce musí být platná emailová adresa nebo název domény.", "recipient_maps": "Mapy příjemců", + "relay_all": "Předávání všech příjemců", "remove": "Smazat", "resources": "Zdroje", "running": "Běží", diff --git a/data/web/lang/lang.da-dk.json b/data/web/lang/lang.da-dk.json index 6fd170d2a..8b5ef0d5f 100644 --- a/data/web/lang/lang.da-dk.json +++ b/data/web/lang/lang.da-dk.json @@ -640,11 +640,14 @@ "deactivate": "Deaktiver", "description": "Beskrivelse", "disable_login": "Tillad ikke login (indgående mail accepteres stadig)", - "disable_x": "Deaktiver", + "disable_x": "Deaktiver", + "dkim_domains_selector": "Vælger", + "dkim_key_length": "DKIM nøgle længde (bits)", "domain": "Domæne", "domain_admins": "Domæneadministratorer", "domain_aliases": "Domænealiaser", "domain_quota": "Kvote", + "domain_quota_total": "Samlet domænekvote", "domains": "Domains", "edit": "Edit", "empty": "Ingen resultater", @@ -653,6 +656,8 @@ "filter_table": "Filtertabel", "filters": "Filtre", "fname": "Fulde navn", + "force_pw_update": "Tving adgangskodeopdatering til næste login", + "gal": "Global adresseliste", "hourly": "Hver time", "in_use": "I brug (%)", "inactive": "Inaktiv", @@ -667,6 +672,9 @@ "mailboxes": "Postkasser", "mailbox_defaults": "Standardindstillinger", "mailbox_defaults_info": "Definer standardindstillinger for nye postkasser.", + "max_aliases": "Maks. mulige aliasser", + "max_mailboxes": "Maks. mulige postkasser", + "max_quota": "Maks. kvote pr. postkasse", "mins_interval": "Interval (min)", "msg_num": "Besked #", "multiple_bookings": "Flere bookinger", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 0ae8c59e1..8dd544542 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -746,10 +746,13 @@ "description": "Beschreibung", "disable_login": "Login verbieten (Mails werden weiterhin angenommen)", "disable_x": "Deaktivieren", + "dkim_domains_selector": "Selector", + "dkim_key_length": "DKIM-Schlüssellänge (bits)", "domain": "Domain", "domain_admins": "Domain-Administratoren", "domain_aliases": "Domain-Aliasse", "domain_quota": "Gesamtspeicher", + "domain_quota_total": "Domain-Speicherplatz gesamt", "domains": "Domains", "edit": "Bearbeiten", "empty": "Keine Einträge vorhanden", @@ -758,6 +761,8 @@ "filter_table": "Filtern", "filters": "Filter", "fname": "Name", + "force_pw_update": "Erzwinge Passwortänderung bei nächstem Login", + "gal": "Globales Adressbuch", "hourly": "Stündlich", "in_use": "Prozentualer Gebrauch", "inactive": "Inaktiv", @@ -773,6 +778,9 @@ "mailbox_defquota": "Standard-Quota", "mailbox_quota": "Max. Größe einer Mailbox", "mailboxes": "Mailboxen", + "max_aliases": "Max. mögliche Aliasse", + "max_mailboxes": "Max. mögliche Mailboxen", + "max_quota": "Max. Größe per Mailbox", "mins_interval": "Intervall (min)", "msg_num": "Anzahl Nachrichten", "multiple_bookings": "Mehrfachbuchen", @@ -796,6 +804,7 @@ "recipient_map_old": "Original-Empfänger", "recipient_map_old_info": "Der originale Empfänger muss eine E-Mail-Adresse oder ein Domainname sein.", "recipient_maps": "Empfängerumschreibungen", + "relay_all": "Alle Empfänger-Adressen relayen", "remove": "Entfernen", "resources": "Ressourcen", "running": "In Ausführung", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 02a699a92..0dcfdaeee 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -439,6 +439,9 @@ "target_domain_invalid": "Target domain %s is invalid", "targetd_not_found": "Target domain %s not found", "targetd_relay_domain": "Target domain %s is a relay domain", + "template_exists": "Template %s already exists", + "template_id_invalid": "Template ID %s invalid", + "template_name_invalid": "Template name invalid", "temp_error": "Temporary error", "text_empty": "Text must not be empty", "tfa_token_invalid": "TFA token invalid", @@ -713,6 +716,7 @@ "add_mailbox": "Add mailbox", "add_recipient_map_entry": "Add recipient map", "add_resource": "Add resource", + "add_template": "Add Template", "add_tls_policy_map": "Add TLS policy map", "address_rewriting": "Address rewriting", "alias": "Alias", @@ -749,10 +753,14 @@ "description": "Description", "disable_login": "Disallow login (incoming mail is still accepted)", "disable_x": "Disable", + "dkim_domains_selector": "Selector", + "dkim_key_length": "DKIM key length (bits)", "domain": "Domain", "domain_admins": "Domain administrators", "domain_aliases": "Domain aliases", + "domain_templates": "Domain Templates", "domain_quota": "Quota", + "domain_quota_total": "Total domain quota", "domains": "Domains", "edit": "Edit", "empty": "No results", @@ -761,6 +769,8 @@ "filter_table": "Filter table", "filters": "Filters", "fname": "Full name", + "force_pw_update": "Force password update at next login", + "gal": "Global Address List", "goto_ham": "Learn as ham", "goto_spam": "Learn as spam", "hourly": "Hourly", @@ -776,8 +786,12 @@ "mailbox_defaults": "Default settings", "mailbox_defaults_info": "Define default settings for new mailboxes.", "mailbox_defquota": "Default mailbox size", + "mailbox_templates": "Mailbox Templates", "mailbox_quota": "Max. size of a mailbox", "mailboxes": "Mailboxes", + "max_aliases": "Max. aliases", + "max_mailboxes": "Max. possible mailboxes", + "max_quota": "Max. quota per mailbox", "mins_interval": "Interval (min)", "msg_num": "Message #", "multiple_bookings": "Multiple bookings", @@ -803,6 +817,8 @@ "recipient_map_old": "Original recipient", "recipient_map_old_info": "A recipient maps original destination must be valid email addresses or a domain name.", "recipient_maps": "Recipient maps", + "relay_all": "Relay all recipients", + "relay_unknown": "Relay unknown mailboxes", "remove": "Remove", "resources": "Resources", "running": "Running", @@ -839,6 +855,8 @@ "table_size_show_n": "Show %s items", "target_address": "Goto address", "target_domain": "Target domain", + "templates": "Templates", + "template": "Template", "tls_enforce_in": "Enforce TLS incoming", "tls_enforce_out": "Enforce TLS outgoing", "tls_map_dest": "Destination", @@ -1012,6 +1030,8 @@ "settings_map_added": "Added settings map entry", "settings_map_removed": "Removed settings map ID %s", "sogo_profile_reset": "SOGo profile for user %s was reset", + "template_added": "Added template %s", + "template_modified": "Changes to template %s have been saved", "tls_policy_map_entry_deleted": "TLS policy map ID %s has been deleted", "tls_policy_map_entry_saved": "TLS policy map entry \"%s\" has been saved", "ui_texts": "Saved changes to UI texts", diff --git a/data/web/lang/lang.es-es.json b/data/web/lang/lang.es-es.json index 67c30ae15..d14384ee3 100644 --- a/data/web/lang/lang.es-es.json +++ b/data/web/lang/lang.es-es.json @@ -488,10 +488,13 @@ "deactivate": "Desactivar", "description": "Descripción", "disable_x": "Desactivar", + "dkim_domains_selector": "Selector", + "dkim_key_length": "Longitud de la llave DKIM (bits)", "domain": "Dominio", "domain_admins": "Administradores por dominio", "domain_aliases": "Alias de dominio", "domain_quota": "Cuota", + "domain_quota_total": "Cuota total del dominio", "domains": "Dominios", "edit": "Editar", "empty": "Sin resultados", @@ -500,6 +503,8 @@ "filter_table": "Filtrar tabla", "filters": "Filtros", "fname": "Nombre completo", + "force_pw_update": "Forzar cambio de contraseña en el próximo inicio de sesión", + "gal": "Lista global de direcciones (GAL)", "hourly": "Cada hora", "in_use": "En uso (%)", "inactive": "Inactivo", @@ -508,6 +513,9 @@ "mailbox_defquota": "Tamaño de buzón predeterminado", "mailbox_quota": "Tamaño máx. de cuota", "mailboxes": "Buzones", + "max_aliases": "Máx. alias posibles", + "max_mailboxes": "Máx. buzones posibles", + "max_quota": "Máx. cuota por buzón", "mins_interval": "Intervalo (min)", "msg_num": "Mensaje #", "multiple_bookings": "Reservas multiples", @@ -523,6 +531,7 @@ "recipient_map_old": "Destinatario original", "recipient_map_old_info": "El destino original de una regla de destinatario debe ser una dirección de correo electrónico válida o un nombre de dominio.", "recipient_maps": "Reglas de destinatario", + "relay_all": "Retransmitir todos los destinatarios", "remove": "Eliminar", "resources": "Recursos", "running": "En marcha", diff --git a/data/web/lang/lang.fi-fi.json b/data/web/lang/lang.fi-fi.json index 3ae5f0b25..1468761ca 100644 --- a/data/web/lang/lang.fi-fi.json +++ b/data/web/lang/lang.fi-fi.json @@ -558,11 +558,14 @@ "daily": "Päivittäin", "deactivate": "Deaktivoi", "description": "Kuvaus", - "disable_x": "Poista käytöstä", + "disable_x": "Poista käytöstä", + "dkim_domains_selector": "Valitsin", + "dkim_key_length": "DKIM avaimen pituus (bits)", "domain": "Verkkotunnukset", "domain_admins": "Verkkotunnuksien järjestelmänvalvojat", "domain_aliases": "Domain alueiden aliakset", "domain_quota": "Kiintiö", + "domain_quota_total": "Verkkotunnuksen kokonaiskiintiö", "domains": "Verkkotunnukset", "edit": "Muokkaa", "empty": "Ei tuloksia", @@ -571,6 +574,8 @@ "filter_table": "Suodata taulu", "filters": "Suodattimet", "fname": "Koko nimi", + "force_pw_update": "Pakota salasanan vaihto seuraavan sisään kirjautumisen jälkeen", + "gal": "Yleinen osoite luettelo", "hourly": "Tunnin välein", "in_use": "Käytössä (%)", "inactive": "Epäaktiivinen", @@ -581,6 +586,9 @@ "mailbox_defquota": "Tilin koko", "mailbox_quota": "Kiintiön koko", "mailboxes": "Sähköposti tilit", + "max_aliases": "Max. mahdolliset aliakset", + "max_mailboxes": "Max. mahdolliset sähkö postilaatikot", + "max_quota": "Maks. Kiintiö sähköposti laatikkoa kohden", "mins_interval": "Aikaväli (min)", "msg_num": "Viestejä #", "multiple_bookings": "Useita varauksia", @@ -600,6 +608,7 @@ "recipient_map_old": "Alkuperäinen vastaanottaja", "recipient_map_old_info": "Vastaanottajan yhdistämis määritysten alkuperäisen kohteen on oltava kelvollinen sähköposti osoite tai verkkotunnus alueen nimi.", "recipient_maps": "Vastaanottajien yhdistämis määritykset", + "relay_all": "Välitä kaikki vastaanottajat", "remove": "Poista", "resources": "Resursseja", "running": "Running", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 3311e8672..0a3e8075c 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -661,18 +661,23 @@ "description": "Description", "disable_login": "Refuser l’ouverture de session (le courrier entrant est toujours accepté)", "disable_x": "Désactiver", + "dkim_domains_selector": "Sélecteur", + "dkim_key_length": "Longueur de la clé DKIM (bits)", "domain": "Domaine", "domain_admins": "Administrateurs de domaine", "domain_aliases": "Alias de domaine", "domain_quota": "Quota", + "domain_quota_total": "Quota total du domaine", "domains": "Domaines", "edit": "Editer", "empty": "Pas de résulats", "enable_x": "Activer", "excludes": "Exclut", "filter_table": "Table de filtre", - "filters": "Filtres", + "filters": "Filtres", "fname": "Nom complet", + "force_pw_update": "Forcer la mise à jour du mot de passe à la prochaine ouverture de session", + "gal": "Carnet d'Adresses Global (GAL)", "hourly": "Horaire", "in_use": "Utilisé (%)", "inactive": "Inactif", @@ -687,6 +692,9 @@ "mailboxes": "Boîtes mail", "mailbox_defaults": "Paramètres par défaut", "mailbox_defaults_info": "Définir les paramètres par défaut pour les nouvelles boîtes aux lettres.", + "max_aliases": "Nombre maximal d'alias", + "max_mailboxes": "Nombre maximal de boîtes", + "max_quota": "Quota max. par boîte mail", "mins_interval": "Intervalle (min)", "msg_num": "Message #", "multiple_bookings": "Réservations multiples", @@ -710,6 +718,7 @@ "recipient_map_old": "Destinataire original", "recipient_map_old_info": "Une carte de destination originale doit être une adresse e-mail valide ou un nom de domaine.", "recipient_maps": "Cartes des bénéficiaires", + "relay_all": "Relayer tous les destinataires", "remove": "Supprimer", "resources": "Ressources", "running": "En fonctionnement", diff --git a/data/web/lang/lang.hu-hu.json b/data/web/lang/lang.hu-hu.json index 5888a1867..4fa55a3b5 100644 --- a/data/web/lang/lang.hu-hu.json +++ b/data/web/lang/lang.hu-hu.json @@ -118,6 +118,7 @@ "filter_table": "Szűrő-táblázat", "filters": "Szűrők", "fname": "Teljes név", + "force_pw_update": "Új jelszót kell beállítania a csoportos szolgáltatások eléréséhez.", "hourly": "Óránként", "in_use": "Foglalt (%)", "inactive": "Inaktív", diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index 09b3ee309..d94ba21c2 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -711,10 +711,13 @@ "description": "Descrizione", "disable_login": "Disabilita l'accesso (la posta in arrivo viene correttamente recapitata)", "disable_x": "Disabilita", + "dkim_domains_selector": "Selettore", + "dkim_key_length": "Lunghezza chiave DKIM (bits)", "domain": "Dominio", "domain_admins": "Amministratori di dominio", "domain_aliases": "Alias di domini", "domain_quota": "Spazio", + "domain_quota_total": "Spazio totale dominio", "domains": "Domini", "edit": "Modifica", "empty": "Nessun risultato", @@ -738,6 +741,9 @@ "mailbox_defquota": "Dimensione predefinita della casella di posta", "mailbox_quota": "Massima dimensione della casella", "mailboxes": "Caselle", + "max_aliases": "Numero massimo alias", + "max_mailboxes": "Numero massimo caselle di posta", + "max_quota": "Massimo spazio per casella", "mins_interval": "Intervallo (min)", "msg_num": "Messaggio #", "multiple_bookings": "Prenotazioni multiple", @@ -761,6 +767,7 @@ "recipient_map_old": "Original recipient", "recipient_map_old_info": "A recipient maps original destination must be valid email addresses or a domain name.", "recipient_maps": "Recipient maps", + "relay_all": "Trasmettere a tutti i destinatari", "remove": "Rimuovi", "resources": "Risorse", "running": "In esecuzione", diff --git a/data/web/lang/lang.ko-kr.json b/data/web/lang/lang.ko-kr.json index 14b4554e5..5a4a46cff 100644 --- a/data/web/lang/lang.ko-kr.json +++ b/data/web/lang/lang.ko-kr.json @@ -627,10 +627,13 @@ "description": "설명", "disable_login": "로그인 비활성화 (오는 메일은 계속 받습니다.)", "disable_x": "비활성화", + "dkim_domains_selector": "선택기", + "dkim_key_length": "DKIM key 길이 (bits)", "domain": "도메인", "domain_admins": "도메인 관리자", "domain_aliases": "도메인 별칭", "domain_quota": "한도", + "domain_quota_total": "도메인에 할당할 디스크 크기", "domains": "도메인", "edit": "수정", "empty": "결과 없음", @@ -639,6 +642,8 @@ "filter_table": "Filter table", "filters": "Filters", "fname": "Full name", + "force_pw_update": "그룹웨어 관련 서비스에 접근하기 위해서는 새 비밀번호를 꼭 설정해야 합니다.", + "gal": "글로벌 주소 리스트", "hourly": "Hourly", "in_use": "In use (%)", "inactive": "Inactive", @@ -651,6 +656,9 @@ "mailbox_defquota": "Default mailbox size", "mailbox_quota": "Max. size of a mailbox", "mailboxes": "Mailboxes", + "max_aliases": "최대 별칭 주소", + "max_mailboxes": "최대 메일함 수", + "max_quota": "Max. quota per mailbox", "mins_interval": "Interval (min)", "msg_num": "Message #", "multiple_bookings": "Multiple bookings", @@ -670,6 +678,7 @@ "recipient_map_old": "Original recipient", "recipient_map_old_info": "A recipient maps original destination must be valid email addresses or a domain name.", "recipient_maps": "Recipient maps", + "relay_all": "모든 수신자에게 릴레이", "remove": "Remove", "resources": "Resources", "running": "Running", diff --git a/data/web/lang/lang.lv-lv.json b/data/web/lang/lang.lv-lv.json index 8a658f14f..d3b53ddf6 100644 --- a/data/web/lang/lang.lv-lv.json +++ b/data/web/lang/lang.lv-lv.json @@ -323,10 +323,12 @@ "bcc_type": "BCC tips", "deactivate": "Deaktivizēt", "description": "Apraksts", + "dkim_key_length": "DKIM atslēgas garums (bits)", "domain": "Domēns", "domain_admins": "Domēna administratori", "domain_aliases": "Domēna aliases", "domain_quota": "Kvota", + "domain_quota_total": "Kopējā domēna kvota", "domains": "Domēns", "edit": "Labot", "empty": "Nav rezultātu", @@ -334,6 +336,7 @@ "filter_table": "Filtra tabula", "filters": "Filtri", "fname": "Pilns vārds", + "force_pw_update": "Piespiedu paroles atjaunošana pie nākošās pieslēgšanās", "in_use": "Lietošanā (%)", "inactive": "Neaktīvs", "kind": "Veids", @@ -341,6 +344,9 @@ "last_run_reset": "Nākamais grafiks", "mailbox_quota": "Maks. pastkastes izmērs", "mailboxes": "Pastkaste", + "max_aliases": "Maks. iespejamās aliases", + "max_mailboxes": "Maks. iespējamās pastkastes", + "max_quota": "Maks. kvota uz pastkasti", "mins_interval": "Intervāls (min)", "msg_num": "Vēstule #", "multiple_bookings": "Vairāki rezervējumi", @@ -352,6 +358,7 @@ "recipient_map_new": "Jauns saņēmējs", "recipient_map_old": "Oriģinālais saņēmējs", "recipient_maps": "Saņēmēja kartes", + "relay_all": "Pārsūtīt visus saņēmējus", "remove": "Noņemt", "resources": "Resursi", "running": "Darbojas", diff --git a/data/web/lang/lang.nl-nl.json b/data/web/lang/lang.nl-nl.json index bbe96fca7..025f9960b 100644 --- a/data/web/lang/lang.nl-nl.json +++ b/data/web/lang/lang.nl-nl.json @@ -651,10 +651,13 @@ "description": "Beschrijving", "disable_login": "Weiger aanmelden (inkomende mail blijft binnenkomen)", "disable_x": "Schakel uit", + "dkim_domains_selector": "Selector", + "dkim_key_length": "Grootte van key (bits)", "domain": "Domein", "domain_admins": "Domeinadministrators", "domain_aliases": "Domeinaliassen", "domain_quota": "Quota", + "domain_quota_m": "Totale domeinquota", "domains": "Domeinen", "edit": "Wijzig", "empty": "Geen resultaten", @@ -663,6 +666,8 @@ "filter_table": "Filtertabel", "filters": "Filters", "fname": "Volledige naam", + "force_pw_update": "Vereis nieuw wachtwoord bij eerstvolgende login", + "gal": "Globale adreslijst", "hourly": "Ieder uur", "in_use": "In gebruik (%)", "inactive": "Inactief", @@ -677,6 +682,9 @@ "mailboxes": "Mailboxen", "mailbox_defaults": "Standaardinstellingen", "mailbox_defaults_info": "Stel standaardinstellingen in voor nieuwe mailboxen.", + "max_aliases": "Maximaal aantal aliassen", + "max_mailboxes": "Maximaal aantal mailboxen", + "max_quota": "Mailboxquota", "mins_interval": "Interval (min)", "msg_num": "Bericht #", "multiple_bookings": "Meerdere boekingen", @@ -699,6 +707,7 @@ "recipient_map_old": "Oorspronkelijke ontvanger", "recipient_map_old_info": "De oorspronkelijke bestemming van een ontvanger-map dient een geldig mailadres of domeinnaam te zijn.", "recipient_maps": "Ontvanger-maps", + "relay_all": "Forward alle ontvangers", "remove": "Verwijder", "resources": "Resources", "running": "Wordt uitgevoerd", diff --git a/data/web/lang/lang.pl-pl.json b/data/web/lang/lang.pl-pl.json index a3721617f..c2f2bd366 100644 --- a/data/web/lang/lang.pl-pl.json +++ b/data/web/lang/lang.pl-pl.json @@ -233,10 +233,12 @@ "daily": "Co dzień", "deactivate": "Wyłącz", "description": "Opis", + "dkim_key_length": "Długość klucza DKIM (bity)", "domain": "Domena", "domain_admins": "Administratorzy domeny", "domain_aliases": "Aliasy domeny", "domain_quota": "Limit wielkości", + "domain_quota_total": "Łączny limit domeny", "domains": "Domeny", "edit": "Edytuj", "empty": "Brak wyników", @@ -250,6 +252,9 @@ "last_run": "Ostatnie uruchomienie", "mailbox_quota": "Maks. wielkość skrzynki", "mailboxes": "Skrzynki", + "max_aliases": "Maks. liczba aliasów", + "max_mailboxes": "Maks. liczba skrzynek", + "max_quota": "Maks. wielkość skrzynki", "mins_interval": "Zakres (min)", "msg_num": "Wiadomość #", "multiple_bookings": "Wielokrotne rejestracje", @@ -258,6 +263,7 @@ "no_record_single": "Brak rekordu", "quarantine_notification": "Powiadomienia o kwarantannie", "quick_actions": "Szybkie działania", + "relay_all": "Przekaż wszystkim odbiorcom", "remove": "Usuń", "resources": "Zasoby", "spam_aliases": "Alias tymczasowy", diff --git a/data/web/lang/lang.pt-pt.json b/data/web/lang/lang.pt-pt.json index 3e60fec08..6eba05290 100644 --- a/data/web/lang/lang.pt-pt.json +++ b/data/web/lang/lang.pt-pt.json @@ -9,7 +9,7 @@ "backup_mx_options": "Opções Backup MX:", "description": "Descrição:", "domain": "Domínio", - "domain_quota_m": "Total de espaço por domínio(MiB):", + "domain_quota_m": "Total de espaço por domínio (MiB):", "full_name": "Nome:", "mailbox_quota_m": "Máximo espaço por conta (MiB):", "mailbox_username": "Usuário (primeira parte do endereço de email):", @@ -161,10 +161,12 @@ "aliases": "Apelidos", "backup_mx": "Backup MX", "description": "Descrição:", + "dkim_key_length": "Tamanho do registro DKIM (bits)", "domain": "Domínio", "domain_admins": "Administradores de domínio", "domain_aliases": "Encaminhamento de Domínio", "domain_quota": "Espaço", + "domain_quota_total": "Total de espaço por domínio", "domains": "Domínios", "edit": "Alterar", "filter_table": "Procurar", @@ -172,9 +174,13 @@ "in_use": "Em uso (%)", "mailbox_quota": "Espaço máximo da Conta", "mailboxes": "Contas", + "max_aliases": "Máximo de apelidos", + "max_mailboxes": "Máximo de contas", + "max_quota": "Máximo espaço por conta", "msg_num": "Mensagens", "no_record": "Nenhum registro", "no_record_single": "Nenhum registro", + "relay_all": "Relay para todas as contas", "remove": "Remover", "target_address": "Encaminhar para", "target_domain": "Domínio Destino", diff --git a/data/web/lang/lang.ro-ro.json b/data/web/lang/lang.ro-ro.json index 033d7421c..6100c0908 100644 --- a/data/web/lang/lang.ro-ro.json +++ b/data/web/lang/lang.ro-ro.json @@ -712,10 +712,13 @@ "description": "Descriere", "disable_login": "Nu permiteți autentificarea", "disable_x": "Dezactivează", + "dkim_domains_selector": "Selector", + "dkim_key_length": "Lungimea cheii DKIM (biți)", "domain": "Domeniu", "domain_admins": "Administratori domeniu", "domain_aliases": "Aliasuri de domenii", "domain_quota": "Cotă", + "domain_quota_total": "Cota totală domeniu", "domains": "Domenii", "edit": "Editează", "empty": "Nici un rezultat", @@ -724,6 +727,8 @@ "filter_table": "Tabel filtre", "filters": "Filtre", "fname": "Nume complet", + "force_pw_update": "Forțează o actualizare a parolei la următoarea conectare", + "gal": "Lista adreselor globale", "goto_ham": "Învață ca ham", "goto_spam": "Învață ca spam", "hourly": "Din oră în oră", @@ -741,6 +746,9 @@ "mailboxes": "Cutii poștale", "mailbox_defaults": "Setări implicite", "mailbox_defaults_info": "Definiți setările implicite pentru cutiile poștale noi.", + "max_aliases": "Număr maxim posibil de aliasuri", + "max_mailboxes": "Număr maxim posibil de cutii poștale", + "max_quota": "Cotă maximă pentru cutia poștală", "mins_interval": "Interval (min)", "msg_num": "Mesaj #", "multiple_bookings": "Rezervări multiple", @@ -766,6 +774,7 @@ "recipient_map_old": "Destinatar original", "recipient_map_old_info": "Destinația originală a hărților destinatarilor trebuie să fie adrese de email valide sau nume de domeniu.", "recipient_maps": "Hărți destinatar", + "relay_all": "Retransmite toți destinatarii", "remove": "Elimină", "resources": "Resurse", "running": "Rulare", diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index 336272a03..69fd75b27 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -710,10 +710,13 @@ "description": "Описание", "disable_login": "Вход в систему запрещен", "disable_x": "Отключить", + "dkim_domains_selector": "Selector", + "dkim_key_length": "Длина DKIM ключа (bits)", "domain": "Домен", "domain_admins": "Администраторы домена", "domain_aliases": "Псевдонимы доменов", "domain_quota": "Квота", + "domain_quota_total": "Квота домена", "domains": "Домены", "edit": "Изменить", "empty": "Пусто", @@ -722,6 +725,8 @@ "filter_table": "Поиск", "filters": "Фильтры", "fname": "Полное имя", + "force_pw_update": "Требовать смены пароля при следующем входе в систему", + "gal": "GAL - Глобальная адресная книга", "goto_ham": "Запомнить как полезную почту", "goto_spam": "Запомнить как спам", "hourly": "Раз в час", @@ -739,6 +744,9 @@ "mailbox_defquota": "Квота по умолчанию", "mailbox_quota": "Макс. квота почт. ящика", "mailboxes": "Почтовые ящики", + "max_aliases": "Максимум псевдонимов", + "max_mailboxes": "Максимум почтовых ящиков", + "max_quota": "Максимальная квота почтового аккаунта", "mins_interval": "Интервал (в минутах)", "msg_num": "Писем", "multiple_bookings": "Несколько бронирований", @@ -764,6 +772,7 @@ "recipient_map_old": "Получатель", "recipient_map_old_info": "Должен быть валидный почтовым ящиком или доменом.", "recipient_maps": "Перезапись получателя", + "relay_all": "Ретрансляция всех получателей", "remove": "Удалить", "resources": "Ресурсы", "running": "В процессе", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 365e2ffac..83dded150 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -712,10 +712,13 @@ "description": "Popis", "disable_login": "Zablokovať prihlásenie (nevzťahuje sa na prichádzajúcu poštu)", "disable_x": "Pozastaviť", + "dkim_domains_selector": "Selektor", + "dkim_key_length": "Dĺžka DKIM kľúča (bity)", "domain": "Doména", "domain_admins": "Administrátori domény", "domain_aliases": "Alias domény", "domain_quota": "Kvóta", + "domain_quota_total": "Celkové kvóta domény", "domains": "Domény", "edit": "Upraviť", "empty": "Žiadne výsledky", @@ -724,6 +727,8 @@ "filter_table": "Filtrovať tabuľku", "filters": "Filtre", "fname": "Celé meno", + "force_pw_update": "Vynútiť zmenu hesla pri ďalšom prihlásení", + "gal": "Globálny zoznam adries", "goto_ham": "Považovať za ham", "goto_spam": "Považovať za spam", "hourly": "Hodinový", @@ -741,6 +746,9 @@ "mailbox_defquota": "Predvolená veľkosť schránky", "mailbox_quota": "Max. veľkosť schránky", "mailboxes": "Mailové schránky", + "max_aliases": "Max. počet aliasov", + "max_mailboxes": "Max. počet mailových schránok", + "max_quota": "Max. kvóta pre mailovú schránku", "mins_interval": "Interval (min)", "msg_num": "Počet správ", "multiple_bookings": "Viaceré rezervácie", @@ -766,6 +774,7 @@ "recipient_map_old": "Originálny príjemca", "recipient_map_old_info": "Originálny cieľ mapy príjemcu musí byť platná emailová adresa alebo meno domény.", "recipient_maps": "Mapy príjemcov", + "relay_all": "Preposielať všetkým príjemcom", "remove": "Odstrániť", "resources": "Zdroje", "running": "Bežiaci", diff --git a/data/web/lang/lang.sv-se.json b/data/web/lang/lang.sv-se.json index c545cd1ca..518d2ddcd 100644 --- a/data/web/lang/lang.sv-se.json +++ b/data/web/lang/lang.sv-se.json @@ -668,10 +668,13 @@ "description": "Beskrivning", "disable_login": "Inaktivera inloggning (inkommande post kommer fortfarande tas emot)", "disable_x": "Inaktivera", + "dkim_domains_selector": "Välj", + "dkim_key_length": "DKIM-nyckellängd (bitar)", "domain": "Domän", "domain_admins": "Domänadministratörer", "domain_aliases": "Domänalias", "domain_quota": "Kvot", + "domain_quota_total": "Total kvot per postlåda", "domains": "Domäner", "edit": "Ändra", "empty": "Ingen information", @@ -680,6 +683,8 @@ "filter_table": "Filtrera tabellen", "filters": "Postfilter", "fname": "Fullständigt namn", + "force_pw_update": "Kräv uppdatering av lösenordet vid nästa inloggning", + "gal": "Global adressbok", "hourly": "Varje timme", "in_use": "Användning (%)", "inactive": "Inaktiv", @@ -694,6 +699,9 @@ "mailboxes": "Postlådor", "mailbox_defaults": "Standardinställningar", "mailbox_defaults_info": "Standardinställningar för nya postlådor.", + "max_aliases": "Max antal alias", + "max_mailboxes": "Max antal postlådor", + "max_quota": "Max. kvot per postlåda", "mins_interval": "Interval (min)", "msg_num": "Antal meddelanden", "multiple_bookings": "Flera bokningar", @@ -717,6 +725,7 @@ "recipient_map_old": "Ursprunglig mottagaren", "recipient_map_old_info": "Den ursprungliga mottagaren måste vara en giltiga e-postadresser eller ett domännamn.", "recipient_maps": "Skriv om mottagaradressen", + "relay_all": "Vidarebefordra alla mottagare", "remove": "Ta bort", "resources": "Resurser", "running": "Körs", diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 06360dc26..883fd2c9d 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -707,10 +707,13 @@ "daily": "Раз на день", "description": "Опис", "disable_x": "Вимкнути", + "dkim_domains_selector": "Селектор", + "dkim_key_length": "Довжина ключа DKIM (біт)", "domain": "Домен", "domain_admins": "Адміністратори домену", "domain_aliases": "Псевдоніми доменів", "domain_quota": "Квота", + "domain_quota_total": "Загальна квота домену", "domains": "Домени", "edit": "Змінити", "empty": "Пусто", @@ -719,6 +722,8 @@ "filter_table": "Пошук", "filters": "Фильтри", "fname": "Повне ім'я", + "gal": "GAL - Глобальна адресна книга", + "force_pw_update": "Вимагати зміну пароля при наступному вході до системи", "goto_spam": "Запам'ятати як спам", "hourly": "Щогодини", "in_use": "Використано (%)", @@ -731,6 +736,9 @@ "mailbox": "Поштовий акаунт", "mailbox_defaults_info": "Визначте параметри за замовчуванням для нових поштових акаунтів.", "mailbox_quota": "Макс. квота пошт. ящика", + "max_aliases": "Максимум псевдонімів", + "max_mailboxes": "Максимум поштових скриньок", + "max_quota": "Максимальна квота поштового акаунту", "mins_interval": "Інтервал (у хвилинах)", "msg_num": "Листів", "multiple_bookings": "Декілька бронювань", @@ -751,6 +759,7 @@ "recipient_map_new_info": "Повинен бути чинною поштовою скринькою.", "recipient_map_old": "Одержувач", "recipient_maps": "Перезапис одержувача", + "relay_all": "Ретрансляція всіх отримувачів", "remove": "Видалити", "resources": "Ресурси", "running": "В процесі", diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json index e1c50ffe8..ddb5a9ec4 100644 --- a/data/web/lang/lang.zh-cn.json +++ b/data/web/lang/lang.zh-cn.json @@ -640,10 +640,13 @@ "description": "描述", "disable_login": "不允许登录 (仍然会接收邮件)", "disable_x": "关闭", + "dkim_domains_selector": "选择器", + "dkim_key_length": "DKIM密钥长度 (bits)", "domain": "域名", "domain_admins": "域名管理员", "domain_aliases": "域名别名", "domain_quota": "配额", + "domain_quota_total": "域名总配额", "domains": "域名", "edit": "编辑", "empty": "结果为空", @@ -652,6 +655,8 @@ "filter_table": "筛选表格", "filters": "过滤器", "fname": "全名", + "force_pw_update": "你必须设置一个新密码以继续使用群件相关服务。", + "gal": "全球地址簿", "hourly": "每小时", "in_use": "使用数 (%)", "inactive": "禁用", @@ -666,6 +671,9 @@ "mailboxes": "邮箱", "mailbox_defaults": "默认设置", "mailbox_defaults_info": "配置新邮箱的默认设置", + "max_aliases": "最大允许地址别名数", + "max_mailboxes": "最大允许邮箱数", + "max_quota": "每个邮箱的最大配额", "mins_interval": "间隔 (分钟)", "msg_num": "消息 #", "multiple_bookings": "登记限制", @@ -685,6 +693,7 @@ "recipient_map_old": "原收件人", "recipient_map_old_info": "原收件人必须为合法的邮件地址", "recipient_maps": "收件人映射", + "relay_all": "中继所有收件人", "remove": "删除", "resources": "日历资源", "running": "运行中", diff --git a/data/web/lang/lang.zh-tw.json b/data/web/lang/lang.zh-tw.json index d0d6bb14e..89b984f6e 100644 --- a/data/web/lang/lang.zh-tw.json +++ b/data/web/lang/lang.zh-tw.json @@ -722,10 +722,13 @@ "description": "描述", "disable_login": "不允許登入 (仍然會接收郵件)", "disable_x": "關閉", + "dkim_domains_selector": "選擇器", + "dkim_key_length": "DKIM 金鑰長度 (bits)", "domain": "域名", "domain_admins": "域名管理員", "domain_aliases": "域名別名", "domain_quota": "容量配額", + "domain_quota_total": "域名總容量配額", "domains": "域名", "edit": "編輯", "empty": "沒有結果", @@ -734,6 +737,8 @@ "filter_table": "篩選表格", "filters": "過濾器", "fname": "全名", + "force_pw_update": "你必須設定一個新密碼以繼續使用相關服務。", + "gal": "全域地址清單", "goto_ham": "學習為非垃圾郵件", "goto_spam": "學習為垃圾郵件", "hourly": "每小時", @@ -751,6 +756,9 @@ "mailbox_defquota": "預設信箱大小", "mailbox_quota": "最大信箱大小", "mailboxes": "信箱", + "max_aliases": "地址別名上限", + "max_mailboxes": "信箱數量上限", + "max_quota": "每個信箱的最大容量配額", "mins_interval": "間隔 (分鐘)", "msg_num": "訊息 #", "multiple_bookings": "重複登記", @@ -776,6 +784,7 @@ "recipient_map_old": "原收件人", "recipient_map_old_info": "原收件人必須為有效的郵件地址", "recipient_maps": "收件人規則表", + "relay_all": "中繼所有收件人", "remove": "刪除", "resources": "資源", "running": "執行中", diff --git a/data/web/mailbox.php b/data/web/mailbox.php index a8abd7ca7..65c76f531 100644 --- a/data/web/mailbox.php +++ b/data/web/mailbox.php @@ -40,6 +40,7 @@ $template_data = [ 'domains' => $domains, 'mailboxes' => $mailboxes, 'lang_mailbox' => json_encode($lang['mailbox']), + 'lang_rl' => json_encode($lang['ratelimit']), 'lang_datatables' => json_encode($lang['datatables']), ]; diff --git a/data/web/templates/base.twig b/data/web/templates/base.twig index 7df1f49b1..08da5ca9d 100644 --- a/data/web/templates/base.twig +++ b/data/web/templates/base.twig @@ -143,10 +143,10 @@ var mailcow_info = { version_tag: '{{ mailcow_info.version_tag }}', last_version_tag: '{{ mailcow_info.last_version_tag }}', - updatedAt: '{{ mailcow_info.updatedAt }}', + updatedAt: '{{ mailcow_info.updated_at }}', project_url: '{{ mailcow_info.project_url }}', - project_owner: '{{ mailcow_info.project_owner }}', - project_repo: '{{ mailcow_info.project_repo }}', + project_owner: '{{ mailcow_info.git_owner }}', + project_repo: '{{ mailcow_info.git_repo }}', branch: '{{ mailcow_info.mailcow_branch }}' }; diff --git a/data/web/templates/edit/domain-defaults.twig b/data/web/templates/edit/domain-defaults.twig deleted file mode 100644 index 84b150dac..000000000 --- a/data/web/templates/edit/domain-defaults.twig +++ /dev/null @@ -1,156 +0,0 @@ -{% extends 'edit.twig' %} - -{% block inner_content %} -{% if result %} - - {{ lang.edit.domain }} - {{ lang.edit.ratelimit }} - {{ lang.edit.spam_filter }} - {{ lang.edit.quota_warning_bcc }} - - - - - - - - - - - {% if mailcow_cc_role == 'admin' %} - - {{ lang.edit.max_aliases }} - - - - - - {{ lang.edit.max_mailboxes }} - - - - - - {{ lang.edit.mailbox_quota_def }} - - - - - - {{ lang.edit.max_quota }} - - - - - - {{ lang.edit.domain_quota }} - - - - - {% endif %} - - - - - {{ lang.edit.active }} - - - - - - {{ lang.admin.save }} - - - - - - - - - {{ lang.edit.ratelimit }} - - - {% include 'mailbox/rl-frame.twig' %} - - {{ lang.admin.save }} - - - - - - - - {{ lang.user.spamfilter_wl }} - {{ lang.user.spamfilter_wl_desc|raw }} - - - - - {{ lang.user.spamfilter_table_add }} - - - - - - - {{ lang.mailbox.toggle_all }} - {{ lang.mailbox.remove }} - - - - - {{ lang.user.spamfilter_bl }} - {{ lang.user.spamfilter_bl_desc|raw }} - - - - - {{ lang.user.spamfilter_table_add }} - - - - - - - {{ lang.mailbox.toggle_all }} - {{ lang.mailbox.remove }} - - - - - - - - - {{ lang.edit.quota_warning_bcc }} - {{ lang.edit.quota_warning_bcc_info|raw }} - - - - {{ lang.edit.target_address|raw }}: - - {{ quota_notification_bcc.bcc_rcpts|join("\n") }} - - - - - - {{ lang.edit.active }} - - - - - - {{ lang.edit.save }} - - - - - - - -{% else %} - {{ parent() }} -{% endif %} -{% endblock %} diff --git a/data/web/templates/edit/domain-templates.twig b/data/web/templates/edit/domain-templates.twig new file mode 100644 index 000000000..5a0cbb695 --- /dev/null +++ b/data/web/templates/edit/domain-templates.twig @@ -0,0 +1,136 @@ +{% extends 'edit.twig' %} + +{% block inner_content %} +{% if result %} + + + + + + + + + + {% if mailcow_cc_role == 'admin' %} + + {{ lang.mailbox.template }} + + + + + + + + + + {{ lang.add.tags }} + + + + + + + + + + {{ lang.edit.max_aliases }} + + + + + + {{ lang.edit.max_mailboxes }} + + + + + + {{ lang.edit.mailbox_quota_def }} + + + + + + {{ lang.edit.max_quota }} + + + + + + {{ lang.edit.domain_quota }} + + + + + + + + {{ lang.edit.gal }} + {{ lang.edit.gal_info|raw }} + + + + + + + {{ lang.edit.active }} + + + + + + {{ lang.edit.ratelimit }} + + + + {{ lang.ratelimit.second }} + {{ lang.ratelimit.minute }} + {{ lang.ratelimit.hour }} + {{ lang.ratelimit.day }} + + + + {% endif %} + + + {{ lang.admin.dkim_domains_selector }} + + + + + + {{ lang.admin.dkim_key_length }} + + + 1024 + 2048 + + + + + + {{ lang.edit.backup_mx_options }} + + + {{ lang.edit.relay_domain }} + + {{ lang.edit.relay_all }} + {{ lang.edit.relay_all_info|raw }} + {{ lang.edit.relay_unknown_only }} + + {{ lang.edit.relay_transport_info|raw }} + + + + + + + {{ lang.admin.save }} + + + + +{% else %} + {{ parent() }} +{% endif %} +{% endblock %} diff --git a/data/web/templates/edit/mailbox-defaults.twig b/data/web/templates/edit/mailbox-defaults.twig deleted file mode 100644 index 9487c8565..000000000 --- a/data/web/templates/edit/mailbox-defaults.twig +++ /dev/null @@ -1,195 +0,0 @@ -{% extends 'edit.twig' %} - -{% block inner_content %} -{% if result %} - - {{ lang.edit.mailbox }} - {{ lang.edit.acl }} - {{ lang.edit.ratelimit }} - - - - - - - - - - - - {{ lang.edit.quota_mb }} - - - - 0 = ∞ - - - - {{ lang.user.quarantine_notification }} - - - {{ lang.user.never }} - {{ lang.user.hourly }} - {{ lang.user.daily }} - {{ lang.user.weekly }} - - {{ lang.user.quarantine_notification_info }} - - - - {{ lang.user.quarantine_category }} - - - {{ lang.user.q_reject }} - {{ lang.user.q_add_header }} - {{ lang.user.q_all }} - - {{ lang.user.quarantine_category_info }} - - - - {{ lang.user.tls_policy }} - - - {{ lang.user.tls_enforce_in }} - {{ lang.user.tls_enforce_out }} - - - - - {{ lang.edit.allowed_protocols }} - - - IMAP - POP3 - SMTP - Sieve - - - - - {{ lang.edit.allow_from_smtp }} - - - {{ lang.edit.allow_from_smtp_info }} - - - - - - - {{ lang.edit.active }} - {{ lang.edit.disable_login }} - {{ lang.edit.inactive }} - - - - - - - {{ lang.edit.force_pw_update }} - {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }} - - - - {% if not skip_sogo %} - - - - {{ lang.edit.sogo_access }} - {{ lang.edit.sogo_access_info }} - - - - {% endif %} - - - {{ lang.edit.save }} - - - - - - - - - ACL - - - - {% for acl, val in user_acls %} - {{ lang.acl[acl] }} - {% endfor %} - - {{ lang.edit.save }} - - - - - - - - - {{ lang.acl.ratelimit }} - - - - - {% include 'mailbox/rl-frame.twig' %} - - {{ lang.edit.save }} - {{ lang.edit.mbox_rl_info }} - - - - - -{% else %} - {{ parent() }} -{% endif %} -{% endblock %} diff --git a/data/web/templates/edit/mailbox-templates.twig b/data/web/templates/edit/mailbox-templates.twig new file mode 100644 index 000000000..fea99bdd2 --- /dev/null +++ b/data/web/templates/edit/mailbox-templates.twig @@ -0,0 +1,169 @@ +{% extends 'edit.twig' %} + +{% block inner_content %} +{% if result %} + + + + + + + + + + + {{ lang.mailbox.template }} + + + + + + + + {{ lang.add.tags }} + + + + + + + + + + {{ lang.edit.quota_mb }} + + + 0 = ∞ + + + + {{ lang.user.quarantine_notification }} + + + + {{ lang.user.never }} + + + {{ lang.user.hourly }} + + + {{ lang.user.daily }} + + + {{ lang.user.weekly }} + + {{ lang.user.quarantine_notification_info }} + + + + {{ lang.user.quarantine_category }} + + + + {{ lang.user.q_reject }} + + + {{ lang.user.q_add_header }} + + + {{ lang.user.q_all }} + + {{ lang.user.quarantine_category_info }} + + + + {{ lang.user.tls_policy }} + + + + {{ lang.user.tls_enforce_in }} + + + {{ lang.user.tls_enforce_out }} + + + + + {{ lang.edit.allowed_protocols }} + + + IMAP + POP3 + SMTP + Sieve + + + + + ACL + + + {{ lang.acl["spam_alias"] }} + {{ lang.acl["tls_policy"] }} + {{ lang.acl["spam_score"] }} + {{ lang.acl["spam_policy"] }} + {{ lang.acl["delimiter_action"] }} + {{ lang.acl["syncjobs"] }} + {{ lang.acl["eas_reset"] }} + {{ lang.acl["sogo_profile_reset"] }} + {{ lang.acl["pushover"] }} + {{ lang.acl["quarantine"] }} + {{ lang.acl["quarantine_attachments"] }} + {{ lang.acl["quarantine_notification"] }} + {{ lang.acl["quarantine_category"] }} + {{ lang.acl["app_passwds"] }} + + + + + {{ lang.acl.ratelimit }} + + + + {{ lang.ratelimit.second }} + {{ lang.ratelimit.minute }} + {{ lang.ratelimit.hour }} + {{ lang.ratelimit.day }} + + {{ lang.edit.mbox_rl_info }} + + + + + + + {{ lang.edit.active }} + {{ lang.edit.disable_login }} + {{ lang.edit.inactive }} + + + + + + + {{ lang.edit.force_pw_update }} + {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }} + + + + {% if not skip_sogo %} + + + + {{ lang.edit.sogo_access }} + {{ lang.edit.sogo_access_info }} + + + + {% endif %} + + + {{ lang.edit.save }} + + + + +{% else %} + {{ parent() }} +{% endif %} +{% endblock %} diff --git a/data/web/templates/mailbox.twig b/data/web/templates/mailbox.twig index 26215ef27..fa89b001b 100644 --- a/data/web/templates/mailbox.twig +++ b/data/web/templates/mailbox.twig @@ -6,8 +6,8 @@ {{ lang.mailbox.domains }} - {{ lang.mailbox.domains }} - {{ lang.mailbox.mailbox_defaults }} + {{ lang.mailbox.domains }} + {{ lang.mailbox.templates }} {# {{ lang.mailbox.domains }} #} @@ -16,7 +16,7 @@ {{ lang.mailbox.mailboxes }} {{ lang.mailbox.mailboxes }} - {{ lang.mailbox.mailbox_defaults }} + {{ lang.mailbox.templates }} {{ lang.mailbox.resources }} @@ -38,7 +38,9 @@ {% include 'mailbox/tab-domains.twig' %} {# {% include 'mailbox/tab-mailbox-defaults.twig' %} #} + {% include 'mailbox/tab-templates-domains.twig' %} {% include 'mailbox/tab-mailboxes.twig' %} + {% include 'mailbox/tab-templates-mbox.twig' %} {% include 'mailbox/tab-resources.twig' %} {% include 'mailbox/tab-domain-aliases.twig' %} {% include 'mailbox/tab-mbox-aliases.twig' %} @@ -56,6 +58,7 @@
{{ lang.user.spamfilter_wl_desc|raw }}
{{ lang.user.spamfilter_bl_desc|raw }}
{{ lang.edit.quota_warning_bcc_info|raw }}
{{ lang.edit.relay_all_info|raw }}
{{ lang.edit.relay_transport_info|raw }}
{{ lang.user.quarantine_notification_info }}
{{ lang.user.quarantine_category_info }}
ACL
{{ lang.acl.ratelimit }}
{{ lang.edit.mbox_rl_info }}