From 1787c53d98ad2251bf2a945ac81358a61ee36664 Mon Sep 17 00:00:00 2001 From: Habetdin <15926758+Habetdin@users.noreply.github.com> Date: Tue, 30 Jan 2024 14:09:37 +0300 Subject: [PATCH 01/10] [Netfilter] respect ban time limits --- data/Dockerfiles/netfilter/main.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py index 62e0dda75a..c3ca379cae 100644 --- a/data/Dockerfiles/netfilter/main.py +++ b/data/Dockerfiles/netfilter/main.py @@ -114,8 +114,6 @@ def ban(address): global lock refreshF2boptions() - BAN_TIME = int(f2boptions['ban_time']) - BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) MAX_ATTEMPTS = int(f2boptions['max_attempts']) RETRY_WINDOW = int(f2boptions['retry_window']) NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4']) @@ -150,7 +148,7 @@ def ban(address): if bans[net]['attempts'] >= MAX_ATTEMPTS: cur_time = int(round(time.time())) - NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] + NET_BAN_TIME = calcNetBanTime(bans[net]['ban_counter']) logger.logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 )) if type(ip) is ipaddress.IPv4Address and int(f2boptions['manage_external']) != 1: with lock: @@ -277,12 +275,11 @@ def snat6(snat_target): tables.snat6(snat_target, os.getenv('IPV6_NETWORK', 'fd4d:6169:6c63:6f77::/64')) def autopurge(): + global f2boptions + while not quit_now: time.sleep(10) refreshF2boptions() - BAN_TIME = int(f2boptions['ban_time']) - MAX_BAN_TIME = int(f2boptions['max_ban_time']) - BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) MAX_ATTEMPTS = int(f2boptions['max_attempts']) QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN') if QUEUE_UNBAN: @@ -290,9 +287,9 @@ def autopurge(): unban(str(net)) for net in bans.copy(): if bans[net]['attempts'] >= MAX_ATTEMPTS: - NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] + NET_BAN_TIME = calcNetBanTime(bans[net]['ban_counter']) TIME_SINCE_LAST_ATTEMPT = time.time() - bans[net]['last_attempt'] - if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME or TIME_SINCE_LAST_ATTEMPT > MAX_BAN_TIME: + if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME: unban(net) def mailcowChainOrder(): @@ -306,6 +303,16 @@ def mailcowChainOrder(): if quit_now: return quit_now, exit_code = tables.checkIPv6ChainOrder() +def calcNetBanTime(ban_counter): + global f2boptions + + BAN_TIME = int(f2boptions['ban_time']) + MAX_BAN_TIME = int(f2boptions['max_ban_time']) + BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) + NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** ban_counter + NET_BAN_TIME = max([BAN_TIME, min([NET_BAN_TIME, MAX_BAN_TIME])]) + return NET_BAN_TIME + def isIpNetwork(address): try: ipaddress.ip_network(address, False) From 3cb9c2ece548c8cb8ce7f41a503ec32ea9c46bfc Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 9 Feb 2024 08:05:19 +0100 Subject: [PATCH 02/10] ui: fix wrong docs links ui: fixed broken Links to docs --- data/web/lang/lang.cs-cz.json | 2 +- data/web/lang/lang.da-dk.json | 2 +- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- data/web/lang/lang.fr-fr.json | 2 +- data/web/lang/lang.it-it.json | 2 +- data/web/lang/lang.nl-nl.json | 2 +- data/web/lang/lang.pt-br.json | 2 +- data/web/lang/lang.ro-ro.json | 2 +- data/web/lang/lang.ru-ru.json | 2 +- data/web/lang/lang.si-si.json | 2 +- data/web/lang/lang.sk-sk.json | 2 +- data/web/lang/lang.sv-se.json | 2 +- data/web/lang/lang.uk-ua.json | 2 +- data/web/lang/lang.zh-cn.json | 2 +- data/web/lang/lang.zh-tw.json | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 2d0b1014ef..593f1cdcfd 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -547,7 +547,7 @@ "dns_records": "DNS záznamy", "dns_records_24hours": "Upozornění: Změnám v systému DNS může trvat až 24 hodin, než se zde správně zobrazí jejich aktuální stav. Můžete zde snadno zjistit, jak nastavit DNS záznamy a zda jsou všechny záznamy správně uloženy.", "dns_records_data": "Správný záznam", - "dns_records_docs": "Přečtěte si prosím dokumentaci.", + "dns_records_docs": "Přečtěte si prosím dokumentaci.", "dns_records_name": "Název", "dns_records_status": "Současný stav", "dns_records_type": "Typ", diff --git a/data/web/lang/lang.da-dk.json b/data/web/lang/lang.da-dk.json index 33629bbeb6..95db916eff 100644 --- a/data/web/lang/lang.da-dk.json +++ b/data/web/lang/lang.da-dk.json @@ -459,7 +459,7 @@ "cname_from_a": "Værdi afledt af A / AAAA-post. Dette understøttes, så længe posten peger på den korrekte ressource.", "dns_records": "DNS-poster", "dns_records_24hours": "Bemærk, at ændringer, der foretages i DNS, kan tage op til 24 timer for at få deres aktuelle status korrekt reflekteret på denne side. Det er beregnet som en måde for dig let at se, hvordan du konfigurerer dine DNS-poster og kontrollere, om alle dine poster er korrekt gemt i DNS.", - "dns_records_docs": "Se også dokumentationen.", + "dns_records_docs": "Se også dokumentationen.", "dns_records_data": "Korrekte data", "dns_records_name": "Navn", "dns_records_status": "Nuværende tilstand", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index ddadfac630..73d02bdd05 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -556,7 +556,7 @@ "dns_records": "DNS-Einträge", "dns_records_24hours": "Bitte beachten Sie, dass es bis zu 24 Stunden dauern kann, bis Änderungen an Ihren DNS-Einträgen als aktueller Status auf dieser Seite dargestellt werden. Diese Seite ist nur als Hilfsmittel gedacht, um die korrekten Werte für DNS-Einträge anzuzeigen und zu überprüfen, ob die Daten im DNS hinterlegt sind.", "dns_records_data": "Korrekte Daten", - "dns_records_docs": "Die Online-Dokumentation enthält weitere Informationen zur DNS-Konfiguration.", + "dns_records_docs": "Die Online-Dokumentation enthält weitere Informationen zur DNS-Konfiguration.", "dns_records_name": "Name", "dns_records_status": "Aktueller Status", "dns_records_type": "Typ", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index ec97d0aef4..e413664f55 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -556,7 +556,7 @@ "dns_records": "DNS Records", "dns_records_24hours": "Please note that changes made to DNS may take up to 24 hours to correctly have their current state reflected on this page. It is intended as a way for you to easily see how to configure your DNS records and to check whether all your records are correctly stored in DNS.", "dns_records_data": "Correct Data", - "dns_records_docs": "Please also consult the documentation.", + "dns_records_docs": "Please also consult the documentation.", "dns_records_name": "Name", "dns_records_status": "Current State", "dns_records_type": "Type", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 96e1aef7d9..4b5ab2e500 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -483,7 +483,7 @@ "cname_from_a": "Valeur dérivée de l’enregistrement A/AAAA. Ceci est supporté tant que l’enregistrement indique la bonne ressource.", "dns_records": "Enregistrements DNS", "dns_records_24hours": "Veuillez noter que les modifications apportées au DNS peuvent prendre jusqu’à 24 heures pour que leurs états actuels soient correctement reflétés sur cette page. Il est conçu comme un moyen pour vous de voir facilement comment configurer vos enregistrements DNS et de vérifier si tous vos enregistrements sont correctement stockés dans les DNS.", - "dns_records_docs": "Veuillez également consulter la documentation.", + "dns_records_docs": "Veuillez également consulter la documentation.", "dns_records_data": "Données correcte", "dns_records_name": "Nom", "dns_records_status": "Etat courant", diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index 6783dfed85..158f798644 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -506,7 +506,7 @@ "dns_records": "Record DNS", "dns_records_24hours": "Tieni presente che le modifiche apportate ai record DNS potrebbero richiedere fino a 24 ore per poter essere visualizzate correttamente in questa pagina. Tutto ciò è da intendersi come un modo per voi di vedere come configurare i record DNS e per controllare se tutti i record DNS sono stati inseriti correttamente.", "dns_records_data": "Dati corretti", - "dns_records_docs": "Si prega di consultare anche la documentazione.", + "dns_records_docs": "Si prega di consultare anche la documentazione.", "dns_records_name": "Nome", "dns_records_status": "Stato attuale", "dns_records_type": "Tipo", diff --git a/data/web/lang/lang.nl-nl.json b/data/web/lang/lang.nl-nl.json index efffa1d7e0..46325effc0 100644 --- a/data/web/lang/lang.nl-nl.json +++ b/data/web/lang/lang.nl-nl.json @@ -510,7 +510,7 @@ "cname_from_a": "Waarde afgeleid van een A- of AAAA-vermelding.", "dns_records": "DNS-configuratie", "dns_records_24hours": "Houd er rekening mee dat wijzigingen aan DNS tot wel 24 uur in beslag kunnen nemen voordat ze op deze pagina worden weergegeven. Deze informatie is bedoeld om gemakkelijk te bekijken of de DNS-configuratie aan de eisen voldoet.", - "dns_records_docs": "Raadpleeg ook de documentatie.", + "dns_records_docs": "Raadpleeg ook de documentatie.", "dns_records_data": "Correcte gegevens", "dns_records_name": "Naam", "dns_records_status": "Huidige staat", diff --git a/data/web/lang/lang.pt-br.json b/data/web/lang/lang.pt-br.json index 9acaf87c77..fbc79bde80 100644 --- a/data/web/lang/lang.pt-br.json +++ b/data/web/lang/lang.pt-br.json @@ -554,7 +554,7 @@ "dns_records": "Registros DNS", "dns_records_24hours": "Observe que as alterações feitas no DNS podem levar até 24 horas para que seu estado atual seja refletido corretamente nesta página. O objetivo é uma forma de você ver facilmente como configurar seus registros DNS e verificar se todos os seus registros estão armazenados corretamente no DNS.", "dns_records_data": "Dados corretos", - "dns_records_docs": "Consulte também a documentação.", + "dns_records_docs": "Consulte também a documentação.", "dns_records_name": "Nome", "dns_records_status": "Estado atual", "dns_records_type": "Tipo", diff --git a/data/web/lang/lang.ro-ro.json b/data/web/lang/lang.ro-ro.json index 5c7b29b0ea..90c96c218d 100644 --- a/data/web/lang/lang.ro-ro.json +++ b/data/web/lang/lang.ro-ro.json @@ -504,7 +504,7 @@ "cname_from_a": "Valoare derivată din înregistrarea A/AAAA. Acest lucru este acceptat atâta timp cât înregistrarea indică resursele corecte.", "dns_records": "Înregistrări DNS", "dns_records_24hours": "Rețineți că modificările aduse DNS-ului pot dura până la 24 de ore pentru a reflecta corect starea lor curentă pe această pagină. Acest mecanism este conceput ca o modalitate să vezi ușor cum să îți configurezi înregistrările DNS și să verifici dacă toate înregistrările sunt stocate corect în DNS.", - "dns_records_docs": "Vă rugăm să consultați și documentația.", + "dns_records_docs": "Vă rugăm să consultați și documentația.", "dns_records_data": "Date corecte", "dns_records_name": "Nume", "dns_records_status": "Stare curentă", diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index 2a959ab3c9..993f7865b4 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -504,7 +504,7 @@ "dns_records": "Записи DNS", "dns_records_24hours": "Обратите внимание, что для внесения изменений в DNS может потребоваться до 24 часов, чтобы правильно отобразить их текущее состояние на этой странице. Эта страница предназначен для того, чтобы вы могли легко увидеть, как настроить записи DNS и проверить, все ли записи правильно занесены в DNS.", "dns_records_data": "Значение", - "dns_records_docs": "Пожалуйста, ознакомьтесь с документацией.", + "dns_records_docs": "Пожалуйста, ознакомьтесь с документацией.", "dns_records_name": "Название", "dns_records_status": "Статус", "dns_records_type": "Тип", diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index cf1cf799c2..3a424631db 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -543,7 +543,7 @@ "dns_records": "DNS zapisi", "dns_records_24hours": "Prosim upoštevajte, da lahko traja do 24 ur da se spremembe v DNS pravilno prikažejo na tej strani. Namen je da lahko enostavno vidite, kako konfigurirati svoje DNS zapise in preverite ali so vaši zapisi pravilno shranjeni v DNS.", "dns_records_data": "Pravilni podatki", - "dns_records_docs": "Prosim preverite tudi dokumentacijo.", + "dns_records_docs": "Prosim preverite tudi dokumentacijo.", "dns_records_name": "Ime", "dns_records_status": "Trenutno stanje", "dns_records_type": "Vrsta", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index d656a2cd16..466afdb854 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -523,7 +523,7 @@ "dns_records": "DNS záznamy", "dns_records_24hours": "Berte prosím do úvahy, že zmeny v DNS môžu trvať až 24 hodín, aby sa zmeny prejavili na tejto stránke. Pre jednoduchosť DNS konfigurácie môžete použiť údaje uvedené nižšie, prípadne skontrolovať tak správnosť záznamov v DNS.", "dns_records_data": "Správne dáta", - "dns_records_docs": "Pozrite si prosím dokumentáciu.", + "dns_records_docs": "Pozrite si prosím dokumentáciu.", "dns_records_name": "Meno", "dns_records_status": "Súčasný stav", "dns_records_type": "Typ", diff --git a/data/web/lang/lang.sv-se.json b/data/web/lang/lang.sv-se.json index ba97e705d1..a987081920 100644 --- a/data/web/lang/lang.sv-se.json +++ b/data/web/lang/lang.sv-se.json @@ -473,7 +473,7 @@ "cname_from_a": "Värde härstammar från A/AAAA-uppslaget. Detta stöds så länge som uppslaget pekar mot rätt resurs.", "dns_records": "DNS-uppslag", "dns_records_24hours": "Observera att ändringar gjorda i DNS kan ta upp till 24 timmar innan det visas korrekt på denna sida. Syftet med sidan är att enkelt se hur DNS-uppslagen är konfigurerade. Det är lätt att kontrollera att DNS-uppslagen är korrekt uppsatta.", - "dns_records_docs": "Se även dokumentationen.", + "dns_records_docs": "Se även dokumentationen.", "dns_records_data": "Korrektdata", "dns_records_name": "Namn", "dns_records_status": "Nuvarande status", diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index e778f1569e..201a60b41e 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -525,7 +525,7 @@ "cname_from_a": "Значення, отримане із запису A/AAAA. Це підтримується, поки запис вказує на правильний ресурс.", "dns_records": "Записи DNS", "dns_records_data": "Значення", - "dns_records_docs": "Також перегляньте документацію.", + "dns_records_docs": "Також перегляньте документацію.", "dns_records_name": "Назва", "dns_records_status": "Статус", "optional": "Цей запис необов'язковий.", diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json index b1aacf5c86..cca5ecc58d 100644 --- a/data/web/lang/lang.zh-cn.json +++ b/data/web/lang/lang.zh-cn.json @@ -494,7 +494,7 @@ "dns_records": "DNS 记录", "dns_records_24hours": "请注意 DNS 记录的更改可能需要24小时才可以使此页面的当前状态显示正确。此页面为你提供了一个可以便捷查询如何配置 DNS 记录以及检查你的 DNS 记录是否正确的方式。", "dns_records_data": "正确数据", - "dns_records_docs": "请同时也参考这个文档.", + "dns_records_docs": "请同时也参考这个文档.", "dns_records_name": "名称", "dns_records_status": "当前状态", "dns_records_type": "类型", diff --git a/data/web/lang/lang.zh-tw.json b/data/web/lang/lang.zh-tw.json index 4d84b21162..332eabb682 100644 --- a/data/web/lang/lang.zh-tw.json +++ b/data/web/lang/lang.zh-tw.json @@ -526,7 +526,7 @@ "dns_records": "DNS 紀錄", "dns_records_24hours": "請注意 DNS 紀錄的更改可能需要 24 小時才能正確顯示於此頁面。此頁面的目的是為了讓你可以輕鬆的了解如何設定 DNS 紀錄並檢查 DNS 是否設定正確。", "dns_records_data": "正確值", - "dns_records_docs": "請同時另外查看 文件.", + "dns_records_docs": "請同時另外查看 文件.", "dns_records_name": "名稱", "dns_records_status": "目前狀態", "dns_records_type": "類型", From 86ba019ca09b7e09c59ec8a1e4f562493947510a Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 9 Feb 2024 14:59:14 +0100 Subject: [PATCH 03/10] [Rspamd] apply domain wide footer to alias domains --- data/conf/rspamd/dynmaps/footer.php | 25 +++++++++- data/web/edit.php | 3 +- data/web/inc/functions.mailbox.inc.php | 65 ++++++++++++++++++-------- data/web/inc/init_db.inc.php | 3 +- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- data/web/lang/lang.pt-br.json | 4 +- data/web/lang/lang.ru-ru.json | 2 +- data/web/lang/lang.uk-ua.json | 4 +- data/web/lang/lang.zh-tw.json | 2 +- data/web/templates/edit/domain.twig | 9 +++- 11 files changed, 87 insertions(+), 34 deletions(-) diff --git a/data/conf/rspamd/dynmaps/footer.php b/data/conf/rspamd/dynmaps/footer.php index 36b307c1b5..545c45ec1c 100644 --- a/data/conf/rspamd/dynmaps/footer.php +++ b/data/conf/rspamd/dynmaps/footer.php @@ -56,21 +56,42 @@ function getallheaders() { error_log("FOOTER: checking for domain " . $domain . ", user " . $username . " and address " . $from . PHP_EOL); try { - $stmt = $pdo->prepare("SELECT `plain`, `html`, `mbox_exclude`, `skip_replies` FROM `domain_wide_footer` + // try get $target_domain if $domain is an alias_domain + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` + WHERE `alias_domain` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $domain + )); + $alias_domain = $stmt->fetch(PDO::FETCH_ASSOC); + if (!$alias_domain) { + $target_domain = $domain; + } else { + $target_domain = $alias_domain['target_domain']; + } + + // get footer associated with the domain + $stmt = $pdo->prepare("SELECT `plain`, `html`, `mbox_exclude`, `alias_domain_exclude`, `skip_replies` FROM `domain_wide_footer` WHERE `domain` = :domain"); $stmt->execute(array( - ':domain' => $domain + ':domain' => $target_domain )); $footer = $stmt->fetch(PDO::FETCH_ASSOC); + + // check if the sender is excluded if (in_array($from, json_decode($footer['mbox_exclude']))){ $footer = false; } + if (in_array($domain, json_decode($footer['alias_domain_exclude']))){ + $footer = false; + } if (empty($footer)){ echo $empty_footer; exit; } error_log("FOOTER: " . json_encode($footer) . PHP_EOL); + // footer will be applied + // get custom mailbox attributes to insert into the footer $stmt = $pdo->prepare("SELECT `custom_attributes` FROM `mailbox` WHERE `username` = :username"); $stmt->execute(array( ':username' => $username diff --git a/data/web/edit.php b/data/web/edit.php index 83ae1467e0..4c5cd89e9b 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -59,7 +59,8 @@ 'domain_details' => $result, 'domain_footer' => $domain_footer, 'mailboxes' => mailbox('get', 'mailboxes', $_GET["domain"]), - 'aliases' => mailbox('get', 'aliases', $_GET["domain"], 'address') + 'aliases' => mailbox('get', 'aliases', $_GET["domain"], 'address'), + 'alias_domains' => mailbox('get', 'alias_domains', $_GET["domain"]) ]; } } diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 0f48efbd5c..ea242cf8fa 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -3438,30 +3438,54 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $footers['plain'] = isset($_data['plain']) ? $_data['plain'] : ''; $footers['skip_replies'] = isset($_data['skip_replies']) ? (int)$_data['skip_replies'] : 0; $footers['mbox_exclude'] = array(); - if (isset($_data["mbox_exclude"])){ - if (!is_array($_data["mbox_exclude"])) { - $_data["mbox_exclude"] = array($_data["mbox_exclude"]); - } - foreach ($_data["mbox_exclude"] as $mailbox) { - if (!filter_var($mailbox, FILTER_VALIDATE_EMAIL)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('username_invalid', $mailbox) - ); - continue; + $footers['alias_domain_exclude'] = array(); + if (isset($_data["exclude"])){ + if (!is_array($_data["exclude"])) { + $_data["exclude"] = array($_data["exclude"]); + } + foreach ($_data["exclude"] as $exclude) { + if (filter_var($exclude, FILTER_VALIDATE_EMAIL)) { + $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `address` = :address + UNION + SELECT `username` FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array( + ':address' => $exclude, + ':username' => $exclude, + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if(!$row){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('username_invalid', $exclude) + ); + continue; + } + array_push($footers['mbox_exclude'], $exclude); } - $is_now = mailbox('get', 'mailbox_details', $mailbox); - if(empty($is_now)){ + elseif (is_valid_domain_name($exclude)) { + $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $exclude, + )); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if(!$row){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('username_invalid', $exclude) + ); + continue; + } + array_push($footers['alias_domain_exclude'], $exclude); + } + else { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('username_invalid', $mailbox) + 'msg' => array('username_invalid', $exclude) ); - continue; } - - array_push($footers['mbox_exclude'], $mailbox); } } foreach ($domains as $domain) { @@ -3486,12 +3510,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { try { $stmt = $pdo->prepare("DELETE FROM `domain_wide_footer` WHERE `domain`= :domain"); $stmt->execute(array(':domain' => $domain)); - $stmt = $pdo->prepare("INSERT INTO `domain_wide_footer` (`domain`, `html`, `plain`, `mbox_exclude`, `skip_replies`) VALUES (:domain, :html, :plain, :mbox_exclude, :skip_replies)"); + $stmt = $pdo->prepare("INSERT INTO `domain_wide_footer` (`domain`, `html`, `plain`, `mbox_exclude`, `alias_domain_exclude`, `skip_replies`) VALUES (:domain, :html, :plain, :mbox_exclude, :alias_domain_exclude, :skip_replies)"); $stmt->execute(array( ':domain' => $domain, ':html' => $footers['html'], ':plain' => $footers['plain'], ':mbox_exclude' => json_encode($footers['mbox_exclude']), + ':alias_domain_exclude' => json_encode($footers['alias_domain_exclude']), ':skip_replies' => $footers['skip_replies'], )); } @@ -4648,7 +4673,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } try { - $stmt = $pdo->prepare("SELECT `html`, `plain`, `mbox_exclude`, `skip_replies` FROM `domain_wide_footer` + $stmt = $pdo->prepare("SELECT `html`, `plain`, `mbox_exclude`, `alias_domain_exclude`, `skip_replies` FROM `domain_wide_footer` WHERE `domain` = :domain"); $stmt->execute(array( ':domain' => $domain diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 6fec0c2f86..445af8a9a6 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 = "08012024_1442"; + $db_version = "09022024_1433"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -273,6 +273,7 @@ function init_db_schema() { "html" => "LONGTEXT", "plain" => "LONGTEXT", "mbox_exclude" => "JSON NOT NULL DEFAULT ('[]')", + "alias_domain_exclude" => "JSON NOT NULL DEFAULT ('[]')", "skip_replies" => "TINYINT(1) NOT NULL DEFAULT '0'" ), "keys" => array( diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 73d02bdd05..2298e1cbde 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -613,6 +613,7 @@ "extended_sender_acl_info": "Der DKIM-Domainkey der externen Absenderdomain sollte in diesen Server importiert werden, falls vorhanden.
\r\n Wird SPF verwendet, muss diesem Server der Versand gestattet werden.
\r\n Wird eine Domain oder Alias-Domain zu diesem Server hinzugefügt, die sich mit der externen Absenderadresse überschneidet, wird der externe Absender hier entfernt.
\r\n Ein Eintrag @domain.tld erlaubt den Versand als *@domain.tld", "force_pw_update": "Erzwinge Passwortänderung bei nächstem Login", "force_pw_update_info": "Dem Benutzer wird lediglich der Zugang zur %s ermöglicht, App Passwörter funktionieren weiterhin.", + "footer_exclude": "von Fußzeile ausschließen", "full_name": "Voller Name", "gal": "Globales Adressbuch", "gal_info": "Das globale Adressbuch enthält alle Objekte einer Domain und kann durch keinen Benutzer geändert werden. Die Verfügbarkeitsinformation in SOGo ist nur bei eingeschaltetem globalen Adressbuch ersichtlich Zum Anwenden einer Änderung muss SOGo neugestartet werden.", @@ -631,7 +632,6 @@ "max_quota": "Max. Größe per Mailbox (MiB)", "maxage": "Maximales Alter in Tagen einer Nachricht, die kopiert werden soll
(0 = alle Nachrichten kopieren)", "maxbytespersecond": "Max. Übertragungsrate in Bytes/s (0 für unlimitiert)", - "mbox_exclude": "Mailboxen ausschließen", "mbox_rl_info": "Dieses Limit wird auf den SASL Loginnamen angewendet und betrifft daher alle Absenderadressen, die der eingeloggte Benutzer verwendet. Bei Mailbox Ratelimit überwiegt ein Domain-weites Ratelimit.", "mins_interval": "Intervall (min)", "multiple_bookings": "Mehrfaches Buchen", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index e413664f55..964caade6c 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -613,6 +613,7 @@ "extended_sender_acl_info": "A DKIM domain key should be imported, if available.
\r\n Remember to add this server to the corresponding SPF TXT record.
\r\n Whenever a domain or alias domain is added to this server, that overlaps with an external address, the external address is removed.
\r\n Use @domain.tld to allow to send as *@domain.tld.", "force_pw_update": "Force password update at next login", "force_pw_update_info": "This user will only be able to login to %s. App passwords remain useable.", + "footer_exclude": "Exclude from footer", "full_name": "Full name", "gal": "Global Address List", "gal_info": "The GAL contains all objects of a domain and cannot be edited by any user. Free/busy information in SOGo is missing, if disabled! Restart SOGo to apply changes.", @@ -631,7 +632,6 @@ "max_quota": "Max. quota per mailbox (MiB)", "maxage": "Maximum age of messages in days that will be polled from remote
(0 = ignore age)", "maxbytespersecond": "Max. bytes per second
(0 = unlimited)", - "mbox_exclude": "Exclude mailboxes", "mbox_rl_info": "This rate limit is applied on the SASL login name, it matches any \"from\" address used by the logged-in user. A mailbox rate limit overrides a domain-wide rate limit.", "mins_interval": "Interval (min)", "multiple_bookings": "Multiple bookings", diff --git a/data/web/lang/lang.pt-br.json b/data/web/lang/lang.pt-br.json index fbc79bde80..5636f5cd0c 100644 --- a/data/web/lang/lang.pt-br.json +++ b/data/web/lang/lang.pt-br.json @@ -609,6 +609,7 @@ "extended_sender_acl_info": "Uma chave de domínio DKIM deve ser importada, se disponível.
\r\n Lembre-se de adicionar esse servidor ao registro TXT SPF correspondente.
\r\n Sempre que um domínio ou domínio de alias é adicionado a esse servidor, que se sobrepõe a um endereço externo, o endereço externo é removido.
\r\n Use @domain .tld para permitir o envio como * @domain .tld.", "force_pw_update": "Forçar a atualização da senha no próximo login", "force_pw_update_info": "Esse usuário só poderá fazer login em %s. As senhas do aplicativo permanecem utilizáveis.", + "footer_exclude": "Excluir do rodapé", "full_name": "Nome completo", "gal": "Lista de endereços global", "gal_info": "A GAL contém todos os objetos de um domínio e não pode ser editada por nenhum usuário. Faltam informações de disponibilidade no SoGo, se desativadas! Reinicie o SoGo para aplicar as alterações.", @@ -687,8 +688,7 @@ "unchanged_if_empty": "Se inalterado, deixe em branco", "username": "Nome de usuário", "validate_save": "Valide e salve", - "custom_attributes": "Atributos personalizados", - "mbox_exclude": "Excluir mailboxes" + "custom_attributes": "Atributos personalizados" }, "fido2": { "confirm": "Confirme", diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index 993f7865b4..5891b6abec 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -546,6 +546,7 @@ "extended_sender_acl_info": "Для внешних доменов должен быть импортирован или сгенерирован доменный ключ DKIM с соответствующей записью TXT в домене, если внешний домен использует DMARC.
\r\n Не забудьте добавить этот сервер к соответствующей записи SPF TXT внешнего домена.
\r\n Добавление домена из списка внешних адресов в mailcow автоматически удалит соответствующие записи из внешних адресов пользователей.
\r\n Чтобы разрешить пользователю отправку от имени *@domain.tld, укажите @domain.tld.", "force_pw_update": "Требовать смены пароля при следующем входе в систему", "force_pw_update_info": "Пользователь должен будет войти в %s и сменить свой пароль. mailcow OAuth2, SOGo, EAS, IMAP/POP3 и SMTP будут не доступны до смены пароля.", + "footer_exclude": "Исключить из нижнего колонтитула", "full_name": "Полное имя", "gal": "GAL - Глобальная адресная книга", "gal_info": "GAL содержит все объекты домена и не подлежит редактированию. Информация о занятости в SOGo будет отсутствовать для домена, если данная функция будет отключена! Требуется перезапустить SOGo, чтобы применить изменения.", @@ -635,7 +636,6 @@ "domain_footer": "Нижний колонтитул домена", "domain_footer_html": "HTML нижний колонтитул", "domain_footer_plain": "ПРОСТОЙ нижний колонтитул", - "mbox_exclude": "Исключить почтовые ящики", "custom_attributes": "Пользовательские атрибуты" }, "fido2": { diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 201a60b41e..7312246425 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -561,6 +561,7 @@ "extended_sender_acl": "Зовнішні адреси пошти", "force_pw_update": "Вимагати зміну пароля при наступному вході до системи", "force_pw_update_info": "Цей користувач зможе увійти лише в %s. Паролі додатків залишаються придатними для використання.", + "footer_exclude": "Виключити з нижнього колонтитула", "full_name": "Повне ім'я", "gal": "GAL - Глобальна адресна книга", "generate": "згенерувати", @@ -659,8 +660,7 @@ }, "domain_footer_html": "Нижній колонтитул HTML", "domain_footer_plain": "ЗВИЧАЙНИЙ нижній колонтитул", - "custom_attributes": "Користувацькі атрибути", - "mbox_exclude": "Виключити поштові скриньки" + "custom_attributes": "Користувацькі атрибути" }, "fido2": { "confirm": "Підтвердити", diff --git a/data/web/lang/lang.zh-tw.json b/data/web/lang/lang.zh-tw.json index 332eabb682..af2fb557ee 100644 --- a/data/web/lang/lang.zh-tw.json +++ b/data/web/lang/lang.zh-tw.json @@ -569,6 +569,7 @@ "extended_sender_acl_info": "如果可以的話,請匯入 DKIM 域名金鑰。
\r\n別忘記將此伺服器新增到相應的 SPF TXT 中。
\r\n當域名或域名別名被新增時,若其與此外部寄件人地址交疊,則外部寄件人地址會被移除。
\r\n填入 @domain.tld 以允許作為 *@domain.tld 發送郵件。", "force_pw_update": "在下一次登入時強制要求更新密碼", "force_pw_update_info": "此使用者只能登入至 %s。應用程式密碼仍可正常使用", + "footer_exclude": "从页脚排除", "full_name": "全名", "gal": "全域聯絡人清單", "gal_info": "全域聯絡人清單包含了域名下的所有物件,且使用者不可編輯。如果關閉,使用者的 空閒/繁忙 訊息將不能在 SOGo 中顯示。重新啟動 SOGo 以應用更改。", @@ -648,7 +649,6 @@ "validate_save": "驗證並儲存", "domain_footer_info": "網域範圍的頁尾將會新增至與該網域內的位址關聯的所有外發電子郵件。
以下變數可用於頁尾:", "custom_attributes": "自訂屬性", - "mbox_exclude": "排除信箱", "pushover_sound": "聲音" }, "fido2": { diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 8a700d06ad..08d031c3cf 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -289,9 +289,9 @@ {{ lang.edit.domain_footer_info_vars.custom }}
- +
- {% for mailbox in mailboxes %} {% endfor %} + {% for alias_domain in alias_domains %} + + {% endfor %}
From a0e55cb9b17933f355bbaf773295a2592c950211 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 9 Feb 2024 15:08:21 +0100 Subject: [PATCH 04/10] [Web] fix blank /debug page with invalid timezone --- data/web/debug.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/data/web/debug.php b/data/web/debug.php index 52052f682e..9c338009c8 100644 --- a/data/web/debug.php +++ b/data/web/debug.php @@ -39,9 +39,13 @@ $StartedAt['month'], $StartedAt['day'], $StartedAt['year'])); - $user_tz = new DateTimeZone(getenv('TZ')); - $date->setTimezone($user_tz); - $started = $date->format('r'); + try { + $user_tz = new DateTimeZone(getenv('TZ')); + $date->setTimezone($user_tz); + $started = $date->format('r'); + } catch(Exception $e) { + $started = '?'; + } } else { $started = '?'; From 288dbfa37c59666e548915e66cd0cd3902f08eed Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 9 Feb 2024 15:13:45 +0100 Subject: [PATCH 05/10] [Web] display human readable domainnames instead of punycode --- data/web/inc/functions.mailbox.inc.php | 1 + data/web/js/site/mailbox.js | 12 ++++++++---- data/web/templates/edit/domain.twig | 9 +++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 0f48efbd5c..cf2e567e52 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -4316,6 +4316,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $domaindata['mboxes_in_domain'] = $MailboxDataDomain['count']; $domaindata['mboxes_left'] = $row['mailboxes'] - $MailboxDataDomain['count']; $domaindata['domain_name'] = $row['domain']; + $domaindata['domain_h_name'] = idn_to_utf8($row['domain']); $domaindata['description'] = $row['description']; $domaindata['max_num_aliases_for_domain'] = $row['aliases']; $domaindata['max_num_mboxes_for_domain'] = $row['mailboxes']; diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index cc316b713b..e2016e3eda 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -451,6 +451,10 @@ jQuery(function($){ dataSrc: function(json){ $.each(json.data, function(i, item) { item.domain_name = escapeHtml(item.domain_name); + item.domain_h_name = escapeHtml(item.domain_h_name); + if (item.domain_name != item.domain_h_name){ + item.domain_h_name = item.domain_h_name + '' + item.domain_name + ''; + } item.aliases = item.aliases_in_domain + " / " + item.max_num_aliases_for_domain; item.mailboxes = item.mboxes_in_domain + " / " + item.max_num_mboxes_for_domain; @@ -489,11 +493,11 @@ jQuery(function($){ if (item.backupmx == 1) { if (item.relay_unknown_only == 1) { - item.domain_name = '
Relay Non-Local
' + item.domain_name; + item.domain_h_name = '
Relay Non-Local
' + item.domain_h_name; } else if (item.relay_all_recipients == 1) { - item.domain_name = '
Relay All
' + item.domain_name; + item.domain_h_name = '
Relay All
' + item.domain_h_name; } else { - item.domain_name = '
Relay
' + item.domain_name; + item.domain_h_name = '
Relay
' + item.domain_h_name; } } }); @@ -521,7 +525,7 @@ jQuery(function($){ }, { title: lang.domain, - data: 'domain_name', + data: 'domain_h_name', responsivePriority: 3, defaultContent: '' }, diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 8a700d06ad..8d5c790468 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -26,6 +26,15 @@ +
+ +
+ {{ result.domain_h_name }} + {% if result.domain_h_name != result.domain_name %} + {{ result.domain_name }} + {% endif %} +
+
From dac1bd88dc2842317fefb22b0efb0c8a1eb92bf4 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 9 Feb 2024 15:17:02 +0100 Subject: [PATCH 06/10] [Web] fix setting unchecked checkboxes --- data/web/templates/modals/mailbox.twig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 22807c8d39..6316d9fb05 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -381,6 +381,12 @@