diff --git a/data/Dockerfiles/dockerapi/dockerapi.py b/data/Dockerfiles/dockerapi/dockerapi.py index 6d3b1012..63436b62 100644 --- a/data/Dockerfiles/dockerapi/dockerapi.py +++ b/data/Dockerfiles/dockerapi/dockerapi.py @@ -9,6 +9,7 @@ import os import json import asyncio import redis +import platform from datetime import datetime import logging from logging.config import dictConfig @@ -381,11 +382,14 @@ class DockerUtils: for container in self.docker_client.containers.list(filters={"id": container_id}): sane_name = re.sub(r'\W+', '', request_json['maildir']) vmail_name = request_json['maildir'].replace("'", "'\\''") - index_name = request_json['maildir'].split("/") - index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''") cmd_vmail = "if [[ -d '/var/vmail/" + vmail_name + "' ]]; then /bin/mv '/var/vmail/" + vmail_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi" - cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi" - cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index] + index_name = request_json['maildir'].split("/") + if len(index_name) > 1: + index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''") + cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi" + cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index] + else: + cmd = ["/bin/bash", "-c", cmd_vmail] maildir_cleanup = container.exec_run(cmd, user='vmail') return exec_run_handler('generic', maildir_cleanup) # api call: container_post - post_action: exec - cmd: rspamd - task: worker_password @@ -482,7 +486,8 @@ async def get_host_stats(wait=5): "swap": psutil.swap_memory() }, "uptime": time.time() - psutil.boot_time(), - "system_time": system_time.strftime("%d.%m.%Y %H:%M:%S") + "system_time": system_time.strftime("%d.%m.%Y %H:%M:%S"), + "architecture": platform.machine() } redis_client.set('host_stats', json.dumps(host_stats), ex=10) diff --git a/data/web/css/build/011-datatables.css b/data/web/css/build/011-datatables.css index d03514ff..d262f07c 100644 --- a/data/web/css/build/011-datatables.css +++ b/data/web/css/build/011-datatables.css @@ -342,6 +342,10 @@ div.dataTables_wrapper div.dt-row { position: relative; } +div.dataTables_wrapper span.sorting-value { + display: none; +} + div.dataTables_scrollHead table.dataTable { margin-bottom: 0 !important; } diff --git a/data/web/css/site/mailbox.css b/data/web/css/site/mailbox.css index f62ead31..e896abca 100644 --- a/data/web/css/site/mailbox.css +++ b/data/web/css/site/mailbox.css @@ -66,4 +66,6 @@ table tbody tr td input[type="checkbox"] { padding: .2em .4em .3em !important; background-color: #ececec!important; } - +.badge.bg-info .bi { + font-size: inherit; +} diff --git a/data/web/css/themes/mailcow-darkmode.css b/data/web/css/themes/mailcow-darkmode.css index 6e0db0e9..abaa7499 100644 --- a/data/web/css/themes/mailcow-darkmode.css +++ b/data/web/css/themes/mailcow-darkmode.css @@ -20,6 +20,11 @@ legend { background-color: #7a7a7a !important; border-color: #5c5c5c !important; } +.btn-dark { + color: #000 !important;; + background-color: #f6f6f6 !important;; + border-color: #ddd !important;; +} .btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle { border-color: #7a7a7a !important; } @@ -299,22 +304,22 @@ a:hover { } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { background-color: #7a7a7a !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before { background-color: #7a7a7a !important; border: 1.5px solid #5c5c5c !important; color: #fff !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before { background-color: #949494; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { background-color: #444444; } @@ -327,7 +332,7 @@ table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { } .btn.btn-outline-secondary { color: #fff !important; - border-color: #7a7a7a !important; + border-color: #7a7a7a !important; } .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { background-color: #9b9b9b !important; diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index de1855fa..4dc2418c 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -1015,20 +1015,58 @@ function formatBytes($size, $precision = 2) { } return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; } -function update_sogo_static_view() { +function update_sogo_static_view($mailbox = null) { if (getenv('SKIP_SOGO') == "y") { return true; } global $pdo; global $lang; - $stmt = $pdo->query("SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_NAME = 'sogo_view'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results != 0) { - $stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`) - SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view"); - $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); + + $mailbox_exists = false; + if ($mailbox !== null) { + // Check if the mailbox exists + $stmt = $pdo->prepare("SELECT username FROM mailbox WHERE username = :mailbox AND active = '1'"); + $stmt->execute(array(':mailbox' => $mailbox)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if ($row){ + $mailbox_exists = true; + } } + + $query = "REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`) + SELECT + mailbox.username, + mailbox.domain, + mailbox.username, + IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) = '0', + IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.sogo_access')) = 1, password, '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), + '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), + mailbox.name, + mailbox.username, + IFNULL(GROUP_CONCAT(ga.aliases ORDER BY ga.aliases SEPARATOR ' '), ''), + IFNULL(gda.ad_alias, ''), + IFNULL(external_acl.send_as_acl, ''), + mailbox.kind, + mailbox.multiple_bookings + FROM + mailbox + LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)') + LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username + LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username + WHERE + mailbox.active = '1'"; + + if ($mailbox_exists) { + $query .= " AND mailbox.username = :mailbox"; + $stmt = $pdo->prepare($query); + $stmt->execute(array(':mailbox' => $mailbox)); + } else { + $query .= " GROUP BY mailbox.username"; + $stmt = $pdo->query($query); + } + + $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); + flush_memcached(); } function edit_user_account($_data) { diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 4529ee7b..4e036b99 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1264,11 +1264,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { )); } + update_sogo_static_view($username); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_added', htmlspecialchars($username)) ); + return true; break; case 'resource': $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46); @@ -3130,7 +3132,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_modified', $username) ); + + update_sogo_static_view($username); } + return true; break; case 'mailbox_templates': if ($_SESSION['mailcow_cc_role'] != "admin") { @@ -5053,12 +5058,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); continue; } + + update_sogo_static_view($username); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), 'msg' => array('mailbox_removed', htmlspecialchars($username)) ); } + return true; break; case 'mailbox_templates': if ($_SESSION['mailcow_cc_role'] != "admin") { @@ -5264,7 +5272,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } break; } - if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource')) && getenv('SKIP_SOGO') != "y") { + if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") { update_sogo_static_view(); } } diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js index 23ef1d25..07dfed8c 100644 --- a/data/web/js/site/admin.js +++ b/data/web/js/site/admin.js @@ -117,8 +117,8 @@ jQuery(function($){ data: 'tfa_active', defaultContent: '', render: function (data, type) { - if(data == 1) return ''; - else return ''; + if(data == 1) return '1'; + else return '0'; } }, { @@ -126,8 +126,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return ''; - else return ''; + if(data == 1) return '1'; + else return '0'; } }, { @@ -260,8 +260,8 @@ jQuery(function($){ data: 'tfa_active', defaultContent: '', render: function (data, type) { - if(data == 1) return ''; - else return ''; + if(data == 1) return '1'; + else return '0'; } }, { @@ -269,8 +269,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return ''; - else return ''; + if(data == 1) return '1'; + else return '0'; } }, { @@ -337,7 +337,7 @@ jQuery(function($){ data: 'keep_spam', defaultContent: '', render: function(data, type){ - return 'yes'==data?'':'no'==data&&''; + return 'yes'==data?'yes':'no'==data&&'no'; } }, { @@ -414,8 +414,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return ''; - else return ''; + if(data == 1) return '1'; + else return '0'; } }, { @@ -492,8 +492,8 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - if(data == 1) return ''; - else return ''; + if(data == 1) return '1'; + else return '0'; } }, { diff --git a/data/web/js/site/debug.js b/data/web/js/site/debug.js index 55b6660b..78a4ccaa 100644 --- a/data/web/js/site/debug.js +++ b/data/web/js/site/debug.js @@ -43,7 +43,7 @@ $(document).ready(function() { if (mailcow_info.branch === "master"){ check_update(mailcow_info.version_tag, mailcow_info.project_url); } - $("#maiclow_version").click(function(){ + $("#mailcow_version").click(function(){ if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin" || mailcow_info.branch !== "master") return; @@ -1302,6 +1302,12 @@ function update_stats(timeout=5){ $("#host_cpu_usage").text(parseInt(data.cpu.usage).toString() + "%"); $("#host_memory_total").text((data.memory.total / (1024 ** 3)).toFixed(2).toString() + "GB"); $("#host_memory_usage").text(parseInt(data.memory.usage).toString() + "%"); + if (data.architecture == "aarch64"){ + $("#host_architecture").html('' + data.architecture + ' ⚠️'); + } + else { + $("#host_architecture").html(data.architecture); + } // update cpu and mem chart var cpu_chart = Chart.getChart("host_cpu_chart"); diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index f4039268..d7fca848 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -607,7 +607,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 6, render: function (data, type) { - return 1==data?'':(0==data?'':2==data&&'—'); + return 1==data?'1':(0==data?'0':2==data&&'—'); } }, { @@ -754,7 +754,7 @@ jQuery(function($){ data: 'attributes.gal', defaultContent: '', render: function (data, type) { - return 1==data?'':''; + return 1==data?'1':'0'; } }, { @@ -762,7 +762,7 @@ jQuery(function($){ data: 'attributes.backupmx', defaultContent: '', render: function (data, type) { - return 1==data?'':''; + return 1==data?'1':'0'; } }, { @@ -770,7 +770,7 @@ jQuery(function($){ data: 'attributes.relay_all_recipients', defaultContent: '', render: function (data, type) { - return 1==data?'':''; + return 1==data?'1':'0'; } }, { @@ -778,7 +778,7 @@ jQuery(function($){ data: 'attributes.relay_unknown_only', defaultContent: '', render: function (data, type) { - return 1==data?'':''; + return 1==data?'1':'0'; } }, { @@ -787,7 +787,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 4, render: function (data, type) { - return 1==data?'':''; + return 1==data?'1':'0'; } }, { @@ -1093,7 +1093,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 4, render: function (data, type) { - return 1==data?'':(0==data?'':2==data&&'—'); + return 1==data?'1':(0==data?'0':2==data&&'—'); } }, { @@ -1164,13 +1164,13 @@ jQuery(function($){ 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 = ''; + item.attributes.tls_enforce_in = '' + (item.attributes.tls_enforce_in == 1 ? '1' : '0') + ''; + item.attributes.tls_enforce_out = '' + (item.attributes.tls_enforce_out == 1 ? '1' : '0') + ''; + item.attributes.pop3_access = '' + (item.attributes.pop3_access == 1 ? '1' : '0') + ''; + item.attributes.imap_access = '' + (item.attributes.imap_access == 1 ? '1' : '0') + ''; + item.attributes.smtp_access = '' + (item.attributes.smtp_access == 1 ? '1' : '0') + ''; + item.attributes.sieve_access = '' + (item.attributes.sieve_access == 1 ? '1' : '0') + ''; + item.attributes.sogo_access = '' + (item.attributes.sogo_access == 1 ? '1' : '0') + ''; if (item.attributes.quarantine_notification === 'never') { item.attributes.quarantine_notification = lang.never; } else if (item.attributes.quarantine_notification === 'hourly') { @@ -1188,7 +1188,6 @@ jQuery(function($){ item.attributes.quarantine_category = lang.q_all; } - if (item.template.toLowerCase() == "default"){ item.action = '
' + ' ' + lang.edit + '' + @@ -1329,7 +1328,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 4, render: function (data, type) { - return 1==data?'':(0==data?'':2==data&&'—'); + return 1==data?'1':(0==data?'0':2==data&&'—'); } }, { @@ -1440,7 +1439,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'':(0==data?'':2==data&&'—'); + return 1==data?'1':(0==data?'0':2==data&&'—'); } }, { @@ -1578,7 +1577,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'':(0==data?'':2==data&&'—'); + return 1==data?'1':(0==data?'0':2==data&&'—'); } }, { @@ -1675,7 +1674,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'':0==data&&''; + return 1==data?'1':0==data&&'0'; } }, { @@ -1782,7 +1781,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'':0==data&&''; + return 1==data?'1':0==data&&'0'; } }, { @@ -1917,7 +1916,7 @@ jQuery(function($){ data: 'sogo_visible', defaultContent: '', render: function(data, type){ - return 1==data?'':0==data&&''; + return 1==data?'1':0==data&&'0'; } }, { @@ -1936,7 +1935,7 @@ jQuery(function($){ defaultContent: '', responsivePriority: 6, render: function (data, type) { - return 1==data?'':0==data&&''; + return 1==data?'1':0==data&&'0'; } }, { @@ -1952,6 +1951,10 @@ jQuery(function($){ table.on('responsive-resize', function (e, datatable, columns){ hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table'); }); + + table.on( 'draw', function (){ + $('#alias_table [data-bs-toggle="tooltip"]').tooltip(); + }); } function draw_aliasdomain_table() { // just recalc width if instance already exists @@ -2031,7 +2034,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'':0==data&&''; + return 1==data?'1':0==data&&'0'; } }, { @@ -2167,7 +2170,7 @@ jQuery(function($){ data: 'active', defaultContent: '', render: function (data, type) { - return 1==data?'':0==data&&''; + return 1==data?'1':0==data&&'0'; } }, { diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 5e119fbd..d4f62495 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -105,7 +105,8 @@ "timeout2": "Časový limit pro připojení k lokálnímu serveru", "username": "Uživatelské jméno", "validate": "Ověřit", - "validation_success": "Úspěšně ověřeno" + "validation_success": "Úspěšně ověřeno", + "tags": "Štítky" }, "admin": { "access": "Přístupy", @@ -333,7 +334,11 @@ "username": "Uživatelské jméno", "validate_license_now": "Ověřit GUID na licenčním serveru", "verify": "Ověřit", - "yes": "✓" + "yes": "✓", + "f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem", + "f2b_max_ban_time": "Maximální délka banu (s)", + "ip_check": "Kontrola IP", + "ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v
System > Nastavení > Options > Přizpůsobení" }, "danger": { "access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři", @@ -536,7 +541,7 @@ "inactive": "Neaktivní", "kind": "Druh", "last_modified": "Naposledy změněn", - "lookup_mx": "Cíl je regulární výraz který se shoduje s MX záznamem (.*google\\.com směřuje veškerou poštu na MX které jsou cílem pro google.com přes tento skok)", + "lookup_mx": "Cíl je regulární výraz který se shoduje s MX záznamem (.*\\.google\\.com směřuje veškerou poštu na MX které jsou cílem pro google.com přes tento skok)", "mailbox": "Úprava mailové schránky", "mailbox_quota_def": "Výchozí kvóta schránky", "mailbox_relayhost_info": "Aplikované jen na uživatelskou schránku a přímé aliasy, přepisuje předávající server domény.", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 4bd4b3fa..6b280bbb 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -216,7 +216,7 @@ "loading": "Bitte warten...", "login_time": "Zeit", "logo_info": "Die hochgeladene Grafik wird für die Navigationsleiste auf eine Höhe von 40px skaliert. Für die Darstellung auf der Login-Maske beträgt die skalierte Breite maximal 250px. Eine frei skalierbare Grafik (etwa SVG) wird empfohlen.", - "lookup_mx": "Ziel mit MX vergleichen (Regex, etwa .*google\\.com, um alle Ziele mit MX *google.com zu routen)", + "lookup_mx": "Ziel mit MX vergleichen (Regex, etwa .*\\.google\\.com, um alle Ziele mit MX *google.com zu routen)", "main_name": "\"mailcow UI\" Name", "merged_vars_hint": "Ausgegraute Reihen wurden aus der Datei vars.(local.)inc.php gelesen und können hier nicht verändert werden.", "message": "Nachricht", @@ -498,6 +498,7 @@ } }, "debug": { + "architecture": "Architektur", "chart_this_server": "Chart (dieser Server)", "containers_info": "Container-Information", "container_running": "Läuft", @@ -534,7 +535,8 @@ "update_available": "Es ist ein Update verfügbar", "no_update_available": "Das System ist auf aktuellem Stand", "update_failed": "Es konnte nicht nach einem Update gesucht werden", - "username": "Benutzername" + "username": "Benutzername", + "wip": "Aktuell noch in Arbeit" }, "diagnostics": { "cname_from_a": "Wert abgeleitet von A/AAAA-Eintrag. Wird unterstützt, sofern der Eintrag auf die korrekte Ressource zeigt.", @@ -593,7 +595,7 @@ "inactive": "Inaktiv", "kind": "Art", "last_modified": "Zuletzt geändert", - "lookup_mx": "Ziel mit MX vergleichen (Regex, etwa .*google\\.com, um alle Ziele mit MX *google.com zu routen)", + "lookup_mx": "Ziel mit MX vergleichen (Regex, etwa .*\\.google\\.com, um alle Ziele mit MX *google.com zu routen)", "mailbox": "Mailbox bearbeiten", "mailbox_quota_def": "Standard-Quota einer Mailbox", "mailbox_relayhost_info": "Wird auf eine Mailbox und direkte Alias-Adressen angewendet. Überschreibt die Einstellung einer Domain.", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index df83987c..e53fe896 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -218,7 +218,7 @@ "loading": "Please wait...", "login_time": "Login time", "logo_info": "Your image will be scaled to a height of 40px for the top navigation bar and a max. width of 250px for the start page. A scalable graphic is highly recommended.", - "lookup_mx": "Destination is a regular expression to match against MX name (.*google\\.com to route all mail targeted to a MX ending in google.com over this hop)", + "lookup_mx": "Destination is a regular expression to match against MX name (.*\\.google\\.com to route all mail targeted to a MX ending in google.com over this hop)", "main_name": "\"mailcow UI\" name", "merged_vars_hint": "Greyed out rows were merged from vars.(local.)inc.php and cannot be modified.", "message": "Message", @@ -498,6 +498,7 @@ } }, "debug": { + "architecture": "Architecture", "chart_this_server": "Chart (this server)", "containers_info": "Container information", "container_running": "Running", @@ -534,7 +535,8 @@ "update_available": "There is an update available", "no_update_available": "The System is on the latest version", "update_failed": "Could not check for an Update", - "username": "Username" + "username": "Username", + "wip": "Currently Work in Progress" }, "diagnostics": { "cname_from_a": "Value derived from A/AAAA record. This is supported as long as the record points to the correct resource.", @@ -593,7 +595,7 @@ "inactive": "Inactive", "kind": "Kind", "last_modified": "Last modified", - "lookup_mx": "Destination is a regular expression to match against MX name (.*google\\.com to route all mail targeted to a MX ending in google.com over this hop)", + "lookup_mx": "Destination is a regular expression to match against MX name (.*\\.google\\.com to route all mail targeted to a MX ending in google.com over this hop)", "mailbox": "Edit mailbox", "mailbox_quota_def": "Default mailbox quota", "mailbox_relayhost_info": "Applied to the mailbox and direct aliases only, does override a domain relayhost.", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index d64f62f7..0bc0ba02 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -588,7 +588,7 @@ "unchanged_if_empty": "Si non modifié, laisser en blanc", "username": "Nom d'utilisateur", "validate_save": "Valider et sauver", - "lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (.*google\\.com pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut)", + "lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (.*\\.google\\.com pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut)", "mailbox_relayhost_info": "S'applique uniquement à la boîte aux lettres et aux alias directs, remplace le relayhost du domaine." }, "footer": { diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index 4d21547c..0d5b3f25 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -213,7 +213,7 @@ "loading": "Caricamento in corso...", "login_time": "Ora di accesso", "logo_info": "La tua immagine verrà ridimensionata a 40px di altezza, quando verrà usata nella barra di navigazione in alto, ed ad una larghezza massima di 250px nella schermata iniziale. È altamente consigliato l'utilizzo di un'immagine modulabile.", - "lookup_mx": "Destination is a regular expression to match against MX name (.*google\\.com to route all mail targeted to a MX ending in google.com over this hop)", + "lookup_mx": "Destination is a regular expression to match against MX name (.*\\.google\\.com to route all mail targeted to a MX ending in google.com over this hop)", "main_name": "Nome \"mailcow UI\"", "merged_vars_hint": "Greyed out rows were merged from vars.(local.)inc.php and cannot be modified.", "message": "Messaggio", @@ -554,7 +554,7 @@ "hostname": "Hostname", "inactive": "Inattivo", "kind": "Genere", - "lookup_mx": "Destination is a regular expression to match against MX name (.*google\\.com to route all mail targeted to a MX ending in google.com over this hop)", + "lookup_mx": "Destination is a regular expression to match against MX name (.*\\.google\\.com to route all mail targeted to a MX ending in google.com over this hop)", "mailbox": "Modifica casella di posta", "mailbox_quota_def": "Default mailbox quota", "mailbox_relayhost_info": "Applied to the mailbox and direct aliases only, does override a domain relayhost.", diff --git a/data/web/lang/lang.ro-ro.json b/data/web/lang/lang.ro-ro.json index 8e6e1d45..e6315db0 100644 --- a/data/web/lang/lang.ro-ro.json +++ b/data/web/lang/lang.ro-ro.json @@ -539,7 +539,7 @@ "inactive": "Inactiv", "kind": "Fel", "last_modified": "Ultima modificare", - "lookup_mx": "Destinația este o expresie regulată care potrivită cu numele MX (.*google\\.com pentru a direcționa toate e-mailurile vizate către un MX care se termină în google.com peste acest hop)", + "lookup_mx": "Destinația este o expresie regulată care potrivită cu numele MX (.*\\.google\\.com pentru a direcționa toate e-mailurile vizate către un MX care se termină în google.com peste acest hop)", "mailbox": "Editează căsuța poștală", "mailbox_quota_def": "Cota implicită a căsuței poștale", "mailbox_relayhost_info": "Aplicat numai căsuței poștale și aliasurilor directe, suprascrie un transport dependent de domeniu.", diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index 65dd4bae..bad64184 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -336,7 +336,9 @@ "validate_license_now": "Получить лицензию на основе GUID с сервера лицензий", "verify": "Проверить", "yes": "✓", - "queue_unban": "разблокировать" + "queue_unban": "разблокировать", + "f2b_ban_time_increment": "Время бана увеличивается с каждым баном", + "f2b_max_ban_time": "Максимальное время блокировки" }, "danger": { "access_denied": "Доступ запрещён, или указаны неверные данные", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 2b93650f..29b36c44 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -213,7 +213,7 @@ "loading": "Čakajte prosím ...", "login_time": "Čas prihlásenia", "logo_info": "Váš obrázok bude upravený na výšku 40px pre vrchný navigačný riadok a na maximálnu šírku 250px pre úvodnú stránku. Odporúča sa škálovateľná grafika.", - "lookup_mx": "Cieľ je regulárny výraz ktorý sa porovnáva s MX záznamom (.*google\\.com smeruje všetku poštu určenú pre MX ktoré sú cieľom pre google.com cez tento skok)", + "lookup_mx": "Cieľ je regulárny výraz ktorý sa porovnáva s MX záznamom (.*\\.google\\.com smeruje všetku poštu určenú pre MX ktoré sú cieľom pre google.com cez tento skok)", "main_name": "\"mailcow UI\" názov", "merged_vars_hint": "Sivé riadky boli načítané z vars.(local.)inc.php a nemôžu byť modifikované cez UI.", "message": "Správa", @@ -539,7 +539,7 @@ "inactive": "Neaktívny", "kind": "Druh", "last_modified": "Naposledy upravené", - "lookup_mx": "Cieľ je regulárny výraz ktorý sa zhoduje s MX záznamom (.*google\\.com smeruje všetku poštu na MX ktoré sú cieľom pre google.com cez tento skok)", + "lookup_mx": "Cieľ je regulárny výraz ktorý sa zhoduje s MX záznamom (.*\\.google\\.com smeruje všetku poštu na MX ktoré sú cieľom pre google.com cez tento skok)", "mailbox": "Upraviť mailovú schránku", "mailbox_quota_def": "Predvolená veľkosť mailovej schránky", "mailbox_relayhost_info": "Aplikované len na používateľské schránky a priame aliasy, prepisuje doménového preposielateľa.", diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json index e57ea2a7..90888efd 100644 --- a/data/web/lang/lang.zh-cn.json +++ b/data/web/lang/lang.zh-cn.json @@ -213,7 +213,7 @@ "loading": "请等待...", "login_time": "登录时间", "logo_info": "你的图片将会在顶部导航栏被缩放为 40px 高,在起始页被缩放为最大 250px 高。强烈推荐使用能较好适应缩放的图片。", - "lookup_mx": "应当为一个正则表达式,用于匹配 MX 记录 (例如 .*google\\.com 将转发所有拥有以 google.com 结尾的 MX 记录的邮件)", + "lookup_mx": "应当为一个正则表达式,用于匹配 MX 记录 (例如 .*\\.google\\.com 将转发所有拥有以 google.com 结尾的 MX 记录的邮件)", "main_name": "Mailcow UI 的名称", "merged_vars_hint": "灰色行来自 vars.(local.)inc.php 文件并且无法修改。", "message": "消息", @@ -544,7 +544,7 @@ "hostname": "主机名", "inactive": "禁用", "kind": "类型", - "lookup_mx": "应当为一个正则表达式,用于匹配 MX 记录 (例如 .*google\\.com 将转发所有拥有以 google.com 结尾的 MX 记录的邮件)", + "lookup_mx": "应当为一个正则表达式,用于匹配 MX 记录 (例如 .*\\.google\\.com 将转发所有拥有以 google.com 结尾的 MX 记录的邮件)", "mailbox": "编辑邮箱", "mailbox_quota_def": "邮箱默认配额", "mailbox_relayhost_info": "只适用于邮箱和邮箱别名,不会覆盖域名的中继主机。", diff --git a/data/web/lang/lang.zh-tw.json b/data/web/lang/lang.zh-tw.json index 916188db..ff9ed334 100644 --- a/data/web/lang/lang.zh-tw.json +++ b/data/web/lang/lang.zh-tw.json @@ -213,7 +213,7 @@ "loading": "請稍等...", "login_time": "登入時間", "logo_info": "你的起始頁面圖片會在頂部導覽列的限制下被縮放為 40px 高,以及最大 250px 高度。強烈推薦使用能較好縮放的圖片。", - "lookup_mx": "目的地是可以用來匹配 MX 紀錄的正規表達式 (.*google\\.com 會將所有 MX 結尾於 google.com 的郵件轉發到此主機。)", + "lookup_mx": "目的地是可以用來匹配 MX 紀錄的正規表達式 (.*\\.google\\.com 會將所有 MX 結尾於 google.com 的郵件轉發到此主機。)", "main_name": "\"mailcow UI\" 名稱", "merged_vars_hint": "灰色列來自 vars.(local.)inc.php 並且不能修改。", "message": "訊息", @@ -540,7 +540,7 @@ "inactive": "停用", "kind": "種類", "last_modified": "上次修改時間", - "lookup_mx": "目的地是可以用來匹配 MX 紀錄的正規表達式 (.*google\\.com 會將所有 MX 結尾於 google.com 的郵件轉發到此主機。)", + "lookup_mx": "目的地是可以用來匹配 MX 紀錄的正規表達式 (.*\\.google\\.com 會將所有 MX 結尾於 google.com 的郵件轉發到此主機。)", "mailbox": "編輯信箱", "mailbox_quota_def": "預設信箱容量配額", "mailbox_relayhost_info": "只會套用於信箱和直接別名,不會覆寫域名中繼主機。", diff --git a/data/web/sogo-auth.php b/data/web/sogo-auth.php index 7ca5e4d9..40fff585 100644 --- a/data/web/sogo-auth.php +++ b/data/web/sogo-auth.php @@ -60,7 +60,7 @@ elseif (isset($_GET['login'])) { ':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']) )); // redirect to sogo (sogo will get the correct credentials via nginx auth_request - header("Location: /SOGo/so/${login}"); + header("Location: /SOGo/so/{$login}"); exit; } } diff --git a/data/web/templates/debug.twig b/data/web/templates/debug.twig index d24d7ed6..adc19b26 100644 --- a/data/web/templates/debug.twig +++ b/data/web/templates/debug.twig @@ -49,6 +49,12 @@

{{ hostname }}

+ + {{ lang.debug.architecture }} +
+

-

+
+ IPs @@ -70,7 +76,7 @@ Version
-

{{ mailcow_info.version_tag }}

+

{{ mailcow_info.version_tag }}

diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index 36fe053b..f8cde7da 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -109,25 +109,25 @@
- - - - - - -
- {{ lang.mailbox.toggle_all }} + {{ lang.mailbox.toggle_all }} {{ lang.mailbox.quick_actions }}