From eb26bcbc9417c6d0d2fa35db7ea5e648b48e016f Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 13 Sep 2025 21:41:59 +0200 Subject: [PATCH 01/40] Translations update from Weblate (#6743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Web] Updated lang.zh-cn.json Co-authored-by: Easton Man * [Web] Updated lang.si-si.json [Web] Updated lang.si-si.json Co-authored-by: Matjaž Tekavec Co-authored-by: milkmaker --------- Co-authored-by: Easton Man Co-authored-by: Matjaž Tekavec --- data/web/lang/lang.si-si.json | 15 ++++++++++----- data/web/lang/lang.zh-cn.json | 23 ++++++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index 56da00f74..95e23a5cb 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -109,7 +109,9 @@ "relay_transport_info": "
Info
Definirate lahko preslikave transportov za cilj po meri za to domeno. Če ni nastavljena, se ustvari MX poizvedba.", "syncjob_hint": "Pozor! Gesla se morajo shraniti v golo besedilo!", "timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja", - "dry": "Simuliraj sinhronizacijo" + "dry": "Simuliraj sinhronizacijo", + "internal": "Notranje", + "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen." }, "admin": { "access": "Dostop", @@ -776,7 +778,9 @@ "mta_sts_max_age_info": "Čas v sekundah, ki ga lahko prejemni poštni strežniki shranijo v predpomnilnik, dokler se ne ponovno naloži.", "mta_sts_mx": "MX strežnik", "mta_sts_mx_info": "Omogoča pošiljanje samo na izrecno navedena imena gostiteljskih strežnikov poštnih strežnikov; pošiljajoči MTA preveri, ali se ime gostitelja DNS MX ujema s seznamom pravilnikov, in dovoljuje dostavo le z veljavnim potrdilom TLS (zaščita pred MITM).", - "mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami)." + "mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami).", + "internal": "Notranje", + "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen." }, "footer": { "restart_container_info": "Pomembno: Ugoden ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.", @@ -991,7 +995,8 @@ "yes": "✓", "weekly": "Tedensko", "sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.
\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.

Globalni predfilter sita • Predfilter • Uporabniški skripti • Postfilter • Globalni postfilter sita", - "tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.
\n Za več informacij preverite dokumentacijo »smtp_tls_policy_maps«." + "tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.
\n Za več informacij preverite dokumentacijo »smtp_tls_policy_maps«.", + "internal": "Notranje" }, "fido2": { "known_ids": "Znani ID-ji", @@ -1362,7 +1367,7 @@ "spamfilter_default_score": "Privzete vrednosti", "spamfilter_green": "Zelena: to sporočilo ni neželena pošta", "spamfilter_hint": "Prva vrednost opisuje »nizko oceno neželene pošte«, druga pa »visoko oceno neželene pošte«.", - "spamfilter_red": "Rdeča: To sporočilo je neželena pošta in ga bo strežnik zavrnil.", + "spamfilter_red": "Rdeča: To sporočilo je neželena pošta in ga bo strežnik zavrnil", "spamfilter_table_action": "Dejanje", "spamfilter_table_add": "Dodaj element", "spamfilter_table_domain_policy": "ni na voljo (pravilnik domene)", @@ -1407,7 +1412,7 @@ "warning": { "cannot_delete_self": "Prijavljenega uporabnika ni mogoče izbrisati", "domain_added_sogo_failed": "Domena je bila dodana, vendar ponovni zagon SOGo ni uspel. Preverite dnevnike strežnika.", - "dovecot_restart_failed": "Dovecota ni uspelo znova zagnati, preverite dnevnike.", + "dovecot_restart_failed": "Dovecota ni uspelo znova zagnati, preverite dnevnike", "fuzzy_learn_error": "Napaka učenja mehkega zgoščevanja: %s", "hash_not_found": "Zgoščena vrednost ni bila najdena ali je bila že izbrisana", "ip_invalid": "Preskočen neveljaven IP: %s", diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json index 3c46eb8a4..c2f9cdc35 100644 --- a/data/web/lang/lang.zh-cn.json +++ b/data/web/lang/lang.zh-cn.json @@ -109,7 +109,9 @@ "username": "用户名", "validate": "验证", "validation_success": "验证成功", - "dry": "模拟同步(Dry run)" + "dry": "模拟同步(Dry run)", + "internal_info": "内部的别名只能在域内部或者别名域内部访问。", + "internal": "内部的" }, "admin": { "access": "权限管理", @@ -405,7 +407,9 @@ "user_quicklink": "隐藏指向用户登陆页面的快捷链接", "admin_quicklink": "隐藏指向管理员登陆页面的快捷链接", "force_sso": "强制要求单点登录(SSO)", - "user_link": "自定义链接" + "user_link": "自定义链接", + "app_hide": "在登入界面隐藏", + "needs_restart": "需要重启" }, "danger": { "access_denied": "访问被拒绝或者表单数据无效", @@ -546,7 +550,11 @@ "generic_server_error": "服务器错误。请联系您的管理员。", "authsource_in_use": "由于当前有一个或多个用户正在使用该身份提供者(IDP),因此无法更改或删除。", "iam_test_connection": "连接失败", - "required_data_missing": "缺少需要的 %s 数据" + "required_data_missing": "缺少需要的 %s 数据", + "max_age_invalid": "最大有效时间 %s 无效", + "mode_invalid": "模式 %s 无效", + "mx_invalid": "MX 记录 %s 无效", + "version_invalid": "版本 %s 无效" }, "debug": { "chart_this_server": "图表 (此服务器)", @@ -732,7 +740,11 @@ "domain_footer_skip_replies": "在回信中忽略 footer", "footer_exclude": "从 footer 中排除", "last_modified": "上次修改时间", - "pushover_sound": "声音" + "pushover_sound": "声音", + "internal": "内部的", + "internal_info": "内部的别名只能在域内部或者别名域内部访问。", + "mta_sts": "邮件传输代理严格传输安全协议(MTA-STS)", + "mta_sts_version": "版本" }, "fido2": { "confirm": "确认", @@ -978,7 +990,8 @@ "relay_unknown": "转发未知信箱", "templates": "模板", "template": "模板", - "iam": "身份提供者(IDP)" + "iam": "身份提供者(IDP)", + "internal": "内部的" }, "oauth2": { "access_denied": "请作为邮箱所有者登录以使用 OAuth2 授权。", From 2891bbf82ad35a1f8aa3d302c36c7e9e909ccba2 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Tue, 16 Sep 2025 18:24:12 +0200 Subject: [PATCH 02/40] Translations update from Weblate (#6749) * [Web] Updated lang.cs-cz.json Co-authored-by: Filip Hajny * [Web] Updated lang.lv-lv.json Co-authored-by: Edgars Andersons --------- Co-authored-by: Filip Hajny Co-authored-by: Edgars Andersons --- data/web/lang/lang.cs-cz.json | 44 ++++++++++--- data/web/lang/lang.lv-lv.json | 112 +++++++++++++++++++++------------- 2 files changed, 103 insertions(+), 53 deletions(-) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 9ef0304c8..b3068ab0f 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -24,7 +24,7 @@ "sogo_access": "Správa přístupu do SOGo", "sogo_profile_reset": "Resetování profilu SOGo", "spam_alias": "Dočasné aliasy", - "spam_policy": "Blacklist/Whitelist", + "spam_policy": "Denylist/Allowlist", "spam_score": "Skóre spamu", "syncjobs": "Synchronizační úlohy", "tls_policy": "Pravidla TLS", @@ -109,7 +109,9 @@ "validate": "Ověřit", "validation_success": "Úspěšně ověřeno", "tags": "Štítky", - "dry": "Simulovat synchronizaci" + "dry": "Simulovat synchronizaci", + "internal": "Interní", + "internal_info": "Interní aliasy jsou přístupné jen z vlastních domén nebo jejich aliasů." }, "admin": { "access": "Přístupy", @@ -303,7 +305,7 @@ "rspamd_global_filters": "Mapa globálních filtrů", "rspamd_global_filters_agree": "Budu opatrný!", "rspamd_global_filters_info": "Mapa globálních filtrů obsahuje jiné globální black- a whitelisty.", - "rspamd_global_filters_regex": "Názvy jsou dostatečným vysvětlením. Musí obsahovat jen platné regulární výrazy ve formátu \"/vyraz/parametry\" (e.g. /.+@domena\\.tld/i).
\r\n Každý výraz bude podroben základní kontrole, přesto je možné Rspamd 'rozbít', nebude-li syntax zcela korektní.
\r\n Rspamd se pokusí načíst mapu po každé změně. V případě potíží, restartujte Rspamd, aby se konfigurace načetla explicitně.", + "rspamd_global_filters_regex": "Názvy stačí k vysvětlení. Položky musejí obsahovat jen platné regulární výrazy ve tvaru \"/vyraz/parametry\" (e.g. /.+@domena\\.tld/i).
\n Každý výraz bude podroben základní kontrole, přesto je možné Rspamd 'rozbít', nebude-li syntax zcela korektní.
\n Rspamd se pokusí po každé změně načíst mapu znovu. V případě potíží restartujte Rspamd, aby se konfigurace načetla explicitně.", "rspamd_settings_map": "Nastavení Rspamd", "sal_level": "Úroveň 'Moo'", "save": "Uložit změny", @@ -407,7 +409,9 @@ "iam_extra_permission": "Aby vše fungovalo, musí mít mailcow klient v Keycloaku nastavený servisní účet a povolení view-users.", "iam_host": "Hostitel", "iam_host_info": "Zadejte jeden či více hostitelů, oddělte čárkou.", - "iam_import_users": "Importovat uživatele" + "iam_import_users": "Importovat uživatele", + "iam_auth_flow": "Proces autentizace", + "needs_restart": "potřebuje restart" }, "danger": { "access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři", @@ -548,7 +552,11 @@ "img_size_exceeded": "Obrázek má větší než povolenou velikost souboru", "invalid_reset_token": "Neplatný resetovací token", "required_data_missing": "Chybí potřebný údaj %s", - "reset_token_limit_exceeded": "Byl překročen limit na reset tokeny. Zkuste to později." + "reset_token_limit_exceeded": "Byl překročen limit na reset tokeny. Zkuste to později.", + "max_age_invalid": "Maximální životnost %s není platná", + "mode_invalid": "Mód %s není platný", + "mx_invalid": "Záznam MX %s není platný", + "version_invalid": "Verze %s není platná" }, "datatables": { "emptyTable": "Tabulka neobsahuje žádná data", @@ -759,7 +767,20 @@ "mailbox_rename_warning": "DŮLEŽITÉ! Vytvořte si zálohu schránky, než ji přejmenujete.", "mailbox_rename_alias": "Automaticky vytvořit alias", "mailbox_rename_title": "Nový název zdejší schránky", - "pushover": "Pushover" + "pushover": "Pushover", + "internal": "Interní", + "internal_info": "Interní aliasy jsou přístupné jen z vlastních domén nebo jejich aliasů.", + "mta_sts": "MTA-STS", + "mta_sts_info": "MTA-STS je standard, jenž říká poštovním serverům, aby komunikovaly pomocí TLS s platnými certifikáty.
Používá se, pokud není k dispozici DANE, např. chybí-li či není podporováno DNSSEC.
Pozn.: Podporuje-li přijímající doména DANE a DNSSEC, bude vždy použito DANE; MTA-STS zůstane jako plán B.", + "mta_sts_version": "Verze", + "mta_sts_version_info": "Určuje verzi standardu MTA-STS – zatím je podporována jen STSv1.", + "mta_sts_mode": "Mód", + "mta_sts_mode_info": "K dispozici jsou tři módy:
  • testing – pravidlo se jen sleduje, porušení je bez následků.
  • enforce – pravidlo je důsledně dodržováno, spojení bez platného TLS jsou odmítána.
  • none – pravidlo je zveřejněno, ale neuplatňuje se.
", + "mta_sts_max_age": "Maximální životnost", + "mta_sts_max_age_info": "Doba v sekundách, po niž poštovní servery mohou toho pravidlo držet v mezipaměti bez nutnosti obnovení.", + "mta_sts_mx": "Server MX", + "mta_sts_mx_info": "Dovoluje odesílání jen výslovně vypsaným poštovním serverům; odesílající server kontroluje, že server MX určený v DNS odpovídá pravidlu, a povolí doručení jen s platným certifikátem TLS (chrání přes útokem typu MITM).", + "mta_sts_mx_notice": "Lze zadat více serverů MX (oddělte čárkou)." }, "fido2": { "confirm": "Potvrdit", @@ -829,7 +850,8 @@ "login_admintext": "Přihlášení správce", "login_user": "Přihlášení uživatele", "login_dadmin": "Přihlášení správce domény", - "login_admin": "Přihlášení správce" + "login_admin": "Přihlášení správce", + "email": "Mailová adresa" }, "mailbox": { "action": "Akce", @@ -861,7 +883,7 @@ "bcc": "BCC", "bcc_destination": "Cíl kopie", "bcc_destinations": "Cíl kopií", - "bcc_info": "Skrytá kopie (mapa BCC) se používá pro tiché předávání kopií všech zpráv na jinou adresu. Mapa příjemců se použije, funguje-li je místní cíl jako adresát zprávy. Totéž platí pro mapy odesílatelů.\nMístní cíl se nedozví, selže-li doručení na cíl BCC.", + "bcc_info": "
Skrytá kopie (mapa BCC) se používá pro tiché předávání kopií všech zpráv na jinou adresu. Mapa příjemců se použije, funguje-li je místní cíl jako adresát zprávy. Totéž platí pro mapy odesílatelů.
\n Místní cíl se nedozví, selže-li doručení na cíl BCC.", "bcc_local_dest": "Týká se", "bcc_map": "Skrytá kopie", "bcc_map_type": "Typ skryté kopie", @@ -1005,7 +1027,8 @@ "weekly": "Každý týden", "yes": "✓", "relay_unknown": "Předávání neexistujících schránek", - "iam": "Poskytovatel identity" + "iam": "Poskytovatel identity", + "internal": "Interní" }, "oauth2": { "access_denied": "K udělení přístupu se přihlašte jako vlastník mailové schránky.", @@ -1082,7 +1105,8 @@ "hold_mail_legend": "Podrží vybrané e-maily. (Zabrání dalším pokusům o doručení)", "show_message": "Zobrazit zprávu", "unhold_mail": "Uvolnit", - "unhold_mail_legend": "Uvolnit vybrané e-maily k doručení. (Pouze v případě předchozího podržení)" + "unhold_mail_legend": "Uvolnit vybrané e-maily k doručení. (Pouze v případě předchozího podržení)", + "unban": "odblokovat" }, "ratelimit": { "disabled": "Vypnuto", diff --git a/data/web/lang/lang.lv-lv.json b/data/web/lang/lang.lv-lv.json index 2b433b8e8..86eb91a66 100644 --- a/data/web/lang/lang.lv-lv.json +++ b/data/web/lang/lang.lv-lv.json @@ -39,16 +39,16 @@ "alias_domain_info": "Tikai derīgi domēna vārdi (komatu atdalīti).", "automap": "Mēģiniet automatizēt mapes (\"Nosūtītie vienumi\", \"Nosūtītie\" => \"Nosūtītie\" etc.)", "backup_mx_options": "Dublējuma MX iespējas", - "delete1": "Dzēst no avota, kad tas ir pabeigts", + "delete1": "Izdzēst no avota pēc pabeigšanas", "delete2": "Dzēsiet ziņojumus galamērķī, kas nav avotā", - "delete2duplicates": "Dzēst dublikātus galamērķī", + "delete2duplicates": "Izdzēst atkārtojošos vienumus galamērķī", "description": "Apraksts", "domain": "Domēns", "domain_quota_m": "Kopējā domēna kvota (MiB)", "enc_method": "Šifrēšanas metode", "exclude": "Izslēgt objektus (regex)", "full_name": "Pilns vārds", - "goto_null": "Klusām dzēst pastu", + "goto_null": "Klusām atmest pastu", "hostname": "Saimniekdators", "kind": "Veids", "mailbox_quota_m": "Maks. kvota pastkastei (MiB)", @@ -77,12 +77,13 @@ "target_domain": "Mērķa domēns", "username": "Lietotājvārds", "validate": "Apstiprināt", - "validation_success": "Apstiprināts veiksmīgi", + "validation_success": "Sekmīgi apstiprināts", "bcc_dest_format": "BCC galamērķim ir jābūt vienai derīgai e-pasta adresei.
Ja ir nepieciešams nosūtīt kopiju vairākām adresēm, jāizveido aizstājvārds un jāizmanto tas šeit.", "domain_matches_hostname": "Domēns %s atbilst saimniekdatora nosaukumam", "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)", "app_password": "Pievienot lietotnes paroli", - "app_passwd_protocols": "Atļautie lietotnes paroles protokoli" + "app_passwd_protocols": "Atļautie lietotnes paroles protokoli", + "goto_spam": "Apgūt kā mēstuli" }, "admin": { "access": "Pieeja", @@ -115,14 +116,14 @@ "domain": "Domēns", "domain_admins": "Domēna administratori", "edit": "Labot", - "empty": "Nav rezultātu", + "empty": "Nav iznākuma", "f2b_ban_time": "Aizlieguma laiks (s)", "f2b_max_attempts": "Maks. piegājieni", "f2b_netban_ipv4": "IPv4 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-32)", "f2b_netban_ipv6": "IPv6 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-128)", "f2b_parameters": "Fail2ban parametri", "f2b_retry_window": "Atkārtošanas logs (s) priekš maks. piegājiena", - "f2b_whitelist": "Baltā saraksta tīkls/hosts", + "f2b_whitelist": "Atļautie tīkli/resursdatori", "filter_table": "Filtru tabula", "forwarding_hosts": "Hostu pārsūtīšana", "forwarding_hosts_add_hint": "Var norādīt vai nu IPv4/IPv6 adreses, tīklu ar CIDR apzīmējumu, saimniekdatoru nosaukumus (kas tiks atrisināti IP adresēs) vai arī domēna vārdus (kas tiks atrisināti IP adresēs, vaicājot SPF ierakstus, vai, ja tādu nav, MX ierakstus).", @@ -181,7 +182,10 @@ "rspamd_com_settings": "Iestatījuma nosaukums tiks izveidots automātiski. Lūgums zemāk skatīt priekšiestatījumu piemērus. Vairāk informācijas ir Rspamd dokumentācijā", "reset_password_vars": "{{link}} Izveidotā paroles atiestatīšanas saite
{{username}} Lietotāja, kurš pieprasīja paroles atiestatīšanu, pastkastes nosaukums
{{username2}} Atkopšanas pastkastes nosaukums
{{date}} Paroles atiestatīšanas pieprasījuma veikšanas datums
{{token_lifetime}} Pilnvaras derīgums minūtēs
{{hostname}} mailcow saimniekdatora nosaukums", "ui_header_announcement_help": "Paziņojums ir redzams visiem lietotājiem, kuri ir pieteikušies, un pieteikšanās ekrānā saskarnē.", - "login_time": "Pieteikšanās laiks" + "login_time": "Pieteikšanās laiks", + "iam_version": "Versija", + "quarantine_max_age": "Lielākais pieļaujamais vecums dienās
Vērtībai jābūt vienādai ar vai lielākai par 1 dienu.", + "quarantine_max_score": "Atmest paziņojumu, ja e-pasta ziņojuma mēstuļu novērtējums ir augstāks par šo vērtību:
Noklusējums ir 9999.0" }, "danger": { "access_denied": "Piekļuve liegta, vai nepareizi dati", @@ -201,8 +205,8 @@ "goto_empty": "Aizstājādresei jāsatur vismaz viena derīga mērķa adrese", "goto_invalid": "Goto adrese nepareiza", "imagick_exception": "Kļūda: Imagick izņēmums, lasot attēlu", - "img_invalid": "Nevar apstiprināt attēla failu", - "img_tmp_missing": "Nevar apstiprināt attēla failu: pagaidu failu nav atrasts", + "img_invalid": "Nevar apstiprināt attēla datni", + "img_tmp_missing": "Nevar apstiprināt attēla datni: pagaidu datne nav atrasta", "invalid_mime_type": "Nederīgs mime tips", "is_alias": "%s jau ir zināma kā aizstājadrese", "is_alias_or_mailbox": "%s jau ir zināms kā aizstājvārds, pastkaste vai aizstājadrese, kas ir izvērsta no aizstājdomēna.", @@ -234,7 +238,10 @@ "username_invalid": "Lietotājvārds nevar tikt izmantots", "validity_missing": "Lūdzu piešķiriet derīguma termiņu", "domain_cannot_match_hostname": "Domēns nevar atbilst saimniekdatora nosaukumam", - "app_passwd_id_invalid": "Lietotnes paroles Id %s ir nederīgs" + "app_passwd_id_invalid": "Lietotnes paroles Id %s ir nederīgs", + "img_dimensions_exceeded": "Attēls pārsniedz lielāko pieļaujamo attēla lielumu", + "img_size_exceeded": "Attēls pārsniedz lielāko pieļaujamo datnes lielumu", + "version_invalid": "Versija %s ir nederīga" }, "diagnostics": { "cname_from_a": "Vērtība, kas iegūta no A/AAAA ieraksta. Tas tiek atbalstīts tik ilgi, kamēr ieraksts norāda uz pareizo resursu.", @@ -251,9 +258,9 @@ "alias": "Labot aizstājvārdu", "automap": "Mēģiniet automatizēt mapes (\"Nosūtītie vienumi\", \"Nosūtītie\" => \"Nosūtītie\" utt.)", "backup_mx_options": "Dublēt MX iespējas", - "delete1": "Dzēst no avota, kad pabeigts", + "delete1": "Izdzēst no avota pēc pabeigšanas", "delete2": "Dzēsiet ziņojumus galamērķī, kas nav avotā", - "delete2duplicates": "Dzēst dublikātus galamērķī", + "delete2duplicates": "Izdzēst atkārtojošos vienumus galamērķī", "description": "Apraksts", "domain": "Labot domēnu", "domain_admin": "Labot domēna administratoru", @@ -273,7 +280,7 @@ "max_aliases": "Lielākais aizstājvārdu skaits", "max_mailboxes": "Maks. iespējamās pastkastes", "max_quota": "Maks. kvota uz pastkasti (MiB)", - "maxage": "Lielākais ziņojumu, kuri tiks vaicāti attālajā serverī, vecums dienās
(0 = neņemt vērā vecumu)", + "maxage": "Lielākais pieļaujamais ziņojumu, kuri tiks vaicāti attālajā serverī, vecums dienās
(0 = neņemt vērā vecumu)", "maxbytespersecond": "Maks. baiti sekundē (0 ir vienāds ar neierobežotu skaitu)", "mins_interval": "Intervāls (min)", "multiple_bookings": "Vairāki rezervējumi", @@ -292,8 +299,8 @@ "sieve_type": "Filtra tips", "skipcrossduplicates": "Izlaist dublētus ziņojumus pa mapēm (pirmais nāk, pirmais kalpo)", "spam_alias": "Izveidot vai mainīt laika ierobežotas aizstājadreses", - "spam_policy": "Pievienot vai noņemt vienumus baltajā-/melnajā sarakstā", - "spam_score": "Iestatīt pielāgotu surogātpasta vērtējumu", + "spam_policy": "Pievienot vai noņemt vienumus atļautajā/liegumu sarakstā", + "spam_score": "Iestatīt pielāgotu mēstules vērtējumu", "subfolder2": "Sinhronizēt galamērķa apakšmapē
(tukšs = neizmantot apakšmapi)", "syncjob": "Labot sinhronizācijas darbu", "target_address": "Mērķa adrese/s (atdalītas ar komatu)", @@ -316,17 +323,21 @@ "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)", "app_passwd_protocols": "Atļautie lietotnes paroles protokoli", "allowed_protocols": "Atļautie protokoli tiešai lietotāja piekļuvei (neietekmē lietotnes paroles protokolus)", - "app_passwd": "Lietotnes parole" + "app_passwd": "Lietotnes parole", + "mta_sts_version": "Versija", + "mta_sts_version_info": "Norāda MTA-STS standarta versiju – pašreiz ir derīga tikai STSv1.", + "sender_acl_disabled": "Sūtītāja pārbaude ir atspējota" }, "footer": { "cancel": "Atcelt", - "confirm_delete": "Apstiprināt dzēšanu", - "delete_now": "Dzēst tagad", + "confirm_delete": "Apstiprināt izdzēšanu", + "delete_now": "Izdzēst tagad", "delete_these_items": "Lūgums apstiprināt izmaiņas šim objekta Id", "loading": "Lūgums uzgaidīt...", "restart_container": "Restartēt konteineri", "restart_container_info": "Svarīgi: nesteidzīga pārsāknēšana var aizņemt ilgāku laiku. Lūgums uzgaidīt, līdz tā tiek pabeigta.", - "restart_now": "Pārsāknēt tagad" + "restart_now": "Pārsāknēt tagad", + "hibp_nok": "Sakrīt. Šī, iespējams, ir bīstama parole." }, "header": { "administration": "Konfigurācija un informācija", @@ -389,7 +400,7 @@ "domain_quota_total": "Kopējais domēna ierobežojums", "domains": "Domēns", "edit": "Labot", - "empty": "Nav rezultātu", + "empty": "Nav iznākuma", "excludes": "Izslēdzot", "filter_table": "Filtra tabula", "filters": "Filtri", @@ -448,13 +459,15 @@ "add_alias_expand": "Izvērst aizstājvārdu pār aizstājdomēniem", "alias_domain_alias_hint": "Aizstājvārdi netiek automātiski piemēroti domēnu aizstājvārdiem. Aizstājadrese my-alias@domain nenosedz adresi my-alias@alias-domain (kur \"alias-domain\" ir iedomāts \"domain\" aizstājdomēns).
Lūgums izmantot sieta atlasi, lai pārvirzītu pastu uz ārēju pastkasti (skatīt cilti \"Atlasīšana\" vai izmantot SOGo -> Pārsūtītājs). \"Izvērst aizstājvārdu pār aizstājdomēniem\" ir izmantojams, lai automātiski pievienotu trūkstošos aiztājvārdus.", "alias_domain_backupmx": "Aizstājdomēns ir neaktīvs retranslācijas domēnam", - "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)" + "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)", + "sieve_preset_1": "Atmest e-pasta vēstules ar iespējami bīstamiem datņu veidiem", + "syncjob_last_run_result": "Pēdējās izpildes iznākums" }, "quarantine": { "action": "Darbības", "atts": "Pielikumi", - "check_hash": "Meklēt faila hašu @ VT", - "empty": "Nav rezultātu", + "check_hash": "Meklēt datnes jaucējvērtību @ VT", + "empty": "Nav iznākuma", "qid": "Rspamd QID", "qitem": "Karantīnas vienumi", "quarantine": "Karantīna", @@ -463,7 +476,7 @@ "received": "Saņemtie", "recipients": "Adresāts", "release": "Atbrīvot", - "release_body": "Šim ziņojumam mēs esam pievienojuši jūsu ziņojumu kā eml failu.", + "release_body": "Mēs pievienojām Tavu ziņojumu kā .eml datni šim ziņojumam.", "release_subject": "Potenciāli kaitīgs karantīnas vienums %s", "remove": "Noņemt", "sender": "Sūtītājs (SMTP)", @@ -473,8 +486,14 @@ "text_plain_content": "Saturs (teksts/vienkāršs)", "toggle_all": "Pārslēgt visu", "disabled_by_config": "Pašreizējā sistēmas konfigurācija atspējo karantīnu. Lūgums iestatīt \"saglabāšanu katrai pastkastītei\" un \"lielākais pieļaujamais lielums\" karantīnas vienumiem.", - "qhandler_success": "Pieprasījums veiksmīgi nosūtīts sistēmai. Tagad var aizvērt logu.", - "qinfo": "Karantīnas sistēma datubāzē saglabās noraidīto pastu (sūtītājam netiks radīts iespaids par piegādātu pastu), kā arī pastu, kas tiek piegādāts kā kopija pastkastes mēstuļu mapē.\n
\"Apgūt kā surogātpastu un izdzēst\" apgūs ziņojumu kā surogātpastu ar Bajesa teorēmu un aprēķinās arī nestriktas jaucējvērtības, lai nākotnē noraidītu līdzīgus ziņojumus.\n
Lūgums apzināties, ka vairāku ziņojumu apgūšana var būt laikietilpīga atkarībā no sistēmas.
Melnā saraksta vienumi karantīnā netiek iekļauti." + "qhandler_success": "Pieprasījums sekmīgi nosūtīts sistēmai. Logu tagad var aizvērt.", + "qinfo": "Karantīnas sistēma datubāzē saglabās noraidīto pastu (sūtītājam netiks radīts iespaids par piegādātu pastu), kā arī pastu, kas tiek piegādāts kā kopija pastkastes mēstuļu mapē.\n
\"Apgūt kā surogātpastu un izdzēst\" apgūs ziņojumu kā surogātpastu ar Bajesa teorēmu un aprēķinās arī nestriktas jaucējvērtības, lai nākotnē noraidītu līdzīgus ziņojumus.\n
Lūgums apzināties, ka vairāku ziņojumu apgūšana var būt laikietilpīga atkarībā no sistēmas.
Lieguma saraksta vienumi karantīnā netiek iekļauti.", + "danger": "Bīstamība", + "notified": "Paziņots", + "refresh": "Atsvaidzināt", + "rspamd_result": "Rspamd iznākums", + "settings_info": "Lielākais pieļaujamais karantējamo vienumu daudzums: %s
Lielākais pieļaujamais e-pasta lielums: %s MiB", + "spam_score": "Novērtējums" }, "queue": { "queue_manager": "Rindas pārvaldnieks", @@ -505,8 +524,8 @@ "f2b_modified": "Fail2ban parametru izmaiņas tika saglabātas", "forwarding_host_added": "Pāradresācijas hosts %s pievienotsd", "forwarding_host_removed": "Pāradresācijas hosts %s noņemts", - "item_deleted": "Vērtība %s veiksmīgi dzēsta", - "items_deleted": "Vērtība %s veiksmīgi dzēsta", + "item_deleted": "Vienums %s izdzēsts sekmīgi", + "items_deleted": "Vienums %s izdzēsts sekmīgi", "items_released": "Atlasītie vienumi tika izlaisti", "mailbox_added": "Pastkaste %s ir pievienota", "mailbox_modified": "Izmaiņas pastkastei %s ir saglabātas", @@ -519,20 +538,21 @@ "resource_modified": "Izmaiņas %s ir saglabātas", "resource_removed": "Resurs %s tika noņemts", "ui_texts": "Saglabāt UI izmaiņas tekstiem", - "upload_success": "Faila augšupielāde veiksmīga", + "upload_success": "Datne sekmīgi augšupielādēta", "verified_fido2_login": "Apliecināta FIDO2 pieteikšanās", "verified_webauthn_login": "Apliecināta WebAuthn pieteikšanās", "verified_totp_login": "Apliecināta TOTP pieteikšanās", "verified_yotp_login": "Apliecināta Yubico OTP pieteikšanās", "app_passwd_removed": "Noņemta lietotnes parole ar Id %s", - "app_passwd_added": "Pievienota jauna lietotnes parole" + "app_passwd_added": "Pievienota jauna lietotnes parole", + "f2b_banlist_refreshed": "Liegumu saraksta Id tika sekmīgi atsvaidzināts." }, "tfa": { "api_register": "%s izmanto Yubico Cloud API. Lūdzu iegūstiet API atslēgu priekš Jūsu atslēgashere", "confirm": "Apstiprināt", - "confirm_totp_token": "Lūdzu apstipriniet Jūsu izmaiņas ievadot uzģenerēto tekstu", + "confirm_totp_token": "Lūgums apstiprināt savas izmaiņas ar izveidotās tekstvienības ievadīšanu", "delete_tfa": "Atspējot TFA", - "disable_tfa": "Atspējot TFA līdz nākamajai veiksmīgajai pieteikšanās reizei", + "disable_tfa": "Atspējot TFA līdz nākamajai sekmīgajai pieteikšanās reizei", "enter_qr_code": "TOTP kods, ja Tava ierīce nevar nolasīt kvadrātkodus", "key_id": "Jūsu YubiKey identifikators", "key_id_totp": "Identifikators Jūsu atslēgai", @@ -544,7 +564,7 @@ "totp": "Uz laiku bāzēta vienreizēja parole (Google Autentifikātors utt.)", "webauthn": "WebAuthn autentifikācija", "waiting_usb_auth": "Gaida USB ierīci...

Lūdzu, tagad nospiežiet pogu uz Jūsu WebAuthn USB ierīces.", - "waiting_usb_register": "Gaida USB ierīci...

Lūdzu augšā ievadiet Jūsu paroli un apstipriniet WebAuthn reģistrāciju nospiežot pogu uz Jūsu WebAuthn USB ierīces.", + "waiting_usb_register": "Gaida USB ierīci...

Lūgums augstāk ievadīt savu paroli un apstiprināt reģistrēšanos ar USB ierīces pogas nospiešanu.", "yubi_otp": "Yubico OTP autentifikators", "authenticators": "Autentificētāji" }, @@ -589,7 +609,7 @@ "new_password_repeat": "Paroles apstiprinājums (atkārtoti)", "no_active_filter": "Nav pieejami aktīvi filtri", "no_record": "Nav ieraksta", - "password_now": "Pašreizējā parole (Apstiprināt izmaiņas)", + "password_now": "Pašreizējā parole (apstiprināt izmaiņas)", "remove": "Noņemt", "running": "Darbojas", "save_changes": "Saglabāt izmaiņas", @@ -599,11 +619,11 @@ "spam_aliases": "Pagaidu e-pasta aizstājvārdi", "spamfilter": "Mēstuļu filtrs", "spamfilter_behavior": "Reitings", - "spamfilter_bl": "Melnais saraksts", - "spamfilter_bl_desc": "No melnajā sarakstā iekļautajām e-pasta adresēm saņemtās vēstules vienmēr tiks atzīmētas kā mēstules un noraidītas. Noraidītais pasts netiks ievietots karantīnā. Var izmantot aizstājzīmes. Atlasīšana tiek pielietota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.", + "spamfilter_bl": "Liegumu saraksts", + "spamfilter_bl_desc": "No lieguma sarakstā iekļautajām e-pasta adresēm saņemtās vēstules vienmēr tiks atzīmētas kā mēstules un noraidītas. Noraidītais pasts netiks ievietots karantīnā. Var izmantot aizstājzīmes. Atlasīšana tiek pielietota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.", "spamfilter_default_score": "Noklusējuma vērtības", "spamfilter_green": "Zaļš: šī nav mēstule", - "spamfilter_hint": "Pirmā vērtība norāda uz zemu \"Spam vērtējumu\" vērtējumu, otra vērtība par \"Augstu spam vērtējumu\".", + "spamfilter_hint": "Pirmā vērtība norāda uz zemu \"mēstules novērtējumu\", otrā atspoguļo \"augstu mēstules novērtējumu\".", "spamfilter_red": "Sarkans: Šī vēstule noteikti ir spams un tiek nekavējoties noraidīta", "spamfilter_table_action": "Darbība", "spamfilter_table_add": "Pievienot vienību", @@ -611,8 +631,8 @@ "spamfilter_table_empty": "Nav datu ko parādīt", "spamfilter_table_remove": "noņemt", "spamfilter_table_rule": "Noteikums", - "spamfilter_wl": "Baltais saraksts", - "spamfilter_wl_desc": "No baltā saraksta e-pasta adresēm saņemtās vēstules nekad netiks atzīmētas kā mēstules. Var tikt izmantotas aizstājzīmes. Atlase tiek piemērota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.", + "spamfilter_wl": "Atļautais saraksts", + "spamfilter_wl_desc": "No atļautā saraksta e-pasta adresēm saņemtās vēstules nekad netiks atzīmētas kā mēstules. Var tikt izmantotas aizstājzīmes. Atlase tiek piemērota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.", "spamfilter_yellow": "Dzeltens: šī vēstule visticamāk ir spams un tiks pārvietota uz Junk mapi", "status": "Status", "sync_jobs": "Sinhronizācijas uzdevumi", @@ -644,15 +664,21 @@ "change_password_hint_app_passwords": "Kontā ir %d lietotņu paroles, kas netiks mainītas. Lai pārvaldītu tās, jādodas uz cilni \"Lietotņu paroles\".", "with_app_password": "ar lietotnes paroli", "apple_connection_profile_with_app_password": "Jauna lietotnes parole ir izveidota un pievienota profilam, lai ierīces iestatīšanas laikā nebūtu nepieciešams ievadīt paroli. Lūgums nekopīgot datni, jo tā nodrošina pilnu piekļuvi pastkastei.", - "tfa_info": "Divpakāpju autentificēšanās palīdz aizsargāt kontu.Ja tā ir iespējota, var būt nepieciešamas lietotņu paroles, lai pieteiktos lietotnēs vai pakalpojumos, kas nenodrošina divpakāpju autentificēšanos (piem., e-pasta klienti).", + "tfa_info": "Divpakāpju autentificēšanās palīdz aizsargāt kontu.Ja tā ir iespējota, ir nepieciešamas lietotņu paroles, lai pieteiktos lietotnēs vai pakalpojumos, kas nenodrošina divpakāpju autentificēšanos (piem., e-pasta klienti).", "app_passwds": "Lietotņu paroles", - "create_app_passwd": "Izveidot lietotnes paroli" + "create_app_passwd": "Izveidot lietotnes paroli", + "empty": "Nav iznākuma", + "quarantine_notification_info": "Tiklīdz paziņojums ir nosūtīts, vienumi tiks atzīmēti kā \"paziņoti\", un par šo vienumu vairs netiks sūtīti paziņojumi.", + "sender_acl_disabled": "Sūtītāja pārbaude ir atspējota", + "syncjob_last_run_result": "Pēdējās izpildes iznākums" }, "datatables": { "paginate": { "first": "Pirmā", "last": "Pēdējā" - } + }, + "emptyTable": "Tabulā nav datu", + "search": "Meklēt:" }, "debug": { "last_modified": "Pēdējoreiz mainīts", From 260906e3501048bb6909a0d8329926e17cf2377f Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:28:09 +0200 Subject: [PATCH 03/40] [SOGo][Web] Enable SOGo URL Encryption --- data/Dockerfiles/sogo/bootstrap-sogo.sh | 4 ++++ data/web/inc/triggers.user.inc.php | 4 ++-- data/web/sogo-auth.php | 5 +---- docker-compose.yml | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/data/Dockerfiles/sogo/bootstrap-sogo.sh b/data/Dockerfiles/sogo/bootstrap-sogo.sh index 96d8a6919..ad667fca6 100755 --- a/data/Dockerfiles/sogo/bootstrap-sogo.sh +++ b/data/Dockerfiles/sogo/bootstrap-sogo.sh @@ -50,6 +50,10 @@ cat < /var/lib/sogo/GNUstep/Defaults/sogod.plist YES SOGoEncryptionKey ${RAND_PASS} + SOGoURLEncryptionEnabled + YES + SOGoURLEncryptionPassphrase + ${RAND_PASS} OCSAdminURL mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_admin OCSCacheFolderURL diff --git a/data/web/inc/triggers.user.inc.php b/data/web/inc/triggers.user.inc.php index 4dee75a37..36176c694 100644 --- a/data/web/inc/triggers.user.inc.php +++ b/data/web/inc/triggers.user.inc.php @@ -80,7 +80,7 @@ if (isset($_POST["verify_tfa_login"])) { intval($user_details['attributes']['force_pw_update']) != 1 && getenv('SKIP_SOGO') != "y" && !$is_dual) { - header("Location: /SOGo/so/{$_SESSION['mailcow_cc_username']}"); + header("Location: /SOGo/so/"); die(); } else { header("Location: /user"); @@ -146,7 +146,7 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) { intval($user_details['attributes']['force_pw_update']) != 1 && getenv('SKIP_SOGO') != "y" && !$is_dual) { - header("Location: /SOGo/so/{$login_user}"); + header("Location: /SOGo/so/"); die(); } else { header("Location: /user"); diff --git a/data/web/sogo-auth.php b/data/web/sogo-auth.php index 00709fe5f..962627baf 100644 --- a/data/web/sogo-auth.php +++ b/data/web/sogo-auth.php @@ -64,7 +64,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/"); exit; } } @@ -81,10 +81,7 @@ elseif (isset($_SERVER['HTTP_X_ORIGINAL_URI']) && strcasecmp(substr($_SERVER['HT } require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php'; - // extract email address from "/SOGo/so/user@domain/xy" - $url_parts = explode("/", $_SERVER['HTTP_X_ORIGINAL_URI']); $email_list = array( - $url_parts[3], // Requested mailbox ($_SESSION['mailcow_cc_username'] ?? ''), // Current user ($_SESSION["dual-login"]["username"] ?? ''), // Dual login user ); diff --git a/docker-compose.yml b/docker-compose.yml index 215a196f9..eab49fd69 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -200,7 +200,7 @@ services: - phpfpm sogo-mailcow: - image: ghcr.io/mailcow/sogo:1.135 + image: ghcr.io/mailcow/sogo:1.136 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} From 610609378f2138aac35abd23db8063fdc63d7ef1 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:58:05 +0200 Subject: [PATCH 04/40] [SOGo][Web] Set URL encryption key in mailcow.conf --- _modules/scripts/new_options.sh | 11 ++++++----- data/Dockerfiles/sogo/bootstrap-sogo.sh | 2 +- docker-compose.yml | 1 + generate_config.sh | 4 ++++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/_modules/scripts/new_options.sh b/_modules/scripts/new_options.sh index a3f47dc61..30c747b70 100644 --- a/_modules/scripts/new_options.sh +++ b/_modules/scripts/new_options.sh @@ -43,6 +43,7 @@ adapt_new_options() { "ALLOW_ADMIN_EMAIL_LOGIN" "SKIP_HTTP_VERIFICATION" "SOGO_EXPIRE_SESSION" + "SOGO_URL_ENCRYPTION_KEY" "REDIS_PORT" "REDISPASS" "DOVECOT_MASTER_USER" @@ -94,7 +95,6 @@ adapt_new_options() { echo '# Max log lines per service to keep in Redis logs' >> mailcow.conf echo "LOG_LINES=9999" >> mailcow.conf ;; - IPV4_NETWORK) echo '# Internal IPv4 /24 subnet, format n.n.n. (expands to n.n.n.0/24)' >> mailcow.conf echo "IPV4_NETWORK=172.22.1" >> mailcow.conf @@ -276,21 +276,22 @@ adapt_new_options() { echo '# A COMPLETE DOCKER STACK REBUILD (compose down && compose up -d) IS NEEDED TO APPLY THIS.' >> mailcow.conf echo ENABLE_IPV6=${IPV6_BOOL} >> mailcow.conf ;; - SKIP_CLAMD) echo '# Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n' >> mailcow.conf echo 'SKIP_CLAMD=n' >> mailcow.conf ;; - SKIP_OLEFY) echo '# Skip Olefy (olefy-mailcow) anti-virus for Office documents (Rspamd will auto-detect a missing Olefy container) - y/n' >> mailcow.conf echo 'SKIP_OLEFY=n' >> mailcow.conf ;; - REDISPASS) echo "REDISPASS=$(LC_ALL=C /dev/null | head -c 28)" >> mailcow.conf ;; - + SOGO_URL_ENCRYPTION_KEY) + echo '# SOGo URL encryption key (exactly 16 characters, limited to A–Z, a–z, 0–9)' >> mailcow.conf + echo '# This key is used to encrypt email addresses within SOGo URLs' >> mailcow.conf + echo "SOGO_URL_ENCRYPTION_KEY=$(LC_ALL=C /dev/null | head -c 16)" >> mailcow.conf + ;; *) echo "${option}=" >> mailcow.conf ;; diff --git a/data/Dockerfiles/sogo/bootstrap-sogo.sh b/data/Dockerfiles/sogo/bootstrap-sogo.sh index ad667fca6..af7d2a4db 100755 --- a/data/Dockerfiles/sogo/bootstrap-sogo.sh +++ b/data/Dockerfiles/sogo/bootstrap-sogo.sh @@ -53,7 +53,7 @@ cat < /var/lib/sogo/GNUstep/Defaults/sogod.plist SOGoURLEncryptionEnabled YES SOGoURLEncryptionPassphrase - ${RAND_PASS} + ${SOGO_URL_ENCRYPTION_KEY} OCSAdminURL mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_admin OCSCacheFolderURL diff --git a/docker-compose.yml b/docker-compose.yml index eab49fd69..a0cf85e6a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -213,6 +213,7 @@ services: - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} - SOGO_EXPIRE_SESSION=${SOGO_EXPIRE_SESSION:-480} + - SOGO_URL_ENCRYPTION_KEY=${SOGO_URL_ENCRYPTION_KEY:-SOGoSuperSecret0} - SKIP_SOGO=${SKIP_SOGO:-n} - MASTER=${MASTER:-y} - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} diff --git a/generate_config.sh b/generate_config.sh index 2dba91d51..9a0bd132b 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -436,6 +436,10 @@ MAILDIR_SUB=Maildir # SOGo session timeout in minutes SOGO_EXPIRE_SESSION=480 +# SOGo URL encryption key (exactly 16 characters, limited to A–Z, a–z, 0–9) +# This key is used to encrypt email addresses within SOGo URLs +SOGO_URL_ENCRYPTION_KEY=$(LC_ALL=C /dev/null | head -c 16) + # DOVECOT_MASTER_USER and DOVECOT_MASTER_PASS must both be provided. No special chars. # Empty by default to auto-generate master user and password on start. # User expands to DOVECOT_MASTER_USER@mailcow.local From a36485f0f1fe7ac2599a7c49b3604282b0391d90 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Mon, 22 Sep 2025 13:55:18 +0200 Subject: [PATCH 05/40] [Web] Allow wildcard subdomains for MTA-STS --- data/web/inc/functions.inc.php | 12 +++++++++++- data/web/inc/functions.mailbox.inc.php | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 55329e73a..2631f1214 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -1107,11 +1107,21 @@ function user_get_alias_details($username) { } return $data; } -function is_valid_domain_name($domain_name) { +function is_valid_domain_name($domain_name, $options = array()) { if (empty($domain_name)) { return false; } + + // Convert domain name to ASCII for validation $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46); + + // Remove '*.' if wildcard subdomains are allowed + if (isset($options['allow_wildcard']) && + $options['allow_wildcard'] == true && + strpos($domain_name, '*.') === 0) { + $domain_name = substr($domain_name, 2); + } + return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) && preg_match("/^.{1,253}$/", $domain_name) && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)); diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index a0199fbdc..7638c9bbf 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1446,7 +1446,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } foreach ($mx as $index => $mx_domain) { $mx_domain = idn_to_ascii(strtolower(trim($mx_domain)), 0, INTL_IDNA_VARIANT_UTS46); - if (!is_valid_domain_name($mx_domain)) { + if (!is_valid_domain_name($mx_domain, array('allow_wildcard' => true))) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr), @@ -3897,7 +3897,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { foreach ($mx as $index => $mx_domain) { $mx_domain = idn_to_ascii(strtolower(trim($mx_domain)), 0, INTL_IDNA_VARIANT_UTS46); $invalid_mx = false; - if (!is_valid_domain_name($mx_domain)) { + if (!is_valid_domain_name($mx_domain, array('allow_wildcard' => true))) { $invalid_mx = $mx_domain; break; } From 4b2862cb3c2e8825620989aac42a735d16fe4313 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:07:17 +0200 Subject: [PATCH 06/40] [Web] Remove Port from HTTP_HOST --- data/web/mta-sts.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/web/mta-sts.php b/data/web/mta-sts.php index 51c39eb2f..650b8b583 100644 --- a/data/web/mta-sts.php +++ b/data/web/mta-sts.php @@ -6,7 +6,8 @@ if (!isset($_SERVER['HTTP_HOST']) || strpos($_SERVER['HTTP_HOST'], 'mta-sts.') ! exit; } -$domain = str_replace('mta-sts.', '', $_SERVER['HTTP_HOST']); +$host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']); +$domain = str_replace('mta-sts.', '', $host); $mta_sts = mailbox('get', 'mta_sts', $domain); if (count($mta_sts) == 0 || From 9940c503a2f9410cf802ed4a014699349c738099 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:16:42 +0200 Subject: [PATCH 07/40] [Nginx] do not invert ENABLE_IPV6 --- data/Dockerfiles/nginx/bootstrap.py | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/nginx/bootstrap.py b/data/Dockerfiles/nginx/bootstrap.py index d2d01c0b9..97ce7a4e1 100644 --- a/data/Dockerfiles/nginx/bootstrap.py +++ b/data/Dockerfiles/nginx/bootstrap.py @@ -10,7 +10,7 @@ def includes_conf(env, template_vars): server_name_config = f"server_name {template_vars['MAILCOW_HOSTNAME']} autodiscover.* autoconfig.* {' '.join(template_vars['ADDITIONAL_SERVER_NAMES'])};" listen_plain_config = f"listen {template_vars['HTTP_PORT']};" listen_ssl_config = f"listen {template_vars['HTTPS_PORT']};" - if not template_vars['ENABLE_IPV6']: + if template_vars['ENABLE_IPV6']: listen_plain_config += f"\nlisten [::]:{template_vars['HTTP_PORT']};" listen_ssl_config += f"\nlisten [::]:{template_vars['HTTPS_PORT']} ssl;" listen_ssl_config += "\nhttp2 on;" diff --git a/docker-compose.yml b/docker-compose.yml index a0cf85e6a..86a4f401a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -419,7 +419,7 @@ services: - php-fpm-mailcow - sogo-mailcow - rspamd-mailcow - image: ghcr.io/mailcow/nginx:1.04 + image: ghcr.io/mailcow/nginx:1.05 dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: From ed4dcff63b67366ca3974ec3b048bb2299d16c06 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:42:14 +0200 Subject: [PATCH 08/40] [Web] allow "*" as wildcard domain --- data/web/inc/functions.inc.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 2631f1214..bb2d35ea3 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -1115,11 +1115,15 @@ function is_valid_domain_name($domain_name, $options = array()) { // Convert domain name to ASCII for validation $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46); - // Remove '*.' if wildcard subdomains are allowed - if (isset($options['allow_wildcard']) && - $options['allow_wildcard'] == true && - strpos($domain_name, '*.') === 0) { - $domain_name = substr($domain_name, 2); + if (isset($options['allow_wildcard']) && $options['allow_wildcard'] == true) { + // Remove '*.' if wildcard domains are allowed + if (strpos($domain_name, '*.') === 0) { + $domain_name = substr($domain_name, 2); + } + // Allow '*' as wildcard domain + if ($domain_name === "*") { + return true; + } } return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) From 383b5affb52cd20a87cdfd6235df7e51d4ad31b1 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Mon, 22 Sep 2025 19:49:31 +0200 Subject: [PATCH 09/40] More clearer message to install required tool --- _modules/scripts/core.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/_modules/scripts/core.sh b/_modules/scripts/core.sh index f71368d24..e86c2afc9 100644 --- a/_modules/scripts/core.sh +++ b/_modules/scripts/core.sh @@ -17,7 +17,12 @@ caller="${BASH_SOURCE[1]##*/}" get_installed_tools(){ for bin in openssl curl docker git awk sha1sum grep cut jq; do - if [[ -z $(command -v ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi + if [[ -z $(command -v ${bin}) ]]; then + echo "Error: Cannot find command '${bin}'. Cannot proceed." + echo "Solution: Please install accordingly and re-run the script." + echo "Exiting..." + exit 1 + fi done if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo -e "${LIGHT_RED}BusyBox grep detected, please install gnu grep, \"apk add --no-cache --upgrade grep\"${NC}"; exit 1; fi @@ -221,4 +226,4 @@ detect_major_update() { fi fi fi -} \ No newline at end of file +} From f2c4697ca3df548c6f56b5d2bf686c78bba8c573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20=F0=9F=A6=84?= <43847817+codiflow@users.noreply.github.com> Date: Mon, 22 Sep 2025 23:45:54 +0200 Subject: [PATCH 10/40] Fixed typo in lang de-de (#6765) --- data/web/lang/lang.de-de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index b5f3f325d..dbc6b2f93 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -1100,7 +1100,7 @@ "legend": "Funktionen der Mailqueue Aktionen:", "ays": "Soll die derzeitige Queue wirklich komplett bereinigt werden?", "deliver_mail": "Ausliefern", - "deliver_mail_legend": "Versucht eine erneute Zustellung der ausgwählten Mails.", + "deliver_mail_legend": "Versucht eine erneute Zustellung der ausgewählten Mails.", "hold_mail": "Zurückhalten", "hold_mail_legend": "Hält die ausgewählten Mails zurück. (Verhindert weitere Zustellversuche)", "queue_manager": "Queue Manager", From 28985973eb746ea5486aa5377fd426ce7a5f5ab1 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Tue, 23 Sep 2025 10:07:33 +0200 Subject: [PATCH 11/40] [Web] Revert - allow "*" as wildcard domain --- data/web/inc/functions.inc.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index bb2d35ea3..5ac72ed24 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -1116,14 +1116,10 @@ function is_valid_domain_name($domain_name, $options = array()) { $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46); if (isset($options['allow_wildcard']) && $options['allow_wildcard'] == true) { - // Remove '*.' if wildcard domains are allowed + // Remove '*.' if wildcard subdomains are allowed if (strpos($domain_name, '*.') === 0) { $domain_name = substr($domain_name, 2); } - // Allow '*' as wildcard domain - if ($domain_name === "*") { - return true; - } } return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) From 4440bd46adc73cd9be69f5f5716dbec4c92c7b73 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Tue, 23 Sep 2025 12:24:25 +0200 Subject: [PATCH 12/40] [Web] set cookie SameSite attribute to Lax --- data/web/inc/sessions.inc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/data/web/inc/sessions.inc.php b/data/web/inc/sessions.inc.php index bbc08cf13..1bb29d410 100644 --- a/data/web/inc/sessions.inc.php +++ b/data/web/inc/sessions.inc.php @@ -2,6 +2,7 @@ // Start session if (session_status() !== PHP_SESSION_ACTIVE) { ini_set("session.cookie_httponly", 1); + ini_set("session.cookie_samesite", "Lax"); ini_set('session.gc_maxlifetime', $SESSION_LIFETIME); } From 8ead77083ff5ac58ab640f9fa9a8d58fec10b617 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Tue, 23 Sep 2025 12:39:48 +0200 Subject: [PATCH 13/40] [Web] Rename PHP Cookie to MCSESSID --- data/web/inc/sessions.inc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/data/web/inc/sessions.inc.php b/data/web/inc/sessions.inc.php index 1bb29d410..68b3d5585 100644 --- a/data/web/inc/sessions.inc.php +++ b/data/web/inc/sessions.inc.php @@ -1,6 +1,7 @@ Date: Wed, 24 Sep 2025 17:36:09 +0200 Subject: [PATCH 14/40] [Web] Updated lang.si-si.json (#6771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matjaž Tekavec --- data/web/lang/lang.si-si.json | 108 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index 95e23a5cb..0b6626127 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -42,7 +42,7 @@ "app_name": "Ime aplikacije", "app_password": "Dodaj geslo aplikacije", "app_passwd_protocols": "Dovoljeni protokoli za geslo aplikacije", - "automap": "Poskusi samodejno preslikati mape (\"Sent items\", \"Sent\" => \"Poslano\" ipd.)", + "automap": "Poskusi samodejno preslikati mape (\"Poslani elementi\", \"Poslano\" => \"Poslano\" ipd.)", "backup_mx_options": "Možnosti posredovanja (relay)", "comment_info": "Zasebni komentarji niso vidni uporabnikom, javni komentarji pa so prikazani kot opis, ko se z miško postavimo nad uporabnika v pregledu", "custom_params": "Parametri po meri", @@ -152,7 +152,7 @@ "customize": "Prilagodi", "destination": "Cilj", "dkim_add_key": "Dodaj ARC/DKIM ključ", - "dkim_domains_selector": "Izbira", + "dkim_domains_selector": "Izbirnik", "dkim_domains_wo_keys": "Izberi domene z manjkajočimi ključi", "dkim_from": "Od", "dkim_from_title": "Izvorna domena od katere prekopiram podatke", @@ -178,8 +178,8 @@ "f2b_filter": "Regex filtri", "f2b_max_attempts": "Največ poskusov", "f2b_max_ban_time": "Maksimalno trajanje blokade (s)", - "f2b_netban_ipv4": "velikost subneta IPv4 za blokiranje (8-32)", - "f2b_netban_ipv6": "Velikost subneta IPv6 za blokiranje (8-128)", + "f2b_netban_ipv4": "velikost podomrežja IPv4 za blokiranje (8-32)", + "f2b_netban_ipv6": "Velikost podomrežja IPv6 za blokiranje (8-128)", "f2b_parameters": "Fail2ban parametri", "f2b_regex_info": "Upoštevajo se dnevniki SOGo, Postfix, Dovecot, PHP-FPM.", "f2b_retry_window": "Upoštevan čas (s) za največ poskusov", @@ -189,41 +189,41 @@ "generate": "ustvari", "guid": "GUID - enolični ID instance", "guid_and_license": "GUID & licenca", - "hash_remove_info": "Odstranitev hasha za omejitev (če obstaja) bo povsem ponastavilo njen števec.
\n Vsak hash je prikazan z individualno barvo.", - "help_text": "Zamenjaj tekst za pomoč pod masko za prijavo (HTML je dovoljen)", + "hash_remove_info": "Odstranitev zgoščene vrednosti za omejitev (če obstaja) bo povsem ponastavilo njen števec.
\n Vsaka zgoščena vrednost je prikazana z individualno barvo.", + "help_text": "Preglasi besedilo za pomoč pod masko za prijavo (HTML je dovoljen)", "host": "Gostitelj", "html": "HTML", "import": "Uvozi", "import_private_key": "Uvozi zasebni ključ", - "in_use_by": "V uporabi", + "in_use_by": "V uporabi od", "inactive": "Neaktivno", "include_exclude": "Vključi/Izključi", "include_exclude_info": "Privzeto - če ni izbire - so vključeni vsi poštni predali", "includes": "Vključi te prejemnike", - "ip_check": "Kontrola IP", - "ip_check_disabled": "Kontrola IP je onemogočena. Lahko jo omogočite pod
Sistem > Konfiguracija > Možnosti > Prilagodi", - "ip_check_opt_in": "Opt-in za uporabo zunanje storitve ipv4.mailcow.email in ipv6.mailcow.email za razreševanje zunanjih IP.", - "is_mx_based": "Glede na MX", - "last_applied": "Nazadnje aplicirano", + "ip_check": "Preverjanje IP-ja", + "ip_check_disabled": "Preverjanje IP-ja je onemogočeno. Lahko ga omogočite pod
Sistem > Konfiguracija > Možnosti > Prilagodi", + "ip_check_opt_in": "Prijavite se za uporabo storitev tretjih oseb ipv4.mailcow.email in ipv6.mailcow.email za razreševanje zunanjih IP naslovov.", + "is_mx_based": "Glede na MX zapis", + "last_applied": "Nazadnje uporabljeno", "link": "Povezava", "loading": "Prosim počakajte...", "login_time": "Čas prijave", - "logo_info": "Vaša slika bo pomanjšana na velikost 40px za zgornjo navigacijo in največjo velikost 250px za začetno stran. Zelo priporočena je uporaba grafike brez izgube kakovosti ob spremembi velikosti.", + "logo_info": "Vaša slika bo pomanjšana na višino 40 slikovnih pik za zgornjo navigacijsko vrstico in na največjo širino 250 slikovnih pik za začetno stran. Zelo priporočljiva je skalabilna grafika.", "message": "Sporočilo", "message_size": "Velikost sporočila", "nexthop": "Naslednji skok", "no": "✕", "no_active_bans": "Ni aktivnih blokad", - "no_new_rows": "Ni dodatnih vrstic", + "no_new_rows": "Nadaljnjih vrstic ni na voljo", "no_record": "Ni zapisa", "oauth2_apps": "OAuth2 aplikacije", "oauth2_add_client": "Dodaj OAuth2 klienta", - "oauth2_client_id": "ID klienta", - "oauth2_client_secret": "Skrivnost (secret)", + "oauth2_client_id": "ID odjemalca", + "oauth2_client_secret": "Skrivnost odjemalca", "oauth2_redirect_uri": "URI za preusmeritev", - "oauth2_renew_secret": "Generiraj nov client secret", - "oauth2_revoke_tokens": "Zavrni vse tokene klientov", - "optional": "opcijsko", + "oauth2_renew_secret": "Generiraj novo skrivnost odjemalca", + "oauth2_revoke_tokens": "Prekliči vse žetone odjemalca", + "optional": "neobvezno", "options": "Možnosti", "password": "Geslo", "password_length": "Dolžina gesla", @@ -238,21 +238,21 @@ "private_key": "Zasebni ključ", "quarantine": "Karantena", "quarantine_bcc": "Pošlji kopijo vseh obvestil (BCC) temu prejemniku:
Pustite prazno za izklop te funkcije. Nepodpisana, nepreverjena pošta. Uporabljalo naj bi se samo za interno dostavo.", - "quarantine_exclude_domains": "Izključi domene in alias-domene", - "quarantine_max_age": "Maksimalna starost v dnevnih
Vrednost mora biti večja ali enaka 1 dnevu", - "quarantine_max_score": "Opusti obvestilo, če je ocena spama večja od te vrednosti:
Privzeto 9999.0", - "quarantine_max_size": "Največja velikost v MiB (Večji elementi so zavrženi):
0 ne pomeni neomejeno.", - "quarantine_notification_html": "Predloga sporočila za obvestilo:
Pustite prazno za obnovitev privzete predloge.", - "quarantine_notification_sender": "Pošiljatelj obvestila", - "quarantine_notification_subject": "Naslov obvestila", - "quarantine_release_format": "Oblika sproščenih elementov", + "quarantine_exclude_domains": "Izključi domene in vzdevke domen", + "quarantine_max_age": "Najvišja starost v dneh
Vrednost mora biti enaka ali večja od 1 dneva.", + "quarantine_max_score": "Zavrzi obvestilo, če je ocena neželene pošte višja od te vrednosti:
Privzeto 9999,0", + "quarantine_max_size": "Največja velikost v MiB (večji elementi so zavrženi):
0 ne pomeni neomejeno.", + "quarantine_notification_html": "Predloga za obvestilo po e-pošti:
Pustite prazno, če želite obnoviti privzeto predlogo.", + "quarantine_notification_sender": "Pošiljatelj obvestil po e-pošti", + "quarantine_notification_subject": "Zadeva e-poštnega obvestila", + "quarantine_release_format": "Oblika izdanih elementov", "quarantine_release_format_att": "Kot priponka", - "quarantine_release_format_raw": "Nespremenjen original", - "quarantine_retention_size": "Število zadržanj na poštni predal:
0 pomeni neaktivno,", + "quarantine_release_format_raw": "Nespremenjen izvirnik", + "quarantine_retention_size": "Hrambe na poštni predal:
0 pomeni neaktivno.", "quota_notification_sender": "Pošiljatelj obvestila", "quota_notification_subject": "Predmet obvestila", - "quota_notifications": "Obvestila o omejitvi", - "quota_notifications_info": "Obvestila o omejitvi so poslana uporabnikom enkrat, ko presežejo 80% in enkrat ko presežejo 95% zasedenosti.", + "quota_notifications": "Obvestila o kvotah", + "quota_notifications_info": "Obvestila o kvoti se uporabnikom pošljejo enkrat, ko presežejo 80 % in enkrat, ko presežejo 95 % porabe.", "queue_unban": "odblokiraj", "r_active": "Aktivne omejitve", "r_inactive": "Neaktivne omejitve", @@ -268,8 +268,8 @@ "remove": "Odstrani", "remove_row": "Odstrani vrstico", "reset_default": "Ponastavi na privzeto", - "reset_limit": "Odstrani hash", - "routing": "Routing", + "reset_limit": "Odstrani zgoščeno vrednost", + "routing": "Usmerjanje", "rsetting_add_rule": "Dodaj pravilo", "rsetting_content": "Vsebina pravila", "rsetting_desc": "Kratek opis", @@ -277,10 +277,10 @@ "rsetting_none": "Ni pravil na voljo", "rsettings_insert_preset": "Vstavi prednastavljen primer \"%s\"", "rsettings_preset_1": "Onemogoči vse razen DKIM in omejitve za prijavljene uporabnike", - "rsettings_preset_2": "Postmasterji želijo spam", - "rsettings_preset_3": "Dovoli samo specifične pošiljatelje za poštni predal (npr. uporaba samo kot interni poštni predal)", + "rsettings_preset_2": "Poštni upravitelji želijo neželeno pošto", + "rsettings_preset_3": "Dovoli samo določene pošiljatelje za poštni predal (tj. uporabo samo kot notranji poštni predal)", "rsettings_preset_4": "Onemogoči Rspamd za domeno", - "rspamd_com_settings": "Ime nastavitve bo samodejno generirano. Prosim oglejte si primere nastavitev spodaj. Za več informacij si oglejte dokumentacijo Rspamd", + "rspamd_com_settings": "Ime nastavitve bo samodejno ustvarjeno, oglejte si spodnje primere prednastavitev. Za več podrobnosti glejte dokumentacijo Rspamd", "rspamd_global_filters": "Globalne preslikave filtrov", "rspamd_global_filters_agree": "Previden bom!", "rspamd_global_filters_info": "Globalni filtri vsebujejo različne vrste globalnih seznamov zavrnjenih in dovoljenih vsebin.", @@ -295,30 +295,30 @@ "f2b_list_info": "Gostitelj ali omrežje na seznamu zavrnjenih bo vedno imelo prednost pred entiteto na seznamu dovoljenih. Posodobitve seznama bodo trajale nekaj sekund, da se uporabijo.", "forwarding_hosts": "Gostitelji za posredovanje", "forwarding_hosts_add_hint": "Lahko vpišete IPv4/IPv6 naslove, mreže v CIDR obliki, imena gostiteljev (kateri se prevedejo v IP naslove) ali imena domen (katera se prevedejo v IP naslove glede na poizvedbo po SPF zapisih, v primeru manjkajočih zapisov pa MX zapisih).", - "forwarding_hosts_hint": "Dohodna sporočila so brezpogojno sprejeta od katerih koli gostiteljev v tem seznamu. Ti gostitelji se ne bodo preverjali po DNSBL seznamih in ne bodo dodani v greyliste. Prejeti spam s teh gostiteljev ni nikoli zavrnjen, opcijsko pa se lahko premakne v mapo neželene pošte. Najpogostejša uporaba za to je navedba poštnih strežnikov, iz katerih ste nastavili pravilo za posredovanje pošte na vaš mailcow strežnik.", - "license_info": "Licenca ni zahtevana, a pomaga pri nadaljnjem razvoju.
Registrirajte svoj GUID tukaj ali Kupite podporo za svojo namestitev Mailcow.", - "lookup_mx": "Cilj je regular expression za ujemanje MX zapisov (.*\\.google\\.com za usmeritev vse pošte na MX, ki se konča z google.com, preko tega skoka)", + "forwarding_hosts_hint": "Dohodna sporočila so brezpogojno sprejeta od katerih koli gostiteljev v tem seznamu. Ti gostitelji se ne bodo preverjali po DNSBL seznamih in ne bodo dodani v listo sivih. Prejeta neželena pošta s teh gostiteljev ni nikoli zavrnjena, opcijsko pa se lahko premakne v mapo neželene pošte. Najpogostejša uporaba za to je navedba poštnih strežnikov, iz katerih ste nastavili pravilo za posredovanje pošte na vaš mailcow strežnik.", + "license_info": "Licenca ni zahtevana, a pomaga pri nadaljnjem razvoju.
Registrirajte svoj GUID tukaj ali Kupite podporo za svojo namestitev Mailcow.", + "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (.*\\.google\\.com za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka).", "main_name": "Naziv \"mailcow UI\"", "merged_vars_hint": "Sive vrstice so združene iz vars.(local.)inc.php in jih ni mogoče spremeniti.", - "oauth2_info": "OAuth2 implementacija omogoča grant vrste \"Authorization code\" in izdaja refresh tokene.
\nStrežnik prav tako izda nove refresh tokene, ko je bil refresh token uporabljen

\n• Privzeti obseg je profile. Samo uporabniki poštnih predalov se lahko prijavijo s pomočjo OAuth2. Če parameter obsega ni vnesen, se nastavi na profile.
\n• Parameter state mora biti poslan s strani klienta kot del zahtevka za avtorizacijo .

\nPoti za OAuth2 API:
\n
    \n
  • Endpoint za avtorizacijo: /oauth/authorize
  • \n
  • Endpoint za tokene: /oauth/token
  • \n
  • Stran vira: /oauth/profile
  • \n
\nPonovno generiranje client secret ne bo razveljavilo obstoječih avtorizacijskih kod, ne bodo pa mogle obnoviti svoje tokene.

\nZavrnitev client tokenov bo povzročilo tekojčno prekinitev aktivnih sej. Vsi klienti se bodo morali ponovno prijaviti.", - "quarantine_redirect": "Preusmeri vsa obvestila k temu prejemniku:
Pustite prazno, da onemogočite. Nepodpisana, nepreverjena pošta. Uporabljalo bi se naj samo za interno dostavo.", + "oauth2_info": "Implementacija OAuth2 podpira vrsto odobritve »Avtorizacijska koda« in izda osvežilne žetone.
\nStrežnik samodejno izda tudi nove osvežilne žetone, ko je žeton za osvežitev uporabljen.

\n• Privzeti obseg je profile. Prek OAuth2 je mogoče overiti samo uporabnike poštnega predala. Če parameter obsega izpustite, se vrne na profile.
\n• Parameter state mora odjemalec poslati kot del zahteve za avtorizacijo.

\nPoti za zahteve do API-ja OAuth2:
\n
    \n
  • Končna točka avtorizacije: /oauth/authorize
  • \n
  • Končna točka žetona: /oauth/token
  • \n
  • Stran z viri: /oauth/profile
  • \n
\nPonovno ustvarjanje skrivnosti odjemalca ne bo poteklo obstoječih kod za avtorizacijo, vendar ne bo obnovilo žetona.

\nPreklic žetonov odjemalca bo povzročil takojšnjo prekinitev vseh aktivnih sej. Vse stranke se morajo ponovno overiti.", + "quarantine_redirect": "Preusmerite vsa obvestila temu prejemniku:
Pustite prazno, če želite onemogočiti. Nepodpisana, nepreverjena pošta. Dostavljeno samo interno.", "quota_notification_html": "Predloga sporočila za obvestilo:
Pustite prazno za obnovitev privzete predloge.", - "quota_notifications_vars": "{{percent}} pomeni trenutna omejitev uporabnika
{{username}} je ime poštnega predala", - "r_info": "Sivi/onemogočeni elementi v seznamu aktivnih omejitev niso znane kot veljavne omejitve za mailcow in ne morejo biti premaknjene. Neznane omejitve bodo kljub temu nastavljene po vrstnem redu pojavitve.
Nove elemente lahko dodate v inc/vars.local.inc.php da jih lahko vklopite ali izklopite.", - "relayhosts_hint": "Določite transporte glede na pošiljatelja, da jih lahko izberete v konfiguraciji domene.
\nTransportni servis je vedno \"smtp:\" in bo poskušal s TLS ko bo na voljo. Wrapped TLS (SMTPS) ni podprto. Upošteva se uporabnikova politika odhodnega TLS.
\nVpliva na izbrane domene vključno z alias domenami.", - "transport_dest_format": "Regex ali sintaksa: example.org, .example.org, *, box@example.org (več vrednosti ločite z vejico)", - "transport_test_rcpt_info": "• Uporabite null@hosted.mailcow.de za testiranje relaya na drugo destinacijo.", - "rspamd_global_filters_regex": "Njihovi nazivi pojasnijo njihov namen. Vsa vsebina mora imeti veljaven regular expression v obliki \"/pattern/options\" (npr. /.+@domain\\.tld/i).
\nČeprav se v vsaki vrstici regexa izvedejo osnovni pregledi, je lahko funkcionalnost programa Rspamd motena, če sintaksa ni pravilna.
\nRspamd bo poskušal prebrati vsebino preslikave, ko bo spremenjena. Če imate težave, ponovno zaženite Rspamd, da prisilite ponovno nalaganje preslikav.
Elementi na seznamu zavrnjenih so izključeni iz karantene.", + "quota_notifications_vars": "{{percent}} je enako trenutni kvoti uporabnika
{{username}} je ime poštnega predala", + "r_info": "Sivi/onemogočeni elementi v seznamu aktivnih omejitev niso znane kot veljavne omejitve za mailcow in ne morejo biti premaknjene. Neznane omejitve bodo kljub temu nastavljene po vrstnem redu pojavljanja.
Nove elemente lahko dodate v inc/vars.local.inc.php da jih lahko vklopite ali izklopite.", + "relayhosts_hint": "Določite transporte, odvisne od pošiljatelja, da jih boste lahko izbrali v pogovornem oknu za konfiguracijo domen.
\n Transportna storitev je vedno »smtp:« in bo zato poskusila s TLS, ko bo ponujena. Zaviti TLS (SMTPS) ni podprt. Upošteva se individualna nastavitev pravilnika za odhodni TLS uporabnika.
\n Vpliva na izbrane domene, vključno z vzdevki domen.", + "transport_dest_format": "Regex ali sintaksa: example.org, .example.org, *, box@example.org (več vrednosti je lahko ločenih z vejicami)", + "transport_test_rcpt_info": "• Za preizkus posredovanja v tujino uporabite null@hosted.mailcow.de.", + "rspamd_global_filters_regex": "Njihova imena pojasnjujejo njihov namen. Vsa vsebina mora vsebovati veljaven regularni izraz v obliki »/vzorec/možnosti« (npr. /.+@domena\\.tld/i).
\n Čeprav se v vsaki vrstici regularnega izraza izvajajo osnovna preverjanja, je lahko funkcionalnost Rspamdsa pokvarjena, če sintakse ne prebere pravilno.
\n Rspamd bo poskušal prebrati vsebino zemljevida, ko se bo spremenila. Če pride do težav, znova zaženite Rspamd, da uveljavite ponovno nalaganje zemljevida.
Elementi na seznamu zavrnjenih so izključeni iz karantene.", "rspamd_settings_map": "Preslikava nastavitev Rspamd", "sal_level": "Moo stopnja", "save": "Shrani spremembe", "search_domain_da": "Išči domene", "send": "Pošlji", "sender": "Pošiljatelj", - "service": "Servis", - "service_id": "ID servisa", + "service": "Storitev", + "service_id": "ID storitve", "source": "Vir", - "spamfilter": "Spam filter", + "spamfilter": "Filter neželene pošte", "subject": "Predmet", "success": "Uspešno", "sys_mails": "Sistemska pošta", @@ -328,7 +328,7 @@ "title_name": "Naziv spletnega mesta \"mailcow UI\"", "to_top": "Nazaj na vrh", "transport_maps": "Preslikave transportov", - "transports_hint": "• Vpis preslikave transporta nadredi preslikavo transporta odvisno od pošiljatelja.
\n• Preferenčno se uporabljajo transporti glede na MX zapise.
\n• Izhodne TLS politike na uporabnika so ignorirane in se lahko vsilijo samo s preslikavami TLS politik.
\n• Transportni servis za definirane transporte je vedno \"smtp:\" in bo posledično poskušal TLS ko bo ponujeno. Wrapped TLS (SMTPS) ni podprto.
\n• Naslovi, ki se ujemajo z \"/localhost$/\" bodo vedno preneseni preko \"local:\", in zato destinacija \"*\" ne bo vplivala na te naslove.
\n• Za določitev poverilnic za naslednji skok (npr. \"[host]:25\"), Postfix vedno preveri \"host\" preden išče \"[host]:25\". Zaradi takšnega obnašanja je nemogoče hkrati uporabiti \"host\" in \"[host]:25\".", + "transports_hint": "• Vnos preslikave transporta preglasi preslikavo transporta, ki je odvisen od pošiljatelja.
\n• Po možnosti se uporabljajo transporti, ki temeljijo na MX.
\n• Nastavitve pravilnika TLS za odhodne uporabnike se prezrejo in jih je mogoče uveljaviti le z vnosi v zemljevidu pravilnika TLS.
\n• Storitev transporta za definirane transporte je vedno »smtp:« in bo zato poskusila s TLS, ko bo ponujena. Zaviti TLS (SMTPS) ni podprt.
\n• Naslovi, ki se ujemajo z \"/localhost$/\" bodo vedno preneseni preko \"local:\", in zato cilj \"*\" ne bo veljal za te naslove.
\n• Za določitev poverilnic za zgledni naslednji skok \"[host]:25\", Postfix vedno poišče \"host\" preden poišče \"[host]:25\". Zaradi tega vedenja je nemogoče hkrati uporabljati \"host\" in \"[host]:25\".", "ui_footer": "Noga (HTML dovoljen)", "ui_header_announcement": "Obvestila", "ui_header_announcement_active": "Nastavi obvestilo kot aktivno", @@ -340,7 +340,7 @@ "ui_header_announcement_type_info": "Info", "ui_header_announcement_type_warning": "Pomembno", "ui_texts": "Oznake in besedila UI", - "unban_pending": "unban v postopku", + "unban_pending": "odblokada v teku", "unchanged_if_empty": "Če je nespremenjeno, pustite prazno", "upload": "Naloži", "username": "Uporabniško ime", @@ -395,7 +395,7 @@ "iam_token_url": "Končna točka žetona", "iam_userinfo_url": "Končna točka z uporabniškimi podatki", "iam_username_field": "Polje z uporabniškim imenom", - "iam_binddn": "Povezava DN", + "iam_binddn": "Vezava DN", "iam_use_ssl": "Uporabi SSL", "iam_use_tls": "Uporabi StartTLS", "iam_version": "Različica", @@ -559,7 +559,7 @@ "version_invalid": "Različica %s je neveljavna" }, "debug": { - "containers_info": "Informacije o vsebniku (containerju)", + "containers_info": "Informacije o zabojniku", "architecture": "Arhitektura", "chart_this_server": "Diagram (ta strežnik)", "container_running": "Aktiven", From c915bf2ee20aa54482b2701f0e8220ea02f14ebe Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Wed, 24 Sep 2025 19:06:47 +0200 Subject: [PATCH 15/40] Add docs link to get_installed_tools() message --- _modules/scripts/core.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_modules/scripts/core.sh b/_modules/scripts/core.sh index e86c2afc9..f776c6212 100644 --- a/_modules/scripts/core.sh +++ b/_modules/scripts/core.sh @@ -19,7 +19,8 @@ get_installed_tools(){ for bin in openssl curl docker git awk sha1sum grep cut jq; do if [[ -z $(command -v ${bin}) ]]; then echo "Error: Cannot find command '${bin}'. Cannot proceed." - echo "Solution: Please install accordingly and re-run the script." + echo "Solution: Please review system requirements and install requirements. Then, re-run the script." + echo "See System Requirements: https://docs.mailcow.email/getstarted/install/" echo "Exiting..." exit 1 fi From 7028619742d2f8c962e7fcef269936511fdc7eb9 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Wed, 24 Sep 2025 21:17:29 +0200 Subject: [PATCH 16/40] Update GitHub's issue template --- .github/ISSUE_TEMPLATE/Bug_report.yml | 77 ++++++++++++++------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.yml b/.github/ISSUE_TEMPLATE/Bug_report.yml index afa1a27f8..df2acdb6b 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_report.yml @@ -11,22 +11,35 @@ body: required: true - type: checkboxes attributes: - label: I've found a bug and checked that ... - description: Prior to placing the issue, please check following:** *(fill out each checkbox with an `X` once done)* + label: Checklist prior issue creation + description: Prior to creating the issue... options: - - label: ... I understand that not following the below instructions will result in immediate closure and/or deletion of my issue. - required: true - - label: ... I have understood that this bug report is dedicated for bugs, and not for support-related inquiries. - required: true - - label: ... I have understood that answers are voluntary and community-driven, and not commercial support. - required: true - - label: ... I have verified that my issue has not been already answered in the past. I also checked previous [issues](https://github.com/mailcow/mailcow-dockerized/issues). - required: true + - label: I understand that failure to follow below instructions may cause this issue to be closed. + required: true + - label: I understand that vague, incomplete or inaccurate information may cause this issue to be closed. + required: true + - label: I understand that this form is intended solely for reporting software bugs and not for support-related inquiries. + required: true + - label: I understand that all responses are voluntary and community-driven, and do not constitute commercial support. + required: true + - label: I confirm that I have reviewed previous [issues](https://github.com/mailcow/mailcow-dockerized/issues) to ensure this matter has not already been addressed. + required: true + - label: I confirm that my environment meets all [prerequisite requirements](https://docs.mailcow.email/getstarted/prerequisite-system/) as specified in the official documentation. + required: true - type: textarea attributes: label: Description - description: Please provide a brief description of the bug in 1-2 sentences. If applicable, add screenshots to help explain your problem. Very useful for bugs in mailcow UI. - render: plain text + description: Please provide a brief description of the bug. If applicable, add screenshots to help explain your problem. (Very useful for bugs in mailcow UI.) + validations: + required: true + - type: textarea + attributes: + label: "Steps to reproduce:" + description: "Please describe the steps to reproduce the bug. Screenshots can be added, if helpful." + placeholder: |- + 1. ... + 2. ... + 3. ... validations: required: true - type: textarea @@ -36,45 +49,36 @@ body: render: plain text validations: required: true - - type: textarea - attributes: - label: "Steps to reproduce:" - description: "Please describe the steps to reproduce the bug. Screenshots can be added, if helpful." - render: plain text - placeholder: |- - 1. ... - 2. ... - 3. ... - validations: - required: true - type: markdown attributes: value: | ## System information - ### In this stage we would kindly ask you to attach general system information about your setup. + In this stage we would kindly ask you to attach general system information about your setup. - type: dropdown attributes: label: "Which branch are you using?" - description: "#### `git rev-parse --abbrev-ref HEAD`" + description: "#### Run: `git rev-parse --abbrev-ref HEAD`" multiple: false options: - - master + - master (stable) + - staging - nightly validations: required: true - type: dropdown attributes: label: "Which architecture are you using?" - description: "#### `uname -m`" + description: "#### Run: `uname -m`" multiple: false options: - - x86 + - x86_64 - ARM64 (aarch64) validations: required: true - type: input attributes: label: "Operating System:" + description: "#### Run: `lsb_release -ds`" placeholder: "e.g. Ubuntu 22.04 LTS" validations: required: true @@ -93,43 +97,44 @@ body: - type: input attributes: label: "Virtualization technology:" - placeholder: "KVM, VMware, Xen, etc - **LXC and OpenVZ are not supported**" + description: "LXC and OpenVZ are not supported!" + placeholder: "KVM, VMware ESXi, Xen, etc" validations: required: true - type: input attributes: label: "Docker version:" - description: "#### `docker version`" + description: "#### Run: `docker version`" placeholder: "20.10.21" validations: required: true - type: input attributes: label: "docker-compose version or docker compose version:" - description: "#### `docker-compose version` or `docker compose version`" + description: "#### Run: `docker-compose version` or `docker compose version`" placeholder: "v2.12.2" validations: required: true - type: input attributes: label: "mailcow version:" - description: "#### ```git describe --tags `git rev-list --tags --max-count=1` ```" - placeholder: "2022-08" + description: "#### Run: ```git describe --tags `git rev-list --tags --max-count=1` ```" + placeholder: "2022-08x" validations: required: true - type: input attributes: label: "Reverse proxy:" - placeholder: "e.g. Nginx/Traefik" + placeholder: "e.g. nginx/Traefik, or none" validations: required: true - type: textarea attributes: label: "Logs of git diff:" - description: "#### Output of `git diff origin/master`, any other changes to the code? If so, **please post them**:" + description: "#### Output of `git diff origin/master`, any other changes to the code? Sanitize if needed. If so, **please post them**:" render: plain text validations: - required: true + required: false - type: textarea attributes: label: "Logs of iptables -L -vn:" From eabd22188b8c58fec533ef815fca59ddd676c121 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Wed, 24 Sep 2025 21:20:48 +0200 Subject: [PATCH 17/40] Re-intend checkboxes --- .github/ISSUE_TEMPLATE/Bug_report.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.yml b/.github/ISSUE_TEMPLATE/Bug_report.yml index df2acdb6b..f6fb7d280 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_report.yml @@ -14,18 +14,18 @@ body: label: Checklist prior issue creation description: Prior to creating the issue... options: - - label: I understand that failure to follow below instructions may cause this issue to be closed. - required: true - - label: I understand that vague, incomplete or inaccurate information may cause this issue to be closed. - required: true - - label: I understand that this form is intended solely for reporting software bugs and not for support-related inquiries. - required: true - - label: I understand that all responses are voluntary and community-driven, and do not constitute commercial support. - required: true - - label: I confirm that I have reviewed previous [issues](https://github.com/mailcow/mailcow-dockerized/issues) to ensure this matter has not already been addressed. - required: true - - label: I confirm that my environment meets all [prerequisite requirements](https://docs.mailcow.email/getstarted/prerequisite-system/) as specified in the official documentation. - required: true + - label: I understand that failure to follow below instructions may cause this issue to be closed. + required: true + - label: I understand that vague, incomplete or inaccurate information may cause this issue to be closed. + required: true + - label: I understand that this form is intended solely for reporting software bugs and not for support-related inquiries. + required: true + - label: I understand that all responses are voluntary and community-driven, and do not constitute commercial support. + required: true + - label: I confirm that I have reviewed previous [issues](https://github.com/mailcow/mailcow-dockerized/issues) to ensure this matter has not already been addressed. + required: true + - label: I confirm that my environment meets all [prerequisite requirements](https://docs.mailcow.email/getstarted/prerequisite-system/) as specified in the official documentation. + required: true - type: textarea attributes: label: Description From 171c591da42a83bd9bd053ff8b1f15be1b10b231 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 01:14:23 +0200 Subject: [PATCH 18/40] Enable REDIRECT_HTTP=y by default --- generate_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_config.sh b/generate_config.sh index 9a0bd132b..3711c1138 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -218,7 +218,7 @@ HTTPS_PORT=443 HTTPS_BIND= # Redirect HTTP connections to HTTPS - y/n -HTTP_REDIRECT=n +HTTP_REDIRECT=y # ------------------------------ # Other bindings From 5f4a4fd759b0ad3671e59b092cb2a2f571c4cb53 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 01:14:33 +0200 Subject: [PATCH 19/40] Removed new lines for consistency --- generate_config.sh | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/generate_config.sh b/generate_config.sh index 3711c1138..6b193f84d 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -172,7 +172,6 @@ cat << EOF > mailcow.conf # example.org is _not_ a valid hostname, use a fqdn here. # Default admin user is "admin" # Default password is "moohoo" - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} # Password hash algorithm @@ -183,19 +182,16 @@ MAILCOW_PASS_SCHEME=BLF-CRYPT # ------------------------------ # SQL database configuration # ------------------------------ - DBNAME=mailcow DBUSER=mailcow # Please use long, random alphanumeric strings (A-Za-z0-9) - DBPASS=$(LC_ALL=C /dev/null | head -c 28) DBROOT=$(LC_ALL=C /dev/null | head -c 28) # ------------------------------ # REDIS configuration # ------------------------------ - REDISPASS=$(LC_ALL=C /dev/null | head -c 28) # ------------------------------ @@ -210,7 +206,6 @@ REDISPASS=$(LC_ALL=C /dev/null | head -c 28) # Example: HTTP_BIND=1.2.3.4 # For IPv4 leave it as it is: HTTP_BIND= & HTTPS_PORT= # For IPv6 see https://docs.mailcow.email/post_installation/firststeps-ip_bindings/ - HTTP_PORT=80 HTTP_BIND= @@ -225,7 +220,6 @@ HTTP_REDIRECT=y # ------------------------------ # You should leave that alone # Format: 11.22.33.44:25 or 12.34.56.78:465 etc. - SMTP_PORT=25 SMTPS_PORT=465 SUBMISSION_PORT=587 @@ -241,12 +235,10 @@ REDIS_PORT=127.0.0.1:7654 # Your timezone # See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of timezones # Use the column named 'TZ identifier' + pay attention for the column named 'Notes' - TZ=${MAILCOW_TZ} # Fixed project name # Please use lowercase letters only - COMPOSE_PROJECT_NAME=mailcowdockerized # Used Docker Compose version @@ -254,7 +246,6 @@ COMPOSE_PROJECT_NAME=mailcowdockerized # For more informations take a look at the mailcow docs regarding the configuration options. # Normally this should be untouched but if you decided to use either of those you can switch it manually here. # Please be aware that at least one of those variants should be installed on your machine or mailcow will fail. - DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION} # Set this to "allow" to enable the anyone pseudo user. Disabled by default. @@ -267,7 +258,6 @@ ACL_ANYONE=disallow # Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring # How long should objects remain in the garbage until they are being deleted? (value in minutes) # Check interval is hourly - MAILDIR_GC_TIME=7200 # Additional SAN for the certificate @@ -282,8 +272,6 @@ MAILDIR_GC_TIME=7200 #ADDITIONAL_SAN=srv1.example.net # ...or combine wildcard and static names: #ADDITIONAL_SAN=imap.*,srv1.example.com -# - ADDITIONAL_SAN= # Obtain certificates for autodiscover.* and autoconfig.* domains. @@ -300,11 +288,9 @@ AUTODISCOVER_SAN=y # If the server name does not match a known site, Nginx decides by best-guess and may redirect users to the wrong web root. # You can understand this as server_name directive in Nginx. # Comma separated list without spaces! Example: ADDITIONAL_SERVER_NAMES=a.b.c,d.e.f - ADDITIONAL_SERVER_NAMES= # Skip running ACME (acme-mailcow, Let's Encrypt certs) - y/n - SKIP_LETS_ENCRYPT=n # Create seperate certificates for all domains - y/n @@ -313,52 +299,41 @@ SKIP_LETS_ENCRYPT=n ENABLE_SSL_SNI=n # Skip IPv4 check in ACME container - y/n - SKIP_IP_CHECK=n # Skip HTTP verification in ACME container - y/n - SKIP_HTTP_VERIFICATION=n # Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n - SKIP_UNBOUND_HEALTHCHECK=n # Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n - SKIP_CLAMD=${SKIP_CLAMD} # Skip Olefy (olefy-mailcow) anti-virus for Office documents (Rspamd will auto-detect a missing Olefy container) - y/n - SKIP_OLEFY=n # Skip SOGo: Will disable SOGo integration and therefore webmail, DAV protocols and ActiveSync support (experimental, unsupported, not fully implemented) - y/n - SKIP_SOGO=n # Skip FTS (Fulltext Search) for Dovecot on low-memory, low-threaded systems or if you simply want to disable it. # Dovecot inside mailcow use Flatcurve as FTS Backend. - SKIP_FTS=n # Dovecot Indexing (FTS) Process maximum heap size in MB, there is no recommendation, please see Dovecot docs. # Flatcurve (Xapian backend) is used as the FTS Indexer. It is supposed to be efficient in CPU and RAM consumption. # However: Please always monitor your Resource consumption! - FTS_HEAP=128 # Controls how many processes the Dovecot indexing process can spawn at max. # Too many indexing processes can use a lot of CPU and Disk I/O. # Please visit: https://doc.dovecot.org/configuration_manual/service_configuration/#indexer-worker for more informations - FTS_PROCS=1 # Allow admins to log into SOGo as email user (without any password) - ALLOW_ADMIN_EMAIL_LOGIN=n # Enable watchdog (watchdog-mailcow) to restart unhealthy containers - USE_WATCHDOG=y # Send watchdog notifications by mail (sent from watchdog@MAILCOW_HOSTNAME) @@ -367,7 +342,6 @@ USE_WATCHDOG=y # 2. Mails are sent unsigned (no DKIM) # 3. If you use DMARC, create a separate DMARC policy ("v=DMARC1; p=none;" in _dmarc.MAILCOW_HOSTNAME) # Multiple rcpts allowed, NO quotation marks, NO spaces - #WATCHDOG_NOTIFY_EMAIL=a@example.com,b@example.com,c@example.com #WATCHDOG_NOTIFY_EMAIL= @@ -398,25 +372,20 @@ WATCHDOG_EXTERNAL_CHECKS=n WATCHDOG_VERBOSE=n # Max log lines per service to keep in Redis logs - LOG_LINES=9999 # Internal IPv4 /24 subnet, format n.n.n (expands to n.n.n.0/24) # Use private IPv4 addresses only, see https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses - IPV4_NETWORK=172.22.1 # Internal IPv6 subnet in fc00::/7 # Use private IPv6 addresses only, see https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses - IPV6_NETWORK=fd4d:6169:6c63:6f77::/64 # Use this IPv4 for outgoing connections (SNAT) - #SNAT_TO_SOURCE= # Use this IPv6 for outgoing connections (SNAT) - #SNAT6_TO_SOURCE= # Create or override an API key for the web UI @@ -545,4 +514,4 @@ else echo ' $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php echo '?>' >> data/web/inc/app_info.inc.php echo -e "\e[33mCannot determine current git repository version...\e[0m" -fi \ No newline at end of file +fi From 8978a9ad7903b42533d3bfd2e9a1e9f273026f10 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 02:13:22 +0200 Subject: [PATCH 20/40] Remove debug console.log() lines --- data/web/js/site/admin.js | 1 - data/web/js/site/dashboard.js | 11 ++--------- data/web/js/site/edit.js | 1 - data/web/js/site/user.js | 5 ----- 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js index f4258ff48..009a27fbb 100644 --- a/data/web/js/site/admin.js +++ b/data/web/js/site/admin.js @@ -715,7 +715,6 @@ jQuery(function($){ $('.app_hide').off('change'); $('.app_hide').on('change', function (e) { var value = $(this).is(':checked') ? '1' : '0'; - console.log(value) $(this).parent().children(':first-child').val(value); }) } diff --git a/data/web/js/site/dashboard.js b/data/web/js/site/dashboard.js index 182a09a5b..32c04b518 100644 --- a/data/web/js/site/dashboard.js +++ b/data/web/js/site/dashboard.js @@ -47,8 +47,6 @@ $(document).ready(function() { window.fetch("/api/v1/get/status/host/ip", { method:'GET', cache:'no-cache' }).then(function(response) { return response.json(); }).then(function(data) { - console.log(data); - // display host ips if (data.ipv4) $("#host_ipv4").text(data.ipv4); @@ -1007,7 +1005,7 @@ jQuery(function($){ "data-order": cellData.sortBy, "data-sort": cellData.sortBy }); - }, + }, render: function (data) { return data.value; } @@ -1032,7 +1030,7 @@ jQuery(function($){ "data-order": cellData.sortBy, "data-sort": cellData.sortBy }); - }, + }, render: function (data) { return data.value; } @@ -1347,9 +1345,6 @@ function update_stats(timeout=5){ window.fetch("/api/v1/get/status/host", {method:'GET',cache:'no-cache'}).then(function(response) { return response.json(); - }).then(function(data) { - console.log(data); - if (data){ // display table data $("#host_date").text(data.system_time); @@ -1399,8 +1394,6 @@ function update_container_stats(timeout=5){ var diskIOCtx = Chart.getChart(container + "_DiskIOChart"); var netIOCtx = Chart.getChart(container + "_NetIOChart"); - console.log(container); - console.log(data); prev_stats = null; if (data.length >= 2){ prev_stats = data[data.length -2]; diff --git a/data/web/js/site/edit.js b/data/web/js/site/edit.js index f9fe707c6..308ec8c13 100644 --- a/data/web/js/site/edit.js +++ b/data/web/js/site/edit.js @@ -66,7 +66,6 @@ $(document).ready(function() { // 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(""); diff --git a/data/web/js/site/user.js b/data/web/js/site/user.js index 1d227469a..d7625151d 100644 --- a/data/web/js/site/user.js +++ b/data/web/js/site/user.js @@ -169,7 +169,6 @@ jQuery(function($){ type: "GET", url: "/api/v1/get/time_limited_aliases", dataSrc: function(data){ - console.log(data); $.each(data, function (i, item) { if (acl_data.spam_alias === 1) { item.action = '
' + @@ -262,7 +261,6 @@ jQuery(function($){ type: "GET", url: '/api/v1/get/syncjobs/' + encodeURIComponent(mailcow_cc_username) + '/no_log', dataSrc: function(data){ - console.log(data); $.each(data, function (i, item) { item.user1 = escapeHtml(item.user1); item.log = '' + lang.open_logs + '' @@ -418,7 +416,6 @@ jQuery(function($){ type: "GET", url: '/api/v1/get/app-passwd/all', dataSrc: function(data){ - console.log(data); $.each(data, function (i, item) { item.name = escapeHtml(item.name) item.protocols = [] @@ -514,7 +511,6 @@ jQuery(function($){ type: "GET", url: '/api/v1/get/policy_wl_mailbox', dataSrc: function(data){ - console.log(data); $.each(data, function (i, item) { if (validateEmail(item.object)) { item.chkbox = ''; @@ -585,7 +581,6 @@ jQuery(function($){ type: "GET", url: '/api/v1/get/policy_bl_mailbox', dataSrc: function(data){ - console.log(data); $.each(data, function (i, item) { if (validateEmail(item.object)) { item.chkbox = ''; From 5b1b49a418a711c2be040b191a4b91f7be4e7b54 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 02:37:02 +0200 Subject: [PATCH 21/40] Fixed password complexity check for AppPasswords --- data/web/inc/functions.app_passwd.inc.php | 48 +++++------------------ 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/data/web/inc/functions.app_passwd.inc.php b/data/web/inc/functions.app_passwd.inc.php index b493fc914..161d4d1cd 100644 --- a/data/web/inc/functions.app_passwd.inc.php +++ b/data/web/inc/functions.app_passwd.inc.php @@ -1,7 +1,7 @@ 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'password_complexity' - ); - return false; - } - if ($password != $password2) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data_log), - 'msg' => 'password_mismatch' - ); + if (password_check($password, $password2) !== true) { return false; } $password_hashed = hash_password($password); @@ -88,7 +75,7 @@ function app_passwd($_action, $_data = null) { 'log' => array(__FUNCTION__, $_action, $_data_log), 'msg' => 'app_passwd_added' ); - break; + break; case 'edit': $ids = (array)$_data['id']; foreach ($ids as $id) { @@ -126,20 +113,7 @@ function app_passwd($_action, $_data = null) { } $app_name = htmlspecialchars(trim($app_name)); if (!empty($password) && !empty($password2)) { - if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'password_complexity' - ); - continue; - } - if ($password != $password2) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'password_mismatch' - ); + if (password_check($password, $password2) !== true) { continue; } $password_hashed = hash_password($password); @@ -182,7 +156,7 @@ function app_passwd($_action, $_data = null) { 'msg' => array('object_modified', htmlspecialchars(implode(', ', $ids))) ); } - break; + break; case 'delete': $ids = (array)$_data['id']; foreach ($ids as $id) { @@ -213,19 +187,17 @@ function app_passwd($_action, $_data = null) { 'msg' => array('app_passwd_removed', htmlspecialchars($id)) ); } - break; + break; case 'get': $app_passwds = array(); $stmt = $pdo->prepare("SELECT `id`, `name` FROM `app_passwd` WHERE `mailbox` = :username"); $stmt->execute(array(':username' => $username)); $app_passwds = $stmt->fetchAll(PDO::FETCH_ASSOC); return $app_passwds; - break; + break; case 'details': $app_passwd_data = array(); - $stmt = $pdo->prepare("SELECT * - FROM `app_passwd` - WHERE `id` = :id"); + $stmt = $pdo->prepare("SELECT * FROM `app_passwd` WHERE `id` = :id"); $stmt->execute(array(':id' => $_data)); $app_passwd_data = $stmt->fetch(PDO::FETCH_ASSOC); if (empty($app_passwd_data)) { @@ -237,6 +209,6 @@ function app_passwd($_action, $_data = null) { } $app_passwd_data['name'] = htmlspecialchars(trim($app_passwd_data['name'])); return $app_passwd_data; - break; + break; } } From ce219668cf066309cc7978613975eb3189f23cc2 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 03:37:49 +0200 Subject: [PATCH 22/40] Rename AppPasswds fields uniquely like 'add' --- data/web/inc/functions.app_passwd.inc.php | 4 ++-- data/web/templates/edit/app-passwd.twig | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/web/inc/functions.app_passwd.inc.php b/data/web/inc/functions.app_passwd.inc.php index b493fc914..51b7c33b3 100644 --- a/data/web/inc/functions.app_passwd.inc.php +++ b/data/web/inc/functions.app_passwd.inc.php @@ -95,8 +95,8 @@ function app_passwd($_action, $_data = null) { $is_now = app_passwd('details', $id); if (!empty($is_now)) { $app_name = (!empty($_data['app_name'])) ? $_data['app_name'] : $is_now['name']; - $password = (!empty($_data['password'])) ? $_data['password'] : null; - $password2 = (!empty($_data['password2'])) ? $_data['password2'] : null; + $password = (!empty($_data['app_passwd'])) ? $_data['app_passwd'] : null; + $password2 = (!empty($_data['app_passwd2'])) ? $_data['app_passwd2'] : null; if (isset($_data['protocols'])) { $protocols = (array)$_data['protocols']; $imap_access = (in_array('imap_access', $protocols)) ? 1 : 0; diff --git a/data/web/templates/edit/app-passwd.twig b/data/web/templates/edit/app-passwd.twig index 46dc648db..efab8876b 100644 --- a/data/web/templates/edit/app-passwd.twig +++ b/data/web/templates/edit/app-passwd.twig @@ -13,15 +13,15 @@
- +
- +
- +
- +
From 5c5287ca21da04d9efa5058b200aa3df6aeb8305 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 04:04:45 +0200 Subject: [PATCH 23/40] Fixed wrong footer escaping --- data/web/js/build/013-mailcow.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/web/js/build/013-mailcow.js b/data/web/js/build/013-mailcow.js index f09098310..53e48d60a 100644 --- a/data/web/js/build/013-mailcow.js +++ b/data/web/js/build/013-mailcow.js @@ -22,8 +22,8 @@ $(document).ready(function() { $.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}}); } - $(".generate_password").click(async function( event ) { - try { + $(".generate_password").click(async function( event ) { + try { var password_policy = await window.fetch("/api/v1/get/passwordpolicy", { method:'GET', cache:'no-cache' }); var password_policy = await password_policy.json(); random_passwd_length = password_policy.length; @@ -48,7 +48,7 @@ $(document).ready(function() { }) } $(".rot-enc").html(function(){ - return str_rot13($(this).html()) + return str_rot13($(this).text()) }); // https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate function shake(div,interval,distance,times) { @@ -125,7 +125,7 @@ $(document).ready(function() { } }); })(); - + // responsive tabs, scroll to opened tab $(document).on("shown.bs.collapse shown.bs.tab", function (e) { var target = $(e.target); @@ -409,4 +409,4 @@ function copyToClipboard(id) { // only works with https connections navigator.clipboard.writeText(copyText.value); mailcow_alert_box(lang.copy_to_clipboard, "success"); -} \ No newline at end of file +} From 8abe74a5622a71d5ba2691e0e7c0d1067dea3ccc Mon Sep 17 00:00:00 2001 From: milkmaker Date: Fri, 26 Sep 2025 10:57:32 +0200 Subject: [PATCH 24/40] [Web] Updated lang.si-si.json (#6785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matjaž Tekavec --- data/web/lang/lang.si-si.json | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index 0b6626127..e54c3b11f 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -414,9 +414,9 @@ "needs_restart": "potreben je ponovni zagon" }, "danger": { - "alias_goto_identical": "Alias in goto naslov morata biti identična", - "aliasd_targetd_identical": "Alias domena ne sme biti enaka ciljni domeni: %s", - "bcc_exists": "BCC preslikava obstaja za vrsto %s", + "alias_goto_identical": "Vzdevek in ciljni naslov se ne smeta ujemati.", + "aliasd_targetd_identical": "Vzdevek domene ne sme biti enak ciljni domeni: %s", + "bcc_exists": "Za tip %s obstaja BCC preslikava %s", "dkim_domain_or_sel_exists": "DKIM ključ za \"%s\" obstaja in ne bo prepisan", "domain_quota_m_in_use": "Kvota domene mora biti večja ali enaka %s MiB", "extra_acl_invalid_domain": "Zunanji pošiljatelj \"%s\" uporablja neveljavno domeno", @@ -425,42 +425,42 @@ "invalid_nexthop": "Oblika naslednjega skoka ni veljavna", "invalid_nexthop_authenticated": "Naslednji skok obstaja z drugačnimi poverilnicami. Prosim najprej posodobite obstoječe poverilnice za ta naslednji skok.", "demo_mode_enabled": "Demo način je omogočen", - "access_denied": "Dostop zavrnjen ali pa so podatki obrazca napačni", - "alias_domain_invalid": "Alias domena %s ni veljavna", - "alias_empty": "Alias naslov ne sme biti prazen", - "alias_invalid": "Alias naslov %s ni veljaven", - "aliases_in_use": "Max. aliasov mora biti večje ali enako %d", - "app_name_empty": "Naziv aplikacije ne more biti prazno", - "app_passwd_id_invalid": "ID gesla aplikacije %s je neveljaven", - "bcc_empty": "BCC cilj ne more biti prazen", - "bcc_must_be_email": "BCC cilj %s ni veljaven e-poštni naslov", + "access_denied": "Dostop zavrnjen ali neveljavni podatki obrazca", + "alias_domain_invalid": "Vzdevek domene %s ni veljaven", + "alias_empty": "Naslov vzdevka ne sme biti prazen", + "alias_invalid": "Naslov vzdevka %s ni veljaven", + "aliases_in_use": "Največje število vzdevkov mora biti večje ali enako %d", + "app_name_empty": "Ime aplikacije ne sme biti prazno", + "app_passwd_id_invalid": "ID gesla za aplikacijo %s neveljaven", + "bcc_empty": "Polje za prejemnika BCC ne sme biti prazno", + "bcc_must_be_email": "Cilj BCC %s ni veljaven e-poštni naslov", "comment_too_long": "Komentar je predolg, dovoljeno je največ 160 znakov", "defquota_empty": "Privzeta kvota na poštni predal ne more biti 0.", - "description_invalid": "Opis resursa za %s ni veljaven", + "description_invalid": "Opis vira za %s je neveljaven", "dkim_domain_or_sel_invalid": "Domena ali izbirnik DKIM ni veljaven: %s", "domain_cannot_match_hostname": "Domena se ne more ujemati z imenom gostitelja", "domain_exists": "Domena %s že obstaja", - "domain_invalid": "Manjka ali napačno ime domene", - "domain_not_empty": "Ne morem odstraniti ne-prazno domeno %s", + "domain_invalid": "Ime domene je prazno ali neveljavno", + "domain_not_empty": "Neprazne domene %s ni mogoče odstraniti", "domain_not_found": "Domene %s ni bilo mogoče najti", "extended_sender_acl_denied": "manjka ACL za določitev naslovov zunanjih pošiljateljev", "extra_acl_invalid": "Naslov zunanjega pošiljatelja \"%s\" ni veljaven", "fido2_verification_failed": "Preverjanje FIDO2 ni uspelo: %s", - "file_open_error": "Datoteka ne more biti odprta za urejanje", + "file_open_error": "Datoteke ni mogoče odpreti za pisanje", "filter_type": "Napačna vrsta filtra", - "from_invalid": "Pošiljatelj ne sme biti prazno", + "from_invalid": "Polje za pošiljatelja ne sme biti prazno", "global_filter_write_error": "Ni mogoče zapisati datoteke filtra: %s", "global_map_invalid": "ID globalne preslikave %s ni veljaven", - "goto_empty": "Alias naslov mora vsebovati vsaj en veljaven goto naslov", - "goto_invalid": "Goto naslov %s ni veljaven", + "goto_empty": "Naslov vzdevka mora vsebovati vsaj en veljaven ciljni naslov", + "goto_invalid": "Ciljni naslov %s ni veljaven", "ham_learn_error": "Napaka pri učenju Ham: %s", - "imagick_exception": "Napaka: Imagick napaka pri branju slike", + "imagick_exception": "Napaka: Izjema Imagick med branjem slike", "img_invalid": "Ni možno preveriti slikovne datoteke", "invalid_bcc_map_type": "Neveljavna vrsta preslikave BCC", "invalid_destination": "Ciljna oblika \"%s\" ni veljavna", "invalid_filter_type": "Neveljavna vrsta filtra", "invalid_host": "Naveden je neveljaven gostitelj (host): %s", - "invalid_mime_type": "Neveljaven mime type", + "invalid_mime_type": "Neveljavna vrsta MIME", "max_quota_in_use": "Kvota poštnega predala mora biti večja ali enaka %d MB", "password_complexity": "Geslo ne ustreza varnostni politiki", "pushover_credentials_missing": "Manjka Pushover token ali ključ", From 702ed85dfd0747216da1b74fb535e58f8c19ca40 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 14:41:19 +0200 Subject: [PATCH 25/40] Fixed footer escaping --- data/web/inc/header.inc.php | 6 +++++- data/web/js/build/013-mailcow.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php index 9ab2ad174..d2ce6f3d0 100644 --- a/data/web/inc/header.inc.php +++ b/data/web/inc/header.inc.php @@ -62,7 +62,11 @@ if ($app_links_processed){ } } - +// Workaround to get text with
straight to twig. +// Using "nl2br" doesn't work with Twig as it would escape everything by default. +if (isset($UI_TEXTS["ui_footer"])) { + $UI_TEXTS["ui_footer"] = nl2br($UI_TEXTS["ui_footer"]); +} $globalVariables = [ 'mailcow_hostname' => getenv('MAILCOW_HOSTNAME'), diff --git a/data/web/js/build/013-mailcow.js b/data/web/js/build/013-mailcow.js index 53e48d60a..d897f23ea 100644 --- a/data/web/js/build/013-mailcow.js +++ b/data/web/js/build/013-mailcow.js @@ -48,7 +48,11 @@ $(document).ready(function() { }) } $(".rot-enc").html(function(){ - return str_rot13($(this).text()) + footer_html = $(this).html(); + footer_html = footer_html.replace(/</g, '<').replace(/>/g, '>') + .replace(/&/g, '&').replace(/&nzc;/g, '&') + .replace(/"/g, '"').replace(/'/g, "'"); + return str_rot13(footer_html) }); // https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate function shake(div,interval,distance,times) { From d06d23bbaf528f5edfb26d32d3d693b8005fc81e Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 14:58:04 +0200 Subject: [PATCH 26/40] Fix several SQL statements --- data/conf/rspamd/dynmaps/aliasexp.php | 2 +- data/conf/rspamd/meta_exporter/pipe.php | 2 +- data/conf/rspamd/meta_exporter/pushover.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/conf/rspamd/dynmaps/aliasexp.php b/data/conf/rspamd/dynmaps/aliasexp.php index 824037cf1..814c0d38c 100644 --- a/data/conf/rspamd/dynmaps/aliasexp.php +++ b/data/conf/rspamd/dynmaps/aliasexp.php @@ -133,7 +133,7 @@ try { error_log("ALIAS EXPANDER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); $goto_branch_array = explode(',', $goto_branch); } else { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` = '1'"); $stmt->execute(array(':domain' => $parsed_goto['domain'])); $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; if ($goto_branch) { diff --git a/data/conf/rspamd/meta_exporter/pipe.php b/data/conf/rspamd/meta_exporter/pipe.php index bd5d875bd..003639b08 100644 --- a/data/conf/rspamd/meta_exporter/pipe.php +++ b/data/conf/rspamd/meta_exporter/pipe.php @@ -182,7 +182,7 @@ foreach (json_decode($rcpts, true) as $rcpt) { error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); $goto_branch_array = explode(',', $goto_branch); } else { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` = '1'"); $stmt->execute(array(':domain' => $parsed_goto['domain'])); $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; if ($goto_branch) { diff --git a/data/conf/rspamd/meta_exporter/pushover.php b/data/conf/rspamd/meta_exporter/pushover.php index af1b21ebc..efe5fdd52 100644 --- a/data/conf/rspamd/meta_exporter/pushover.php +++ b/data/conf/rspamd/meta_exporter/pushover.php @@ -167,7 +167,7 @@ foreach (json_decode($rcpts, true) as $rcpt) { error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); $goto_branch_array = explode(',', $goto_branch); } else { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` = '1'"); $stmt->execute(array(':domain' => $parsed_goto['domain'])); $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; if ($goto_branch) { From 85ca197615a490b7ad1bb2a418ad3fec2a734ef4 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 16:50:58 +0200 Subject: [PATCH 27/40] Hide relayhosts when ACL does not allow --- data/web/templates/edit/domain.twig | 4 +++- data/web/templates/edit/mailbox.twig | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 774b30996..8bd7ab253 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -58,6 +58,7 @@
+ {% if acl.domain_relayhost == '1' %}
@@ -76,6 +77,7 @@
+ {% endif %} {% if mailcow_cc_role == 'admin' %}
@@ -293,7 +295,7 @@
-
+ {% if acl.mailbox_relayhost == '1' %}
@@ -134,6 +135,7 @@ {{ lang.edit.mailbox_relayhost_info }}
+ {% endif %}
From ff43799763fd563a38585a693dda62702b97d78b Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Fri, 26 Sep 2025 17:02:22 +0200 Subject: [PATCH 28/40] Show "Never" by default if no last-modified date --- data/web/templates/edit/domain.twig | 4 ++-- data/web/templates/edit/mailbox.twig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 774b30996..dbc62a774 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -147,7 +147,7 @@
{{ lang.edit.created_on }}: {{ result.created }} - {{ lang.edit.last_modified }}: {{ result.modified }} + {{ lang.edit.last_modified }}: {{ result.modified|default(lang.user.never) }}
@@ -293,7 +293,7 @@
-